With latest llvm15, test_varlen failed with the following verifier log: 17: (85) call bpf_probe_read_kernel_str#115 ; R0_w=scalar(smin=-4095,smax=256) 18: (bf) r1 = r0 ; R0_w=scalar(id=1,smin=-4095,smax=256) R1_w=scalar(id=1,smin=-4095,smax=256) 19: (67) r1 <<= 32 ; R1_w=scalar(smax=1099511627776,umax=18446744069414584320,var_off=(0x0; 0xffffffff00000000),s32_min=0,s32_max=0,u32_max=) 20: (bf) r2 = r1 ; R1_w=scalar(id=2,smax=1099511627776,umax=18446744069414584320,var_off=(0x0; 0xffffffff00000000),s32_min=0,s32_max=0,u32) 21: (c7) r2 s>>= 32 ; R2=scalar(smin=-2147483648,smax=256) ; if (len >= 0) { 22: (c5) if r2 s< 0x0 goto pc+7 ; R2=scalar(umax=256,var_off=(0x0; 0x1ff)) ; payload4_len1 = len; 23: (18) r2 = 0xffffc90000167418 ; R2_w=map_value(off=1048,ks=4,vs=1572,imm=0) 25: (63) *(u32 *)(r2 +0) = r0 ; R0=scalar(id=1,smin=-4095,smax=256) R2_w=map_value(off=1048,ks=4,vs=1572,imm=0) 26: (77) r1 >>= 32 ; R1_w=scalar(umax=4294967295,var_off=(0x0; 0xffffffff)) ; payload += len; 27: (18) r6 = 0xffffc90000167424 ; R6_w=map_value(off=1060,ks=4,vs=1572,imm=0) 29: (0f) r6 += r1 ; R1_w=Pscalar(umax=4294967295,var_off=(0x0; 0xffffffff)) R6_w=map_value(off=1060,ks=4,vs=1572,umax=4294967295,var_off=(0) ; len = bpf_probe_read_kernel_str(payload, MAX_LEN, &buf_in2[0]); 30: (bf) r1 = r6 ; R1_w=map_value(off=1060,ks=4,vs=1572,umax=4294967295,var_off=(0x0; 0xffffffff)) R6_w=map_value(off=1060,ks=4,vs=1572,um) 31: (b7) r2 = 256 ; R2_w=256 32: (18) r3 = 0xffffc90000164100 ; R3_w=map_value(off=256,ks=4,vs=1056,imm=0) 34: (85) call bpf_probe_read_kernel_str#115 R1 unbounded memory access, make sure to bounds check any such access processed 27 insns (limit 1000000) max_states_per_insn 0 total_states 2 peak_states 2 mark_read 1 -- END PROG LOAD LOG -- libbpf: failed to load program 'handler32_signed' The failure is due to 20: (bf) r2 = r1 ; R1_w=scalar(id=2,smax=1099511627776,umax=18446744069414584320,var_off=(0x0; 0xffffffff00000000),s32_min=0,s32_max=0,u32) 21: (c7) r2 s>>= 32 ; R2=scalar(smin=-2147483648,smax=256) 22: (c5) if r2 s< 0x0 goto pc+7 ; R2=scalar(umax=256,var_off=(0x0; 0x1ff)) 26: (77) r1 >>= 32 ; R1_w=scalar(umax=4294967295,var_off=(0x0; 0xffffffff)) 29: (0f) r6 += r1 ; R1_w=Pscalar(umax=4294967295,var_off=(0x0; 0xffffffff)) R6_w=map_value(off=1060,ks=4,vs=1572,umax=4294967295,var_off=(0) where r1 has conservative value range compared to r2 and r1 is used later. In llvm, commit [1] triggered the above code generation and caused verification failure. It may take a while for llvm to address this issue. In the main time, let us change the variable 'len' type to 'long' and adjust condition properly. Tested with llvm14 and latest llvm15, both worked fine. [1] https://reviews.llvm.org/D126647 Signed-off-by: Yonghong Song <yhs@fb.com> Link: https://lore.kernel.org/r/20220613233449.2860753-1-yhs@fb.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
159 lines
3.0 KiB
C
159 lines
3.0 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/* Copyright (c) 2020 Facebook */
|
|
|
|
#include "vmlinux.h"
|
|
#include <bpf/bpf_helpers.h>
|
|
#include <bpf/bpf_tracing.h>
|
|
#include <bpf/bpf_core_read.h>
|
|
|
|
#define MAX_LEN 256
|
|
|
|
char buf_in1[MAX_LEN] = {};
|
|
char buf_in2[MAX_LEN] = {};
|
|
|
|
int test_pid = 0;
|
|
bool capture = false;
|
|
|
|
/* .bss */
|
|
__u64 payload1_len1 = 0;
|
|
__u64 payload1_len2 = 0;
|
|
__u64 total1 = 0;
|
|
char payload1[MAX_LEN + MAX_LEN] = {};
|
|
|
|
/* .data */
|
|
int payload2_len1 = -1;
|
|
int payload2_len2 = -1;
|
|
int total2 = -1;
|
|
char payload2[MAX_LEN + MAX_LEN] = { 1 };
|
|
|
|
int payload3_len1 = -1;
|
|
int payload3_len2 = -1;
|
|
int total3= -1;
|
|
char payload3[MAX_LEN + MAX_LEN] = { 1 };
|
|
|
|
int payload4_len1 = -1;
|
|
int payload4_len2 = -1;
|
|
int total4= -1;
|
|
char payload4[MAX_LEN + MAX_LEN] = { 1 };
|
|
|
|
SEC("raw_tp/sys_enter")
|
|
int handler64_unsigned(void *regs)
|
|
{
|
|
int pid = bpf_get_current_pid_tgid() >> 32;
|
|
void *payload = payload1;
|
|
long len;
|
|
|
|
/* ignore irrelevant invocations */
|
|
if (test_pid != pid || !capture)
|
|
return 0;
|
|
|
|
len = bpf_probe_read_kernel_str(payload, MAX_LEN, &buf_in1[0]);
|
|
if (len >= 0) {
|
|
payload += len;
|
|
payload1_len1 = len;
|
|
}
|
|
|
|
len = bpf_probe_read_kernel_str(payload, MAX_LEN, &buf_in2[0]);
|
|
if (len >= 0) {
|
|
payload += len;
|
|
payload1_len2 = len;
|
|
}
|
|
|
|
total1 = payload - (void *)payload1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("raw_tp/sys_exit")
|
|
int handler64_signed(void *regs)
|
|
{
|
|
int pid = bpf_get_current_pid_tgid() >> 32;
|
|
void *payload = payload3;
|
|
long len;
|
|
|
|
/* ignore irrelevant invocations */
|
|
if (test_pid != pid || !capture)
|
|
return 0;
|
|
|
|
len = bpf_probe_read_kernel_str(payload, MAX_LEN, &buf_in1[0]);
|
|
if (len >= 0) {
|
|
payload += len;
|
|
payload3_len1 = len;
|
|
}
|
|
len = bpf_probe_read_kernel_str(payload, MAX_LEN, &buf_in2[0]);
|
|
if (len >= 0) {
|
|
payload += len;
|
|
payload3_len2 = len;
|
|
}
|
|
total3 = payload - (void *)payload3;
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tp/raw_syscalls/sys_enter")
|
|
int handler32_unsigned(void *regs)
|
|
{
|
|
int pid = bpf_get_current_pid_tgid() >> 32;
|
|
void *payload = payload2;
|
|
u32 len;
|
|
|
|
/* ignore irrelevant invocations */
|
|
if (test_pid != pid || !capture)
|
|
return 0;
|
|
|
|
len = bpf_probe_read_kernel_str(payload, MAX_LEN, &buf_in1[0]);
|
|
if (len <= MAX_LEN) {
|
|
payload += len;
|
|
payload2_len1 = len;
|
|
}
|
|
|
|
len = bpf_probe_read_kernel_str(payload, MAX_LEN, &buf_in2[0]);
|
|
if (len <= MAX_LEN) {
|
|
payload += len;
|
|
payload2_len2 = len;
|
|
}
|
|
|
|
total2 = payload - (void *)payload2;
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tp/raw_syscalls/sys_exit")
|
|
int handler32_signed(void *regs)
|
|
{
|
|
int pid = bpf_get_current_pid_tgid() >> 32;
|
|
void *payload = payload4;
|
|
long len;
|
|
|
|
/* ignore irrelevant invocations */
|
|
if (test_pid != pid || !capture)
|
|
return 0;
|
|
|
|
len = bpf_probe_read_kernel_str(payload, MAX_LEN, &buf_in1[0]);
|
|
if (len >= 0) {
|
|
payload += len;
|
|
payload4_len1 = len;
|
|
}
|
|
len = bpf_probe_read_kernel_str(payload, MAX_LEN, &buf_in2[0]);
|
|
if (len >= 0) {
|
|
payload += len;
|
|
payload4_len2 = len;
|
|
}
|
|
total4 = payload - (void *)payload4;
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tp/syscalls/sys_exit_getpid")
|
|
int handler_exit(void *regs)
|
|
{
|
|
long bla;
|
|
|
|
if (bpf_probe_read_kernel(&bla, sizeof(bla), 0))
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
char LICENSE[] SEC("license") = "GPL";
|