]> www.infradead.org Git - linux.git/commit
bpf: Use __u64 to save the bits in bits iterator
authorHou Tao <houtao1@huawei.com>
Wed, 30 Oct 2024 10:05:15 +0000 (18:05 +0800)
committerAlexei Starovoitov <ast@kernel.org>
Wed, 30 Oct 2024 19:13:46 +0000 (12:13 -0700)
commite1339383675063ae4760d81ffe13a79981841b8d
treeda13a420a2fd5bb91b7d46d0ed04b88588c55a16
parent393397fbdcad7396639d7077c33f86169184ba99
bpf: Use __u64 to save the bits in bits iterator

On 32-bit hosts (e.g., arm32), when a bpf program passes a u64 to
bpf_iter_bits_new(), bpf_iter_bits_new() will use bits_copy to store the
content of the u64. However, bits_copy is only 4 bytes, leading to stack
corruption.

The straightforward solution would be to replace u64 with unsigned long
in bpf_iter_bits_new(). However, this introduces confusion and problems
for 32-bit hosts because the size of ulong in bpf program is 8 bytes,
but it is treated as 4-bytes after passed to bpf_iter_bits_new().

Fix it by changing the type of both bits and bit_count from unsigned
long to u64. However, the change is not enough. The main reason is that
bpf_iter_bits_next() uses find_next_bit() to find the next bit and the
pointer passed to find_next_bit() is an unsigned long pointer instead
of a u64 pointer. For 32-bit little-endian host, it is fine but it is
not the case for 32-bit big-endian host. Because under 32-bit big-endian
host, the first iterated unsigned long will be the bits 32-63 of the u64
instead of the expected bits 0-31. Therefore, in addition to changing
the type, swap the two unsigned longs within the u64 for 32-bit
big-endian host.

Signed-off-by: Hou Tao <houtao1@huawei.com>
Link: https://lore.kernel.org/r/20241030100516.3633640-5-houtao@huaweicloud.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/helpers.c