aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorPetr Pavlu2024-07-17 15:00:23 +0200
committerKees Cook2024-08-05 14:34:23 -0700
commitf91f7ac900e7342e0fd66093dfbf7cb8cb585a99 (patch)
tree126191748ddf797d75e0ad3582f64b991295f29a /include
parentde9c2c66ad8e787abec7c9d7eff4f8c3cdd28aed (diff)
refcount: Report UAF for refcount_sub_and_test(0) when counter==0
When a reference counter is at zero and refcount_sub_and_test() is invoked to subtract zero, the function accepts this request without any warning and returns true. This behavior does not seem ideal because the counter being already at zero indicates a use-after-free. Furthermore, returning true by refcount_sub_and_test() in this case potentially results in a double-free done by its caller. Modify the underlying function __refcount_sub_and_test() to warn about this case as a use-after-free and have it return false to avoid the potential double-free. Signed-off-by: Petr Pavlu <petr.pavlu@suse.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/r/20240717130023.5675-1-petr.pavlu@suse.com Signed-off-by: Kees Cook <kees@kernel.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/refcount.h4
1 files changed, 2 insertions, 2 deletions
diff --git a/include/linux/refcount.h b/include/linux/refcount.h
index 59b3b752394d..35f039ecb272 100644
--- a/include/linux/refcount.h
+++ b/include/linux/refcount.h
@@ -266,12 +266,12 @@ bool __refcount_sub_and_test(int i, refcount_t *r, int *oldp)
if (oldp)
*oldp = old;
- if (old == i) {
+ if (old > 0 && old == i) {
smp_acquire__after_ctrl_dep();
return true;
}
- if (unlikely(old < 0 || old - i < 0))
+ if (unlikely(old <= 0 || old - i < 0))
refcount_warn_saturate(r, REFCOUNT_SUB_UAF);
return false;