|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH] x86/atomic: Fix UB on various atomic helpers
The atomic interface is signed. There's UB if a caller adds over INT_MAX
or subtracts below INT_MIN where the addition/subtraction is done in
C, just like in a regular int. Make the outward facing interface respect
two's complement on wraparound by round-tripping through unsigned for
arithmetic.
While at it, fix the while loop to have Xen style.
Fixes: e0efc0738163 ("atomic: replace atomic_compareandswap() with
atomic_cmpxchg()")
Fixes: c98c80084d77 ("asm/atomic.h: implement missing and add common
prototypes")
Signed-off-by: Alejandro Vallejo <alejandro.garciavallejo@xxxxxxx>
---
I'd prefer to turn this into an unsigned interface, but then some
callers would need changing in non-trivial ways.
OTOH, one could argue the atomics merely highlight the UB already
present in signed arithmetic, and thus this doesn't need fixing. I'd
prefer to remove UB where possible.
---
xen/arch/x86/include/asm/atomic.h | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/xen/arch/x86/include/asm/atomic.h
b/xen/arch/x86/include/asm/atomic.h
index ed4e09a503..8f227e0e6f 100644
--- a/xen/arch/x86/include/asm/atomic.h
+++ b/xen/arch/x86/include/asm/atomic.h
@@ -122,7 +122,7 @@ static inline void atomic_add(int i, atomic_t *v)
static inline int atomic_add_return(int i, atomic_t *v)
{
- return i + arch_fetch_and_add(&v->counter, i);
+ return (unsigned int)i + arch_fetch_and_add(&v->counter, i);
}
static inline void atomic_sub(int i, atomic_t *v)
@@ -135,7 +135,9 @@ static inline void atomic_sub(int i, atomic_t *v)
static inline int atomic_sub_return(int i, atomic_t *v)
{
- return arch_fetch_and_add(&v->counter, -i) - i;
+ unsigned int ui = i;
+
+ return arch_fetch_and_add(&v->counter, -ui) - ui;
}
static inline int atomic_sub_and_test(int i, atomic_t *v)
@@ -221,8 +223,9 @@ static inline int atomic_add_unless(atomic_t *v, int a, int
u)
int c, old;
c = atomic_read(v);
- while (c != u && (old = atomic_cmpxchg(v, c, c + a)) != c)
+ while ( c != u && (old = atomic_cmpxchg(v, c, (unsigned int)c + a)) != c )
c = old;
+
return c;
}
base-commit: 7168cc02f86fb069da6e7405afbf5c7a1c215b0d
--
2.43.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |