Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't trace sys_execve inside a c program #2523

Closed
godspeedcurry opened this issue Mar 13, 2023 · 12 comments
Closed

Can't trace sys_execve inside a c program #2523

godspeedcurry opened this issue Mar 13, 2023 · 12 comments

Comments

@godspeedcurry
Copy link

godspeedcurry commented Mar 13, 2023

I write a C program to make system call, I want to use bpftrace to trace it. But when I use it, it can't print out the thing I want.
Here is the C program.

#include <stdio.h>
#include <unistd.h>
int main(){
    char * path = "/usr/bin/id";
    char *argv[] = {"/usr/bin/id","root", NULL};
    char* envp[] = { NULL };

    execve(path, argv, envp);
    return 0;
}

Left window command:

gcc test.c -o foo
./foo

Right window command:

bpftrace -e 'tracepoint:syscalls:sys_enter_execve { printf("%-6d %-8s", pid, comm); join(args->argv);}'

image

but when I use strace strace ./foo, everything works well. I got the line 14074 foo /usr/bin/id root
image

where is the problem?

@godspeedcurry godspeedcurry added the bug Something isn't working label Mar 13, 2023
@fbs
Copy link
Contributor

fbs commented Mar 13, 2023

Can you run with -kk? Its probably because the path isn't faulted into memory yet so the bpf read fails and you get an empty string

@godspeedcurry
Copy link
Author

Hello, when run with '-kk', it give the following message, by the way, the test environment is in docker (on mac)

stdin:1:62-78: WARNING: Failed to probe_read_user_str: Bad address (-14)
tracepoint:syscalls:sys_enter_execve { printf("%s: ", comm); join(args->argv) }
                                                             ~~~~~~~~~~~~~~~~
stdin:1:62-78: WARNING: Failed to probe_read_user_str: Bad address (-14)
tracepoint:syscalls:sys_enter_execve { printf("%s: ", comm); join(args->argv) }

@fbs
Copy link
Contributor

fbs commented Mar 13, 2023

Can you try to loop over and printf your argv from your code and see if it works after?

@godspeedcurry
Copy link
Author

Can you try to loop over and printf your argv from your code and see if it works after?

could you show me the code, I am a beginner in kernel.

@fbs
Copy link
Contributor

fbs commented Mar 13, 2023

It has nothing to do with the kernel, its your own C code

printf("%s %s\n", argv[0], argv[1]);

Should be enough

@godspeedcurry
Copy link
Author

godspeedcurry commented Mar 13, 2023

Hi, I found another problem, If I print something before, I can get the thing I want...

#include <stdio.h>
#include <unistd.h>
int main(){
    printf("test");
    char * path = "/usr/bin/id";
    char *argv[] = {"/usr/bin/id","root", NULL};
    char* envp[] = { NULL };

    execve(path, argv, envp);

    return 0;
}

image

image

@godspeedcurry
Copy link
Author

I tried what you mentioned, also works very well, but I can't explain it.
image

@godspeedcurry
Copy link
Author

also I found that if the binary is statically linked, the program compiled by the original source code works very well.
image

@ValdikSS
Copy link

@fbs
Copy link
Contributor

fbs commented Mar 13, 2023

@ValdikSS what part of that doc are you referring to?

Like I said earlier, the data you're using isn't in memory yet. These static strings are compiled in and are not actually faulted into memory until they're accessed. The access won't happen until its read, which is after your bpftrace probe ran. BPF won't pull the data in so you get an EFAULT/-14.

By printing the values or just a random print of a constant string you pull the small amount of data into memory (as it goes by page, not by var) and then it works

@ValdikSS
Copy link

@fbs,

what part of that doc are you referring to?

While race conditions when hooking syscalls via kprobes and tracepoints are troublesome, it turns out that userspace can flat out block eBPF from reading syscall inputs if they reside in MAP_SHARED pages. It is worth noting that such tomfoolery is somewhat limited as it only works against bpf_probe_read(|_user|_kern) calls made before a page is read by the kernel in a given syscall handler. As a result, a quick “fix” for tracers is to perform such reads when the syscall returns. However, such a “fix” would increase the feasibility of race condition abuse whenever the syscall implementation takes longer than the syscall context switch.

@fbs fbs removed the bug Something isn't working label Mar 13, 2023
@viktormalik
Copy link
Contributor

Looks like this is not a bpftrace bug. Can we close?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants