Messages in this thread Patch in this message | | | Date | Fri, 10 Dec 2021 17:16:24 +0100 | From | Peter Zijlstra <> | Subject | [PATCH v2 6/9] refcount: Fix refcount_dec_not_one() |
| |
refcount_dec_not_one() misbehaves when racing against the other refcount ops, notably it directly compares against REFCOUNT_SATURATED, even though, through aforementioned races, the value might be slightly off.
Additionally, when refcount_dec_not_one() is used to decrement zero; which is valid, because 0 is not one, then it behaves differently from the other refcount_dec*() functions in that it doesn't call refcount_warn_saturate().
In order to allow some fuzz around the corners of the positive range, test for saturation slightly differently.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> --- lib/refcount.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
--- a/lib/refcount.c +++ b/lib/refcount.c @@ -81,7 +81,8 @@ bool refcount_dec_not_one(refcount_t *r) unsigned int new, val = atomic_read(&r->refs); do { - if (unlikely(val == REFCOUNT_SATURATED)) + /* SAT+SAT/2 < val < SAT-SAT/2 */ + if (unlikely(val - (REFCOUNT_SATURATED + REFCOUNT_SATURATED/2) < -REFCOUNT_SATURATED)) return true; if (val == 1) @@ -89,7 +90,7 @@ bool refcount_dec_not_one(refcount_t *r) new = val - 1; if (new > val) { - WARN_ONCE(new > val, "refcount_t: underflow; use-after-free.\n"); + refcount_warn_saturate(r, REFCOUNT_SUB_UAF); return true; }
| |