Skip to content

Commit 6e2e2b7

Browse files
anakryikoKernel Patches Daemon
authored and
Kernel Patches Daemon
committed
BUG: demonstration of uprobe/uretprobe corrupted stack traces
Hi Masami, We've got reports about partially corrupt stack traces when being captured from uretprobes. Trying the simplest repro seems to confirm that something is not quite right here. I'll try to debug it a bit more this week, but I was hoping for you to take a look as well, if you get a chance. Simple repro built on top of BPF selftests. $ sudo ./test_progs -a uprobe_autoattach -v ... FN ADDR 0x55fde0 - 0x55fdef UPROBE SZ 40 (CNT 5) URETPROBE SZ 40 (CNT 5) UPROBE 0x55fde0 URETPROBE 0x55ffd4 UPROBE 0x584653 URETPROBE 0x584653 UPROBE 0x585cc9 URETPROBE 0x585cc9 UPROBE 0x7fa9a31eaca3 URETPROBE 0x7fa9a31eaca3 UPROBE 0x5541f689495641d7 URETPROBE 0x5541f689495641d7 ... #203 uprobe_autoattach:OK Summary: 1/0 PASSED, 0 SKIPPED, 0 FAILED There seem to be two distinct problems. 1. Last two entries for both uprobe and uretprobe stacks are not user-space addressed (0x7fa9a31eaca3) and the very last one doesn't even look like a valid address (0x5541f689495641d7). 2. Looking at first entry for UPROBE vs URETPROBE, you can see that uprobe one's is correct and points exactly to the beginning of autoattach_trigger_func (0x55fde0) as expected, but uretprobe entry (0x55ffd4) is way out of autoattach_trigger_func (which is just 15 bytes long and ends at 0x55fdef). Using addr2line it shows that it points to: 0x000000000055ffd4: test_uprobe_autoattach at /data/users/andriin/linux/tools/testing/selftests/bpf/prog_tests/uprobe_autoattach.c:33 Which is a valid function and location to which autoattach_trigger_func() should return (see objdump snippet below), but from uretprobe I'd imagine that we are going to get address within traced user function (that is 0x55fde0 - 0x55fdef range), not the return address in a parent function. 55ffc4: 89 83 3c 08 00 00 mov %eax,0x83c(%rbx) 55ffca: 8b 45 e8 mov -0x18(%rbp),%eax 55ffcd: 89 c7 mov %eax,%edi 55ffcf: e8 0c fe ff ff call 55fde0 <autoattach_trigger_func> --> 55ffd4: 89 45 a8 mov %eax,-0x58(%rbp) 55ffd7: ba ef fd 55 00 mov $0x55fdef,%edx Both issues above seem unexpected, can you please see if I have some wrong assumptions here? Thanks in advance for taking a look! Cc: Jiri Olsa <[email protected]> Cc: Riham Selim <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]>
1 parent cb9e6fe commit 6e2e2b7

File tree

3 files changed

+27
-1
lines changed

3 files changed

+27
-1
lines changed

tools/testing/selftests/bpf/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ BPF_GCC ?= $(shell command -v bpf-gcc;)
2323
SAN_CFLAGS ?=
2424
CFLAGS += -g -O0 -rdynamic -Wall -Werror $(GENFLAGS) $(SAN_CFLAGS) \
2525
-I$(CURDIR) -I$(INCLUDE_DIR) -I$(GENDIR) -I$(LIBDIR) \
26-
-I$(TOOLSINCDIR) -I$(APIDIR) -I$(OUTPUT)
26+
-I$(TOOLSINCDIR) -I$(APIDIR) -I$(OUTPUT) -fno-omit-frame-pointer
27+
2728
LDFLAGS += $(SAN_CFLAGS)
2829
LDLIBS += -lelf -lz -lrt -lpthread
2930

tools/testing/selftests/bpf/prog_tests/uprobe_autoattach.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ static noinline int autoattach_trigger_func(int arg)
1010
asm volatile ("");
1111
return arg + 1;
1212
}
13+
static noinline int autoattach_trigger_func_post(int arg) { return 0; }
1314

1415
void test_uprobe_autoattach(void)
1516
{
1617
struct test_uprobe_autoattach *skel;
1718
int trigger_val = 100, trigger_ret;
1819
size_t malloc_sz = 1;
1920
char *mem;
21+
int i;
2022

2123
skel = test_uprobe_autoattach__open_and_load();
2224
if (!ASSERT_OK_PTR(skel, "skel_open"))
@@ -30,6 +32,18 @@ void test_uprobe_autoattach(void)
3032
/* trigger & validate uprobe & uretprobe */
3133
trigger_ret = autoattach_trigger_func(trigger_val);
3234

35+
printf("FN ADDR %p - %p\n", autoattach_trigger_func, autoattach_trigger_func_post);
36+
printf("UPROBE SZ %d (CNT %d) URETPROBE SZ %d (CNT %d)\n",
37+
skel->bss->uprobe_stack_sz,
38+
skel->bss->uprobe_stack_sz / 8,
39+
skel->bss->uretprobe_stack_sz,
40+
skel->bss->uretprobe_stack_sz / 8);
41+
for (i = 0; i < skel->bss->uprobe_stack_sz / 8; i++) {
42+
printf("UPROBE %-18p URETPROBE %-18p\n",
43+
(void *)skel->bss->uprobe_stack[i],
44+
(void *)skel->bss->uretprobe_stack[i]);
45+
}
46+
3347
skel->bss->test_pid = getpid();
3448

3549
/* trigger & validate shared library u[ret]probes attached by name */

tools/testing/selftests/bpf/progs/test_uprobe_autoattach.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,19 @@ int handle_uprobe_noautoattach(struct pt_regs *ctx)
2727
return 0;
2828
}
2929

30+
__u64 uprobe_stack[128];
31+
__u64 uretprobe_stack[128];
32+
int uprobe_stack_sz, uretprobe_stack_sz;
33+
3034
SEC("uprobe//proc/self/exe:autoattach_trigger_func")
3135
int handle_uprobe_byname(struct pt_regs *ctx)
3236
{
3337
uprobe_byname_parm1 = PT_REGS_PARM1_CORE(ctx);
3438
uprobe_byname_ran = 1;
39+
40+
uprobe_stack_sz = bpf_get_stack(ctx,
41+
uprobe_stack, sizeof(uprobe_stack),
42+
BPF_F_USER_STACK);
3543
return 0;
3644
}
3745

@@ -40,6 +48,9 @@ int handle_uretprobe_byname(struct pt_regs *ctx)
4048
{
4149
uretprobe_byname_rc = PT_REGS_RC_CORE(ctx);
4250
uretprobe_byname_ran = 2;
51+
uretprobe_stack_sz = bpf_get_stack(ctx,
52+
uretprobe_stack, sizeof(uretprobe_stack),
53+
BPF_F_USER_STACK);
4354
return 0;
4455
}
4556

0 commit comments

Comments
 (0)