iovisor / iovisor/bcc

copy_from_user / access_ok while tracing?

Open
#2,090 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
C
Stars
22.7k
Forks
4.1k
Avg merge
5d 13h
Merged PRs (30d)
3

Description

Hi,

I'm trying to find out if there is a way to do a `bpf_probe_read` that will fail on attempts to read kernel memory (basically `copy_from_user`). There doesn't really seem to be a good way of doing `access_ok()` as the current thread context in eBPF appears to be that of the kernel. `access_ok()` is based on `user_addr_max()`, which is defined as `(current->thread.addr_limit.seg)` ([for x86_64](https://elixir.bootlin.com/linux/v4.19.10/source/arch/x86/include/asm/uaccess.h#L39)). Swapping `current` for `bpf_get_current_task()` and breaking it up a bit for the codegen to be happy with it, I end up getting `0xffffffffffffffff` when in a kprobe on a syscall.

Right now, I'm hackily working around this by replacing `user_addr_max()` with the constant `((size_t)0x0000800000000000)`, per the [kernel memory mapping documentation](https://www.kernel.org/doc/Documentation/x86/x86_64/mm.txt), but this is extremely non-portable and I'd prefer to do this in a better way if one exists.

```
#ifdef current
#undef current
#define current ((struct task_struct*)bpf_get_current_task())
#endif

#ifdef user_addr_max
#undef user_addr_max
#define user_addr_max() ((size_t)0x0000800000000000)
#endif
```

Do you folks happen to know of a proper way to do this?

Thanks.

P.S. For reference, I've thought about using `bpf_probe_write_user` with a size of zero, and calling it on the start and end address (this would have required a separate re-implementation of overflow/wraparound checks), but the verifier refuses to take a size less than 1 when calling `bpf_probe_write_user`.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with arch/x86/include/asm/uaccess.h:user_addr_max() and the bpf_probe_read and bpf_probe_write_user entry points described in the issue. Compare how syscall kprobes obtain user-address bounds and verify behavior across architectures; done means a maintainer-confirmed portable way to reject kernel-memory reads, or a documented limitation.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, linux
Domain
observability, operating-systems
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.