Skip to content

Commit 23e6b16

Browse files
willdeaconIngo Molnar
authored andcommitted
locking/refcount: Define constants for saturation and max refcount values
The REFCOUNT_FULL implementation uses a different saturation point than the x86 implementation, which means that the shared refcount code in lib/refcount.c (e.g. refcount_dec_not_one()) needs to be aware of the difference. Rather than duplicate the definitions from the lkdtm driver, instead move them into <linux/refcount.h> and update all references accordingly. Signed-off-by: Will Deacon <[email protected]> Reviewed-by: Ard Biesheuvel <[email protected]> Reviewed-by: Kees Cook <[email protected]> Tested-by: Hanjun Guo <[email protected]> Cc: Ard Biesheuvel <[email protected]> Cc: Elena Reshetova <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 3ef240e commit 23e6b16

File tree

3 files changed

+29
-26
lines changed

3 files changed

+29
-26
lines changed

drivers/misc/lkdtm/refcount.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,6 @@
66
#include "lkdtm.h"
77
#include <linux/refcount.h>
88

9-
#ifdef CONFIG_REFCOUNT_FULL
10-
#define REFCOUNT_MAX (UINT_MAX - 1)
11-
#define REFCOUNT_SATURATED UINT_MAX
12-
#else
13-
#define REFCOUNT_MAX INT_MAX
14-
#define REFCOUNT_SATURATED (INT_MIN / 2)
15-
#endif
16-
179
static void overflow_check(refcount_t *ref)
1810
{
1911
switch (refcount_read(ref)) {

include/linux/refcount.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <linux/atomic.h>
66
#include <linux/compiler.h>
7+
#include <linux/limits.h>
78
#include <linux/spinlock_types.h>
89

910
struct mutex;
@@ -12,7 +13,7 @@ struct mutex;
1213
* struct refcount_t - variant of atomic_t specialized for reference counts
1314
* @refs: atomic_t counter field
1415
*
15-
* The counter saturates at UINT_MAX and will not move once
16+
* The counter saturates at REFCOUNT_SATURATED and will not move once
1617
* there. This avoids wrapping the counter and causing 'spurious'
1718
* use-after-free bugs.
1819
*/
@@ -56,6 +57,9 @@ extern void refcount_dec_checked(refcount_t *r);
5657

5758
#ifdef CONFIG_REFCOUNT_FULL
5859

60+
#define REFCOUNT_MAX (UINT_MAX - 1)
61+
#define REFCOUNT_SATURATED UINT_MAX
62+
5963
#define refcount_add_not_zero refcount_add_not_zero_checked
6064
#define refcount_add refcount_add_checked
6165

@@ -68,6 +72,10 @@ extern void refcount_dec_checked(refcount_t *r);
6872
#define refcount_dec refcount_dec_checked
6973

7074
#else
75+
76+
#define REFCOUNT_MAX INT_MAX
77+
#define REFCOUNT_SATURATED (INT_MIN / 2)
78+
7179
# ifdef CONFIG_ARCH_HAS_REFCOUNT
7280
# include <asm/refcount.h>
7381
# else

lib/refcount.c

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
* The interface matches the atomic_t interface (to aid in porting) but only
66
* provides the few functions one should use for reference counting.
77
*
8-
* It differs in that the counter saturates at UINT_MAX and will not move once
9-
* there. This avoids wrapping the counter and causing 'spurious'
8+
* It differs in that the counter saturates at REFCOUNT_SATURATED and will not
9+
* move once there. This avoids wrapping the counter and causing 'spurious'
1010
* use-after-free issues.
1111
*
1212
* Memory ordering rules are slightly relaxed wrt regular atomic_t functions
@@ -48,7 +48,7 @@
4848
* @i: the value to add to the refcount
4949
* @r: the refcount
5050
*
51-
* Will saturate at UINT_MAX and WARN.
51+
* Will saturate at REFCOUNT_SATURATED and WARN.
5252
*
5353
* Provides no memory ordering, it is assumed the caller has guaranteed the
5454
* object memory to be stable (RCU, etc.). It does provide a control dependency
@@ -69,16 +69,17 @@ bool refcount_add_not_zero_checked(unsigned int i, refcount_t *r)
6969
if (!val)
7070
return false;
7171

72-
if (unlikely(val == UINT_MAX))
72+
if (unlikely(val == REFCOUNT_SATURATED))
7373
return true;
7474

7575
new = val + i;
7676
if (new < val)
77-
new = UINT_MAX;
77+
new = REFCOUNT_SATURATED;
7878

7979
} while (!atomic_try_cmpxchg_relaxed(&r->refs, &val, new));
8080

81-
WARN_ONCE(new == UINT_MAX, "refcount_t: saturated; leaking memory.\n");
81+
WARN_ONCE(new == REFCOUNT_SATURATED,
82+
"refcount_t: saturated; leaking memory.\n");
8283

8384
return true;
8485
}
@@ -89,7 +90,7 @@ EXPORT_SYMBOL(refcount_add_not_zero_checked);
8990
* @i: the value to add to the refcount
9091
* @r: the refcount
9192
*
92-
* Similar to atomic_add(), but will saturate at UINT_MAX and WARN.
93+
* Similar to atomic_add(), but will saturate at REFCOUNT_SATURATED and WARN.
9394
*
9495
* Provides no memory ordering, it is assumed the caller has guaranteed the
9596
* object memory to be stable (RCU, etc.). It does provide a control dependency
@@ -110,7 +111,8 @@ EXPORT_SYMBOL(refcount_add_checked);
110111
* refcount_inc_not_zero_checked - increment a refcount unless it is 0
111112
* @r: the refcount to increment
112113
*
113-
* Similar to atomic_inc_not_zero(), but will saturate at UINT_MAX and WARN.
114+
* Similar to atomic_inc_not_zero(), but will saturate at REFCOUNT_SATURATED
115+
* and WARN.
114116
*
115117
* Provides no memory ordering, it is assumed the caller has guaranteed the
116118
* object memory to be stable (RCU, etc.). It does provide a control dependency
@@ -133,7 +135,8 @@ bool refcount_inc_not_zero_checked(refcount_t *r)
133135

134136
} while (!atomic_try_cmpxchg_relaxed(&r->refs, &val, new));
135137

136-
WARN_ONCE(new == UINT_MAX, "refcount_t: saturated; leaking memory.\n");
138+
WARN_ONCE(new == REFCOUNT_SATURATED,
139+
"refcount_t: saturated; leaking memory.\n");
137140

138141
return true;
139142
}
@@ -143,7 +146,7 @@ EXPORT_SYMBOL(refcount_inc_not_zero_checked);
143146
* refcount_inc_checked - increment a refcount
144147
* @r: the refcount to increment
145148
*
146-
* Similar to atomic_inc(), but will saturate at UINT_MAX and WARN.
149+
* Similar to atomic_inc(), but will saturate at REFCOUNT_SATURATED and WARN.
147150
*
148151
* Provides no memory ordering, it is assumed the caller already has a
149152
* reference on the object.
@@ -164,7 +167,7 @@ EXPORT_SYMBOL(refcount_inc_checked);
164167
*
165168
* Similar to atomic_dec_and_test(), but it will WARN, return false and
166169
* ultimately leak on underflow and will fail to decrement when saturated
167-
* at UINT_MAX.
170+
* at REFCOUNT_SATURATED.
168171
*
169172
* Provides release memory ordering, such that prior loads and stores are done
170173
* before, and provides an acquire ordering on success such that free()
@@ -182,7 +185,7 @@ bool refcount_sub_and_test_checked(unsigned int i, refcount_t *r)
182185
unsigned int new, val = atomic_read(&r->refs);
183186

184187
do {
185-
if (unlikely(val == UINT_MAX))
188+
if (unlikely(val == REFCOUNT_SATURATED))
186189
return false;
187190

188191
new = val - i;
@@ -207,7 +210,7 @@ EXPORT_SYMBOL(refcount_sub_and_test_checked);
207210
* @r: the refcount
208211
*
209212
* Similar to atomic_dec_and_test(), it will WARN on underflow and fail to
210-
* decrement when saturated at UINT_MAX.
213+
* decrement when saturated at REFCOUNT_SATURATED.
211214
*
212215
* Provides release memory ordering, such that prior loads and stores are done
213216
* before, and provides an acquire ordering on success such that free()
@@ -226,7 +229,7 @@ EXPORT_SYMBOL(refcount_dec_and_test_checked);
226229
* @r: the refcount
227230
*
228231
* Similar to atomic_dec(), it will WARN on underflow and fail to decrement
229-
* when saturated at UINT_MAX.
232+
* when saturated at REFCOUNT_SATURATED.
230233
*
231234
* Provides release memory ordering, such that prior loads and stores are done
232235
* before.
@@ -277,7 +280,7 @@ bool refcount_dec_not_one(refcount_t *r)
277280
unsigned int new, val = atomic_read(&r->refs);
278281

279282
do {
280-
if (unlikely(val == UINT_MAX))
283+
if (unlikely(val == REFCOUNT_SATURATED))
281284
return true;
282285

283286
if (val == 1)
@@ -302,7 +305,7 @@ EXPORT_SYMBOL(refcount_dec_not_one);
302305
* @lock: the mutex to be locked
303306
*
304307
* Similar to atomic_dec_and_mutex_lock(), it will WARN on underflow and fail
305-
* to decrement when saturated at UINT_MAX.
308+
* to decrement when saturated at REFCOUNT_SATURATED.
306309
*
307310
* Provides release memory ordering, such that prior loads and stores are done
308311
* before, and provides a control dependency such that free() must come after.
@@ -333,7 +336,7 @@ EXPORT_SYMBOL(refcount_dec_and_mutex_lock);
333336
* @lock: the spinlock to be locked
334337
*
335338
* Similar to atomic_dec_and_lock(), it will WARN on underflow and fail to
336-
* decrement when saturated at UINT_MAX.
339+
* decrement when saturated at REFCOUNT_SATURATED.
337340
*
338341
* Provides release memory ordering, such that prior loads and stores are done
339342
* before, and provides a control dependency such that free() must come after.

0 commit comments

Comments
 (0)