I think there is something wrong with BPF_PROBE_MEM in ___bpf_prog_run() in big-endian machine. Let's make a test and see what will happen if we want to load a 'u16' with BPF_PROBE_MEM. Let's make the src value '0x0001', the value of dest register will become 0x0001000000000000, as the value will be loaded to the first 2 byte of DST with following code: bpf_probe_read_kernel(&DST, SIZE, (const void *)(long) (SRC + insn->off)); Obviously, the value in DST is not correct. In fact, we can compare BPF_PROBE_MEM with LDX_MEM_H: DST = *(SIZE *)(unsigned long) (SRC + insn->off); If the memory load is done by LDX_MEM_H, the value in DST will be 0x1 now. And I think this error results in the test case 'test_bpf_sk_storage_map' failing: test_bpf_sk_storage_map:PASS:bpf_iter_bpf_sk_storage_map__open_and_load 0 nsec test_bpf_sk_storage_map:PASS:socket 0 nsec test_bpf_sk_storage_map:PASS:map_update 0 nsec test_bpf_sk_storage_map:PASS:socket 0 nsec test_bpf_sk_storage_map:PASS:map_update 0 nsec test_bpf_sk_storage_map:PASS:socket 0 nsec test_bpf_sk_storage_map:PASS:map_update 0 nsec test_bpf_sk_storage_map:PASS:attach_iter 0 nsec test_bpf_sk_storage_map:PASS:create_iter 0 nsec test_bpf_sk_storage_map:PASS:read 0 nsec test_bpf_sk_storage_map:FAIL:ipv6_sk_count got 0 expected 3 $10/26 bpf_iter/bpf_sk_storage_map:FAIL The code of the test case is simply, it will load sk->sk_family to the register with BPF_PROBE_MEM and check if it is AF_INET6. With this patch, now the test case 'bpf_iter' can pass: $10 bpf_iter:OK
Showing the changes to kernel (1 of 1 file). Show all
Unified · Split
| @@ -1953,6 +1953,11 @@ out: · 1952 unmodified lines | ||
| 1953 | 1953 | CONT; \ |
| 1954 | 1954 | LDX_MEM_##SIZEOP: \ |
| 1955 | 1955 | DST = *(SIZE *)(unsigned long) (SRC + insn->off); \ |
| 1956 | + CONT; \ | |
| 1957 | + LDX_PROBE_MEM_##SIZEOP: \ | |
| 1958 | + bpf_probe_read_kernel(&DST, sizeof(SIZE), \ | |
| 1959 | + (const void *)(long) (SRC + insn->off)); \ | |
| 1960 | + DST = *((SIZE *)&DST); \ | |
| 1956 | 1961 | CONT; |
| 1957 | 1962 | |
| 1958 | 1963 | LDST(B, u8) |
| @@ -1960,15 +1965,6 @@ out: · 1 unmodified line | ||
| 1960 | 1965 | LDST(W, u32) |
| 1961 | 1966 | LDST(DW, u64) |
| 1962 | 1967 | #undef LDST |
| 1963 | −#define LDX_PROBE(SIZEOP, SIZE) \ | |
| 1964 | − LDX_PROBE_MEM_##SIZEOP: \ | |
| 1965 | − bpf_probe_read_kernel(&DST, SIZE, (const void *)(long) (SRC + insn->off)); \ | |
| 1966 | − CONT; | |
| 1967 | − LDX_PROBE(B, 1) | |
| 1968 | − LDX_PROBE(H, 2) | |
| 1969 | − LDX_PROBE(W, 4) | |
| 1970 | − LDX_PROBE(DW, 8) | |
| 1971 | −#undef LDX_PROBE | |
| 1972 | 1968 | |
| 1973 | 1969 | #define ATOMIC_ALU_OP(BOP, KOP) \ |
| 1974 | 1970 | case BOP: \ |