copy_from_user / access_ok while tracing?
- 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