Loading arch/Kconfig +9 −0 Original line number Diff line number Diff line Loading @@ -890,6 +890,15 @@ config HAVE_ARCH_PREL32_RELOCATIONS architectures, and don't require runtime relocation on relocatable kernels. config PANIC_ON_REFCOUNT_ERROR bool "Kernel panic on refcount error detection" depends on REFCOUNT_FULL help If enabled, the kernel will panic when the refcount library has detected any type of error (e.g. potential use-after-free or potential memory-leaks) with an object associated with that reference counter. source "kernel/gcov/Kconfig" source "scripts/gcc-plugins/Kconfig" Loading lib/refcount.c +24 −7 Original line number Diff line number Diff line Loading @@ -40,6 +40,16 @@ #include <linux/spinlock.h> #include <linux/bug.h> #ifdef CONFIG_PANIC_ON_REFCOUNT_ERROR #define REFCOUNT_WARN_ONCE(cond, msg) \ do { \ if (cond) \ panic(msg); \ } while (0) #else #define REFCOUNT_WARN_ONCE(cond, msg) WARN_ONCE(cond, msg) #endif /* CONFIG_PANIC_ON_REFCOUNT_ERROR */ /** * refcount_add_not_zero_checked - add a value to a refcount unless it is 0 * @i: the value to add to the refcount Loading Loading @@ -75,7 +85,8 @@ bool refcount_add_not_zero_checked(unsigned int i, refcount_t *r) } while (!atomic_try_cmpxchg_relaxed(&r->refs, &val, new)); WARN_ONCE(new == UINT_MAX, "refcount_t: saturated; leaking memory.\n"); REFCOUNT_WARN_ONCE(new == UINT_MAX, "refcount_t: saturated; leaking memory.\n"); return true; } Loading @@ -99,7 +110,8 @@ EXPORT_SYMBOL(refcount_add_not_zero_checked); */ void refcount_add_checked(unsigned int i, refcount_t *r) { WARN_ONCE(!refcount_add_not_zero_checked(i, r), "refcount_t: addition on 0; use-after-free.\n"); REFCOUNT_WARN_ONCE(!refcount_add_not_zero(i, r), "refcount_t: addition on 0; use-after-free.\n"); } EXPORT_SYMBOL(refcount_add_checked); Loading Loading @@ -130,7 +142,8 @@ bool refcount_inc_not_zero_checked(refcount_t *r) } while (!atomic_try_cmpxchg_relaxed(&r->refs, &val, new)); WARN_ONCE(new == UINT_MAX, "refcount_t: saturated; leaking memory.\n"); REFCOUNT_WARN_ONCE(new == UINT_MAX, "refcount_t: saturated; leaking memory.\n"); return true; } Loading @@ -150,7 +163,8 @@ EXPORT_SYMBOL(refcount_inc_not_zero_checked); */ void refcount_inc_checked(refcount_t *r) { WARN_ONCE(!refcount_inc_not_zero_checked(r), "refcount_t: increment on 0; use-after-free.\n"); REFCOUNT_WARN_ONCE(!refcount_inc_not_zero(r), "refcount_t: increment on 0; use-after-free.\n"); } EXPORT_SYMBOL(refcount_inc_checked); Loading Loading @@ -184,7 +198,8 @@ bool refcount_sub_and_test_checked(unsigned int i, refcount_t *r) new = val - i; if (new > val) { WARN_ONCE(new > val, "refcount_t: underflow; use-after-free.\n"); REFCOUNT_WARN_ONCE(new > val, "refcount_t: underflow; use-after-free.\n"); return false; } Loading Loading @@ -225,7 +240,8 @@ EXPORT_SYMBOL(refcount_dec_and_test_checked); */ void refcount_dec_checked(refcount_t *r) { WARN_ONCE(refcount_dec_and_test_checked(r), "refcount_t: decrement hit 0; leaking memory.\n"); REFCOUNT_WARN_ONCE(refcount_dec_and_test(r), "refcount_t: decrement hit 0; leaking memory.\n"); } EXPORT_SYMBOL(refcount_dec_checked); Loading Loading @@ -277,7 +293,8 @@ 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_ONCE(new > val, "refcount_t: underflow; use-after-free.\n"); return true; } Loading Loading
arch/Kconfig +9 −0 Original line number Diff line number Diff line Loading @@ -890,6 +890,15 @@ config HAVE_ARCH_PREL32_RELOCATIONS architectures, and don't require runtime relocation on relocatable kernels. config PANIC_ON_REFCOUNT_ERROR bool "Kernel panic on refcount error detection" depends on REFCOUNT_FULL help If enabled, the kernel will panic when the refcount library has detected any type of error (e.g. potential use-after-free or potential memory-leaks) with an object associated with that reference counter. source "kernel/gcov/Kconfig" source "scripts/gcc-plugins/Kconfig" Loading
lib/refcount.c +24 −7 Original line number Diff line number Diff line Loading @@ -40,6 +40,16 @@ #include <linux/spinlock.h> #include <linux/bug.h> #ifdef CONFIG_PANIC_ON_REFCOUNT_ERROR #define REFCOUNT_WARN_ONCE(cond, msg) \ do { \ if (cond) \ panic(msg); \ } while (0) #else #define REFCOUNT_WARN_ONCE(cond, msg) WARN_ONCE(cond, msg) #endif /* CONFIG_PANIC_ON_REFCOUNT_ERROR */ /** * refcount_add_not_zero_checked - add a value to a refcount unless it is 0 * @i: the value to add to the refcount Loading Loading @@ -75,7 +85,8 @@ bool refcount_add_not_zero_checked(unsigned int i, refcount_t *r) } while (!atomic_try_cmpxchg_relaxed(&r->refs, &val, new)); WARN_ONCE(new == UINT_MAX, "refcount_t: saturated; leaking memory.\n"); REFCOUNT_WARN_ONCE(new == UINT_MAX, "refcount_t: saturated; leaking memory.\n"); return true; } Loading @@ -99,7 +110,8 @@ EXPORT_SYMBOL(refcount_add_not_zero_checked); */ void refcount_add_checked(unsigned int i, refcount_t *r) { WARN_ONCE(!refcount_add_not_zero_checked(i, r), "refcount_t: addition on 0; use-after-free.\n"); REFCOUNT_WARN_ONCE(!refcount_add_not_zero(i, r), "refcount_t: addition on 0; use-after-free.\n"); } EXPORT_SYMBOL(refcount_add_checked); Loading Loading @@ -130,7 +142,8 @@ bool refcount_inc_not_zero_checked(refcount_t *r) } while (!atomic_try_cmpxchg_relaxed(&r->refs, &val, new)); WARN_ONCE(new == UINT_MAX, "refcount_t: saturated; leaking memory.\n"); REFCOUNT_WARN_ONCE(new == UINT_MAX, "refcount_t: saturated; leaking memory.\n"); return true; } Loading @@ -150,7 +163,8 @@ EXPORT_SYMBOL(refcount_inc_not_zero_checked); */ void refcount_inc_checked(refcount_t *r) { WARN_ONCE(!refcount_inc_not_zero_checked(r), "refcount_t: increment on 0; use-after-free.\n"); REFCOUNT_WARN_ONCE(!refcount_inc_not_zero(r), "refcount_t: increment on 0; use-after-free.\n"); } EXPORT_SYMBOL(refcount_inc_checked); Loading Loading @@ -184,7 +198,8 @@ bool refcount_sub_and_test_checked(unsigned int i, refcount_t *r) new = val - i; if (new > val) { WARN_ONCE(new > val, "refcount_t: underflow; use-after-free.\n"); REFCOUNT_WARN_ONCE(new > val, "refcount_t: underflow; use-after-free.\n"); return false; } Loading Loading @@ -225,7 +240,8 @@ EXPORT_SYMBOL(refcount_dec_and_test_checked); */ void refcount_dec_checked(refcount_t *r) { WARN_ONCE(refcount_dec_and_test_checked(r), "refcount_t: decrement hit 0; leaking memory.\n"); REFCOUNT_WARN_ONCE(refcount_dec_and_test(r), "refcount_t: decrement hit 0; leaking memory.\n"); } EXPORT_SYMBOL(refcount_dec_checked); Loading Loading @@ -277,7 +293,8 @@ 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_ONCE(new > val, "refcount_t: underflow; use-after-free.\n"); return true; } Loading