Skip to content

Commit

Permalink
bpf: Fix prog_array UAF in __uprobe_perf_func()
Browse files Browse the repository at this point in the history
Currently, the pointer stored in call->prog_array is loaded in
__uprobe_perf_func(), with no RCU annotation and no RCU protection, so the
loaded pointer can immediately be dangling. Later,
bpf_prog_run_array_uprobe() starts a RCU-trace read-side critical section,
but this is too late. It then uses rcu_dereference_check(), but this use of
rcu_dereference_check() does not actually dereference anything.

It looks like the intention was to pass a pointer to the member
call->prog_array into bpf_prog_run_array_uprobe() and actually dereference
the pointer in there. Fix the issue by actually doing that.

Fixes: 8c7dcb8 ("bpf: implement sleepable uprobes by chaining gps")
Cc: [email protected]
Signed-off-by: Jann Horn <[email protected]>
  • Loading branch information
thejh authored and Kernel Patches Daemon committed Dec 6, 2024
1 parent e8379c7 commit 17ac123
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 3 deletions.
4 changes: 2 additions & 2 deletions include/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -2193,7 +2193,7 @@ bpf_prog_run_array(const struct bpf_prog_array *array,
* rcu-protected dynamically sized maps.
*/
static __always_inline u32
bpf_prog_run_array_uprobe(const struct bpf_prog_array __rcu *array_rcu,
bpf_prog_run_array_uprobe(struct bpf_prog_array __rcu **array_rcu,
const void *ctx, bpf_prog_run_fn run_prog)
{
const struct bpf_prog_array_item *item;
Expand All @@ -2210,7 +2210,7 @@ bpf_prog_run_array_uprobe(const struct bpf_prog_array __rcu *array_rcu,

run_ctx.is_uprobe = true;

array = rcu_dereference_check(array_rcu, rcu_read_lock_trace_held());
array = rcu_dereference_check(*array_rcu, rcu_read_lock_trace_held());
if (unlikely(!array))
goto out;
old_run_ctx = bpf_set_run_ctx(&run_ctx.run_ctx);
Expand Down
2 changes: 1 addition & 1 deletion kernel/trace/trace_uprobe.c
Original file line number Diff line number Diff line change
Expand Up @@ -1404,7 +1404,7 @@ static void __uprobe_perf_func(struct trace_uprobe *tu,
if (bpf_prog_array_valid(call)) {
u32 ret;

ret = bpf_prog_run_array_uprobe(call->prog_array, regs, bpf_prog_run);
ret = bpf_prog_run_array_uprobe(&call->prog_array, regs, bpf_prog_run);
if (!ret)
return;
}
Expand Down

0 comments on commit 17ac123

Please sign in to comment.