diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-19 19:23:30 -1000 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-19 19:23:30 -1000 |
| commit | 94905fcbd9e225dd931aa543071d2fa55704206a (patch) | |
| tree | 686903cba687ce2f1937f0633f1fd80fa40ea01e /kernel/trace | |
| parent | 9ef61ff7ca4cad2194eb3fd3de99a200f4038833 (diff) | |
bpf: Use get_user() for kprobe_multi symbols and uprobe_multi arrays
copy_user_syms() and bpf_uprobe_multi_link_attach() check whole user
arrays with access_ok() up front, then read them one element at a time
with __get_user(), with other work in between: allocations and
strncpy_from_user() in copy_user_syms(), validation in the uprobe_multi
loop. Each of those accesses enables and disables user access on its
own, so the up-front check saves nothing. On x86, __get_user() is even
more expensive than get_user(): it does an lfence, where get_user()
checks the address with a couple of plain instructions.
Use get_user(). The access_ok() checks stay, because they also make a
bad array fail with -EFAULT before anything else is looked up or
allocated. Update the comment that said they were there for
__get_user().
This is part of getting rid of __get_user() and __put_user() entirely.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/trace')
| -rw-r--r-- | kernel/trace/bpf_trace.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 29260951aa87..88c3b5b513ab 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -2388,7 +2388,7 @@ static int copy_user_syms(struct user_syms *us, unsigned long __user *usyms, u32 goto error; for (p = buf, i = 0; i < cnt; i++) { - if (__get_user(usymbol, usyms + i)) { + if (get_user(usymbol, usyms + i)) { err = -EFAULT; goto error; } @@ -3295,8 +3295,8 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr /* * All uoffsets/uref_ctr_offsets/ucookies arrays have the same value - * size, we need to check their address range is safe for __get_user - * calls. + * size. Check their address ranges up front, so that a bad pointer + * fails before anything is looked up or allocated. */ size = sizeof(*uoffsets) * cnt; if (!access_ok(uoffsets, size) || !access_ok(uref_ctr_offsets, size) || @@ -3331,7 +3331,7 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr goto error_free; for (i = 0; i < cnt; i++) { - if (__get_user(uprobes[i].offset, uoffsets + i)) { + if (get_user(uprobes[i].offset, uoffsets + i)) { err = -EFAULT; goto error_free; } @@ -3339,11 +3339,11 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr err = -EINVAL; goto error_free; } - if (uref_ctr_offsets && __get_user(uprobes[i].ref_ctr_offset, uref_ctr_offsets + i)) { + if (uref_ctr_offsets && get_user(uprobes[i].ref_ctr_offset, uref_ctr_offsets + i)) { err = -EFAULT; goto error_free; } - if (ucookies && __get_user(uprobes[i].cookie, ucookies + i)) { + if (ucookies && get_user(uprobes[i].cookie, ucookies + i)) { err = -EFAULT; goto error_free; } |
