linux/arch
Tiezhu Yang d5d83242a1 LoongArch: BPF: Sign-extend return values
[ Upstream commit 73c359d1d3 ]

(1) Description of Problem:

When testing BPF JIT with the latest compiler toolchains on LoongArch,
there exist some strange failed test cases, dmesg shows something like
this:

  # dmesg -t | grep FAIL | head -1
  ... ret -3 != -3 (0xfffffffd != 0xfffffffd)FAIL ...

(2) Steps to Reproduce:

  # echo 1 > /proc/sys/net/core/bpf_jit_enable
  # modprobe test_bpf

(3) Additional Info:

There are no failed test cases compiled with the lower version of GCC
such as 13.3.0, while the problems only appear with higher version of
GCC such as 14.2.0.

This is because the problems were hidden by the lower version of GCC due
to redundant sign extension instructions generated by compiler, but with
optimization of higher version of GCC, the sign extension instructions
have been removed.

(4) Root Cause Analysis:

The LoongArch architecture does not expose sub-registers, and hold all
32-bit values in a sign-extended format. While BPF, on the other hand,
exposes sub-registers, and use zero-extension (similar to arm64/x86).

This has led to some subtle bugs, where a BPF JITted program has not
sign-extended the a0 register (return value in LoongArch land), passed
the return value up the kernel, for example:

  | int from_bpf(void);
  |
  | long foo(void)
  | {
  |    return from_bpf();
  | }

Here, a0 would be 0xffffffff instead of the expected 0xffffffffffffffff.

Internally, the LoongArch JIT uses a5 as a dedicated register for BPF
return values. That is to say, the LoongArch BPF uses a5 for BPF return
values, which are zero-extended, whereas the LoongArch ABI uses a0 which
is sign-extended.

(5) Final Solution:

Keep a5 zero-extended, but explicitly sign-extend a0 (which is used
outside BPF land). Because libbpf currently defines the return value
of an ebpf program as a 32-bit unsigned integer, just use addi.w to
extend bit 31 into bits 63 through 32 of a5 to a0. This is similar to
commit 2f1b0d3d73 ("riscv, bpf: Sign-extend return values").

Fixes: 5dc615520c ("LoongArch: Add BPF JIT support")
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Signed-off-by: Sasha Levin <sashal@kernel.org>
History 2024-12-05 14:02:29 +01:00
..
alpha move asm/unaligned.h to linux/unaligned.h 2024-10-02 17:23:23 -04:00
arc of/fdt: add dt_phys arg to early_init_dt_scan and early_init_dt_verify 2024-12-05 14:01:32 +01:00
arm of/fdt: add dt_phys arg to early_init_dt_scan and early_init_dt_verify 2024-12-05 14:01:32 +01:00
arm64 arm64: dts: qcom: sc8180x: Add a SoC-specific compatible to cpufreq-hw 2024-12-05 14:02:16 +01:00
csky of/fdt: add dt_phys arg to early_init_dt_scan and early_init_dt_verify 2024-12-05 14:01:32 +01:00
hexagon hexagon: vdso: Fix build failure 2024-09-23 08:17:50 -07:00
loongarch LoongArch: BPF: Sign-extend return values 2024-12-05 14:02:29 +01:00
m68k m68k: coldfire/device.c: only build FEC when HW macros are defined 2024-12-05 14:02:24 +01:00
microblaze of/fdt: add dt_phys arg to early_init_dt_scan and early_init_dt_verify 2024-12-05 14:01:32 +01:00
mips of/fdt: add dt_phys arg to early_init_dt_scan and early_init_dt_verify 2024-12-05 14:01:32 +01:00
nios2 of/fdt: add dt_phys arg to early_init_dt_scan and early_init_dt_verify 2024-12-05 14:01:32 +01:00
openrisc of/fdt: add dt_phys arg to early_init_dt_scan and early_init_dt_verify 2024-12-05 14:01:32 +01:00
parisc mm: refactor arch_calc_vm_flag_bits() and arm64 MTE handling 2024-11-05 16:49:55 -08:00
powerpc powerpc/kexec: Fix return of uninitialized variable 2024-12-05 14:02:14 +01:00
riscv riscv: kvm: Fix out-of-bounds array access 2024-12-05 14:02:08 +01:00
s390 iommu/s390: Implement blocking domain 2024-12-05 14:02:03 +01:00
sh of/fdt: add dt_phys arg to early_init_dt_scan and early_init_dt_verify 2024-12-05 14:01:32 +01:00
sparc move asm/unaligned.h to linux/unaligned.h 2024-10-02 17:23:23 -04:00
um of/fdt: add dt_phys arg to early_init_dt_scan and early_init_dt_verify 2024-12-05 14:01:32 +01:00
x86 x86: fix off-by-one in access_ok() 2024-12-05 14:02:17 +01:00
xtensa of/fdt: add dt_phys arg to early_init_dt_scan and early_init_dt_verify 2024-12-05 14:01:32 +01:00
.gitignore .gitignore: prefix local generated files with a slash 2021-05-02 00:43:35 +09:00
Kconfig cfi: tweak llvm version for HAVE_CFI_ICALL_NORMALIZE_INTEGERS 2024-10-31 00:41:37 +01:00