From fc69a069727475060ee6d9895ac2745b8965237f Mon Sep 17 00:00:00 2001 From: Andres Date: Sun, 30 Mar 2025 23:36:12 -0700 Subject: [PATCH] aya: fix is_probe_read_kernel_supported in aarch64 kernels 5.5 (#1235) In aarch64, with kernel 5.5, my programs that use `bpf_probe_read_user` don't work successfully because `aya` is mistakenly re-writting it `bpf_probe_read` because it falsely detects that the kernel doesn't support `bpf_probe_read_user`. I hadn't updated my `aya` version in a while, but while updating it to fix a separate issue (panics when parsing kernel versions of PVE kernels) and running my test suite I saw tests failing on aarch64 5.5 kernels. A git bisect led me to this commit: 942ea51906fea4e3152e1bd3ef5832bc0df5b205 and further investigation in the difference of the new and old assembly showed that the only difference was subtracting 8 vs adding -8. When I put it back as adding 8 (but without handwritten assembly) then things work as expected. Since it used to be `BPF_ADD` and the commit that changed it was just about no longer handwriting assembly without any reason for the switch to `BPF_SUB` putting it back as `BPF_ADD` seems reasonable. When using `BPF_SUB` 8, the handwritten program in this function returns a permission error which is treated by this function as `bpf_probe_read_kernel` not being supported when it is but for some reason `BPF_SUB` is not. My guess is that it might be an early verifier error but I am not 100% sure as I thought verifier errors are normally `EINVAL` not `EPERM` but I have a vague memory of seeing `EPERM` in the past for errors that happened very early in the verifier. Fixes: #1233 --- aya/src/sys/bpf.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index 3d6d419f..7c658a00 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -16,13 +16,13 @@ use aya_obj::{ }, generated::{ BPF_ALU64, BPF_CALL, BPF_DW, BPF_EXIT, BPF_F_REPLACE, BPF_IMM, BPF_JMP, BPF_K, BPF_LD, - BPF_MEM, BPF_MOV, BPF_PSEUDO_MAP_VALUE, BPF_ST, BPF_SUB, BPF_X, bpf_attach_type, bpf_attr, + BPF_MEM, BPF_MOV, BPF_PSEUDO_MAP_VALUE, BPF_ST, BPF_X, bpf_attach_type, bpf_attr, bpf_btf_info, bpf_cmd, bpf_func_id::*, bpf_insn, bpf_link_info, bpf_map_info, bpf_map_type, bpf_prog_info, bpf_prog_type, bpf_stats_type, }, maps::{LegacyMap, bpf_map_def}, }; -use libc::{ENOENT, ENOSPC}; +use libc::{BPF_ADD, ENOENT, ENOSPC}; use crate::{ Btf, FEATURES, Pod, VerifierLogLevel, @@ -781,13 +781,13 @@ pub(crate) fn is_probe_read_kernel_supported() -> bool { let u = unsafe { &mut attr.__bindgen_anon_3 }; let mov64_reg = (BPF_ALU64 | BPF_MOV | BPF_X) as _; - let sub64_imm = (BPF_ALU64 | BPF_SUB | BPF_K) as _; + let add64_imm = (BPF_ALU64 | BPF_ADD | BPF_K) as _; let mov64_imm = (BPF_ALU64 | BPF_MOV | BPF_K) as _; let call = (BPF_JMP | BPF_CALL) as _; let exit = (BPF_JMP | BPF_EXIT) as _; let insns = [ new_insn(mov64_reg, 1, 10, 0, 0), - new_insn(sub64_imm, 1, 0, 0, 8), + new_insn(add64_imm, 1, 0, 0, -8), new_insn(mov64_imm, 2, 0, 0, 8), new_insn(mov64_imm, 3, 0, 0, 0), new_insn(call, 0, 0, 0, BPF_FUNC_probe_read_kernel as _),