diff options
| author | Benjamin Marzinski <bmarzins@redhat.com> | 2026-07-06 16:23:24 -0400 |
|---|---|---|
| committer | Yury Norov <ynorov@nvidia.com> | 2026-07-22 15:38:37 -0400 |
| commit | 1c61b0a6e5c472737619f74f79c390363ee258df (patch) | |
| tree | 3c75002308997ff5fc7937a20029b9bd3669a572 /include/asm-generic | |
| parent | df81d444dc740778f7c7a2d4c3500136851375aa (diff) | |
| download | linux-next-1c61b0a6e5c472737619f74f79c390363ee258df.tar.gz linux-next-1c61b0a6e5c472737619f74f79c390363ee258df.zip | |
bitops: make the *_bit_le functions use unsigned long
The *_bit_le functions use a signed integer for the bit number.
However, the *_bit functions can use an unsigned long. This causes
problems if there is a large bitmap and a bit number > 0x80000000 is
passed in. Since that is a negative int, it will get sign extended to a
long when getting passed to the *_bit function, turning it into a huge
bit number. This usually ends up with the memory address wrapping around
and the function accessing memory before the start of the bitmap.
Avoid this by making the *_bit_le functions take an unsigned long.
This can be triggered by faking an almost 4TB dm-mirror device, which
uses bitmaps to track the mirror regions:
$ dmsetup create bigzero --table '0 8589934590 zero'
$ dmsetup create mymirror --table '0 8589934590 mirror core 2 2 nosync 2 /dev/mapper/bigzero 0 /dev/mapper/bigzero 0'
This will access memory before the start of the sync_bits bitmap, and
likely hit the guard page of the previously allocated clean_bits bitmap,
causing a kernel panic with the old code.
I looked and didn't see any crazy code using the signed int to
intentionally try and access bits before some address within the bitmap.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Yury Norov <ynorov@nvidia.com>
Diffstat (limited to 'include/asm-generic')
| -rw-r--r-- | include/asm-generic/bitops/le.h | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/include/asm-generic/bitops/le.h b/include/asm-generic/bitops/le.h index d51beff60375..e3b0da9a25f1 100644 --- a/include/asm-generic/bitops/le.h +++ b/include/asm-generic/bitops/le.h @@ -16,47 +16,47 @@ #endif -static inline int test_bit_le(int nr, const void *addr) +static inline int test_bit_le(unsigned long nr, const void *addr) { return test_bit(nr ^ BITOP_LE_SWIZZLE, addr); } -static inline void set_bit_le(int nr, void *addr) +static inline void set_bit_le(unsigned long nr, void *addr) { set_bit(nr ^ BITOP_LE_SWIZZLE, addr); } -static inline void clear_bit_le(int nr, void *addr) +static inline void clear_bit_le(unsigned long nr, void *addr) { clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); } -static inline void __set_bit_le(int nr, void *addr) +static inline void __set_bit_le(unsigned long nr, void *addr) { __set_bit(nr ^ BITOP_LE_SWIZZLE, addr); } -static inline void __clear_bit_le(int nr, void *addr) +static inline void __clear_bit_le(unsigned long nr, void *addr) { __clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); } -static inline int test_and_set_bit_le(int nr, void *addr) +static inline int test_and_set_bit_le(unsigned long nr, void *addr) { return test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr); } -static inline int test_and_clear_bit_le(int nr, void *addr) +static inline int test_and_clear_bit_le(unsigned long nr, void *addr) { return test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); } -static inline int __test_and_set_bit_le(int nr, void *addr) +static inline int __test_and_set_bit_le(unsigned long nr, void *addr) { return __test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr); } -static inline int __test_and_clear_bit_le(int nr, void *addr) +static inline int __test_and_clear_bit_le(unsigned long nr, void *addr) { return __test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); } |
