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

bcc: Use bpf_probe_read_user in tools and provide backward compatibility #2866

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
bcc/docs: Add bpf_probe_read_user to docs and tutorials
Signed-off-by: Sumanth Korikkar <[email protected]>
  • Loading branch information
sumanthkorikkar committed Apr 23, 2020
commit aa3a4a6f7c6d59ede1598bc54fb9c83d8ad1f776
38 changes: 33 additions & 5 deletions docs/reference_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ This guide is incomplete. If something feels missing, check the bcc and kernel s
- [7. bpf_get_current_task()](#7-bpf_get_current_task)
- [8. bpf_log2l()](#8-bpf_log2l)
- [9. bpf_get_prandom_u32()](#9-bpf_get_prandom_u32)
- [10. bpf_probe_read_user()](#10-bpf_probe_read_user)
- [11. bpf_probe_read_user_str()](#11-bpf_probe_read_user_str)
- [Debugging](#debugging)
- [1. bpf_override_return()](#1-bpf_override_return)
- [Output](#output)
Expand Down Expand Up @@ -196,7 +198,7 @@ For example:
```C
int count(struct pt_regs *ctx) {
char buf[64];
bpf_probe_read(&buf, sizeof(buf), (void *)PT_REGS_PARM1(ctx));
bpf_probe_read_user(&buf, sizeof(buf), (void *)PT_REGS_PARM1(ctx));
bpf_trace_printk("%s %d", buf, PT_REGS_PARM2(ctx));
return(0);
}
Expand Down Expand Up @@ -242,7 +244,7 @@ int do_trace(struct pt_regs *ctx) {
uint64_t addr;
char path[128];
bpf_usdt_readarg(6, ctx, &addr);
bpf_probe_read(&path, sizeof(path), (void *)addr);
bpf_probe_read_user(&path, sizeof(path), (void *)addr);
bpf_trace_printk("path:%s\\n", path);
return 0;
};
Expand Down Expand Up @@ -372,7 +374,7 @@ Syntax: ```int bpf_probe_read(void *dst, int size, const void *src)```

Return: 0 on success

This copies a memory location to the BPF stack, so that BPF can later operate on it. For safety, all memory reads must pass through bpf_probe_read(). This happens automatically in some cases, such as dereferencing kernel variables, as bcc will rewrite the BPF program to include the necessary bpf_probe_reads().
This copies size bytes from kernel address space to the BPF stack, so that BPF can later operate on it. For safety, all kernel memory reads must pass through bpf_probe_read(). This happens automatically in some cases, such as dereferencing kernel variables, as bcc will rewrite the BPF program to include the necessary bpf_probe_read().

Examples in situ:
[search /examples](https://github.com/iovisor/bcc/search?q=bpf_probe_read+path%3Aexamples&type=Code),
Expand All @@ -386,7 +388,7 @@ Return:
- \> 0 length of the string including the trailing NULL on success
- \< 0 error

This copies a `NULL` terminated string from memory location to BPF stack, so that BPF can later operate on it. In case the string length is smaller than size, the target is not padded with further `NULL` bytes. In case the string length is larger than size, just `size - 1` bytes are copied and the last byte is set to `NULL`.
This copies a `NULL` terminated string from kernel address space to the BPF stack, so that BPF can later operate on it. In case the string length is smaller than size, the target is not padded with further `NULL` bytes. In case the string length is larger than size, just `size - 1` bytes are copied and the last byte is set to `NULL`.

Examples in situ:
[search /examples](https://github.com/iovisor/bcc/search?q=bpf_probe_read_str+path%3Aexamples&type=Code),
Expand Down Expand Up @@ -490,6 +492,32 @@ Example in situ:
[search /examples](https://github.com/iovisor/bcc/search?q=bpf_get_prandom_u32+path%3Aexamples&type=Code),
[search /tools](https://github.com/iovisor/bcc/search?q=bpf_get_prandom_u32+path%3Atools&type=Code)

### 10. bpf_probe_read_user()

Syntax: ```int bpf_probe_read_user(void *dst, int size, const void *src)```

Return: 0 on success

This attempts to safely read size bytes from user address space to the BPF stack, so that BPF can later operate on it. For safety, all user address space memory reads must pass through bpf_probe_read_user().

Examples in situ:
[search /examples](https://github.com/iovisor/bcc/search?q=bpf_probe_read_user+path%3Aexamples&type=Code),
[search /tools](https://github.com/iovisor/bcc/search?q=bpf_probe_read_user+path%3Atools&type=Code)

### 11. bpf_probe_read_user_str()

Syntax: ```int bpf_probe_read_user_str(void *dst, int size, const void *src)```

Return:
- \> 0 length of the string including the trailing NULL on success
- \< 0 error

This copies a `NULL` terminated string from user address space to the BPF stack, so that BPF can later operate on it. In case the string length is smaller than size, the target is not padded with further `NULL` bytes. In case the string length is larger than size, just `size - 1` bytes are copied and the last byte is set to `NULL`.

Examples in situ:
[search /examples](https://github.com/iovisor/bcc/search?q=bpf_probe_read_user_str+path%3Aexamples&type=Code),
[search /tools](https://github.com/iovisor/bcc/search?q=bpf_probe_read_user_str+path%3Atools&type=Code)

## Debugging

### 1. bpf_override_return()
Expand Down Expand Up @@ -1721,7 +1749,7 @@ See the "Understanding eBPF verifier messages" section in the kernel source unde

## 1. Invalid mem access

This can be due to trying to read memory directly, instead of operating on memory on the BPF stack. All memory reads must be passed via bpf_probe_read() to copy memory into the BPF stack, which can be automatic by the bcc rewriter in some cases of simple dereferencing. bpf_probe_read() does all the required checks.
This can be due to trying to read memory directly, instead of operating on memory on the BPF stack. All kernel memory reads must be passed via bpf_probe_read() to copy kernel memory into the BPF stack, which can be automatic by the bcc rewriter in some cases of simple dereferencing. bpf_probe_read() does all the required checks.

Example:

Expand Down
6 changes: 3 additions & 3 deletions docs/tutorial_bcc_python_developer.md
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ int count(struct pt_regs *ctx) {
struct key_t key = {};
u64 zero = 0, *val;

bpf_probe_read(&key.c, sizeof(key.c), (void *)PT_REGS_PARM1(ctx));
bpf_probe_read_user(&key.c, sizeof(key.c), (void *)PT_REGS_PARM1(ctx));
// could also use `counts.increment(key)`
val = counts.lookup_or_try_init(&key, &zero);
if (val) {
Expand Down Expand Up @@ -620,7 +620,7 @@ int do_trace(struct pt_regs *ctx) {
uint64_t addr;
char path[128]={0};
bpf_usdt_readarg(6, ctx, &addr);
bpf_probe_read(&path, sizeof(path), (void *)addr);
bpf_probe_read_user(&path, sizeof(path), (void *)addr);
bpf_trace_printk("path:%s\\n", path);
return 0;
};
Expand All @@ -640,7 +640,7 @@ b = BPF(text=bpf_text, usdt_contexts=[u])
Things to learn:

1. ```bpf_usdt_readarg(6, ctx, &addr)```: Read the address of argument 6 from the USDT probe into ```addr```.
1. ```bpf_probe_read(&path, sizeof(path), (void *)addr)```: Now the string ```addr``` points to into our ```path``` variable.
1. ```bpf_probe_read_user(&path, sizeof(path), (void *)addr)```: Now the string ```addr``` points to into our ```path``` variable.
1. ```u = USDT(pid=int(pid))```: Initialize USDT tracing for the given PID.
1. ```u.enable_probe(probe="http__server__request", fn_name="do_trace")```: Attach our ```do_trace()``` BPF C function to the Node.js ```http__server__request``` USDT probe.
1. ```b = BPF(text=bpf_text, usdt_contexts=[u])```: Need to pass in our USDT object, ```u```, to BPF object creation.
Expand Down