Linux Perf Users
 help / color / mirror / Atom feed
* [PATCH] uprobes: Fix NULL pointer dereference in hprobe_expire()
@ 2026-07-29 14:44 Breno Leitao
  2026-07-29 16:02 ` Oleg Nesterov
  0 siblings, 1 reply; 5+ messages in thread
From: Breno Leitao @ 2026-07-29 14:44 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, James Clark, Masami Hiramatsu,
	Oleg Nesterov, Andrii Nakryiko
  Cc: linux-perf-users, linux-kernel, linux-trace-kernel, kernel-team,
	stable, Breno Leitao

Forking a task that has a pending uretprobe can oops the kernel with a
NULL pointer dereference in the clone() path:

  BUG: kernel NULL pointer dereference, address: 0000000000000018
  Oops: 0002 [#1] SMP NOPTI
  RIP: 0010:hprobe_expire
  CR2: 0000000000000018
  Call Trace:
   uprobe_copy_process
   copy_process
   kernel_clone
   __x64_sys_clone
   do_syscall_64
   entry_SYSCALL_64_after_hwframe

This was found on real hosts on Meta fleet.

I've got the impression that this is what is happening:

  CPU 1                          CPU 2 (traced task)
  -----                          -------------------
                                 hit uprobe, prepare_uretprobe():
                                   hprobe LEASED, refcount >= 1
  uprobe_unregister()
    put_uprobe(): refcount -> 0
                                 fork() -> dup_utask()
                                   hprobe_expire(hprobe, true)
                                     try_get_uprobe() -> NULL
                                     get_uprobe(NULL)   <-- Oops

Only take the extra reference when the uprobe is non-NULL; a NULL means
it is gone and is the correct value to return.

Fixes: dd1a7567784e ("uprobes: SRCU-protect uretprobe lifetime (with timeout)")
Cc: stable@vger.kernel.org
Signed-off-by: Breno Leitao <leitao@debian.org>
---
 kernel/events/uprobes.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 07f69dd3093d5..950108f92079d 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -832,7 +832,7 @@ static struct uprobe *hprobe_expire(struct hprobe *hprobe, bool get)
 		if (try_cmpxchg(&hprobe->state, &hstate, uprobe ? HPROBE_STABLE : HPROBE_GONE)) {
 			/* We won the race, we are the ones to unlock SRCU */
 			__srcu_read_unlock(&uretprobes_srcu, hprobe->srcu_idx);
-			return get ? get_uprobe(uprobe) : uprobe;
+			return get && uprobe ? get_uprobe(uprobe) : uprobe;
 		}
 
 		/*

---
base-commit: 3652b49adac266a3d27cb41cdfdb7d8790fc3633
change-id: 20260729-uprobe-b142b0863572

Best regards,
--  
Breno Leitao <leitao@debian.org>


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] uprobes: Fix NULL pointer dereference in hprobe_expire()
  2026-07-29 14:44 [PATCH] uprobes: Fix NULL pointer dereference in hprobe_expire() Breno Leitao
@ 2026-07-29 16:02 ` Oleg Nesterov
  2026-07-29 19:31   ` Andrii Nakryiko
  0 siblings, 1 reply; 5+ messages in thread
From: Oleg Nesterov @ 2026-07-29 16:02 UTC (permalink / raw)
  To: Breno Leitao
  Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, James Clark, Masami Hiramatsu,
	Andrii Nakryiko, linux-perf-users, linux-kernel,
	linux-trace-kernel, kernel-team, stable

On 07/29, Breno Leitao wrote:
>
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -832,7 +832,7 @@ static struct uprobe *hprobe_expire(struct hprobe *hprobe, bool get)
>  		if (try_cmpxchg(&hprobe->state, &hstate, uprobe ? HPROBE_STABLE : HPROBE_GONE)) {
>  			/* We won the race, we are the ones to unlock SRCU */
>  			__srcu_read_unlock(&uretprobes_srcu, hprobe->srcu_idx);
> -			return get ? get_uprobe(uprobe) : uprobe;
> +			return get && uprobe ? get_uprobe(uprobe) : uprobe;

Well, looks "obviously correct". At least the current code is obviously
wrong, it even checks uprobe != NULL 3 lines above.

Andrii ?

Acked-by: Oleg Nesterov <oleg@redhat.com>



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] uprobes: Fix NULL pointer dereference in hprobe_expire()
  2026-07-29 16:02 ` Oleg Nesterov
@ 2026-07-29 19:31   ` Andrii Nakryiko
  2026-07-29 23:54     ` Masami Hiramatsu
  0 siblings, 1 reply; 5+ messages in thread
From: Andrii Nakryiko @ 2026-07-29 19:31 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Breno Leitao, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
	James Clark, Masami Hiramatsu, Andrii Nakryiko, linux-perf-users,
	linux-kernel, linux-trace-kernel, kernel-team, stable

On Wed, Jul 29, 2026 at 9:02 AM Oleg Nesterov <oleg@redhat.com> wrote:
>
> On 07/29, Breno Leitao wrote:
> >
> > --- a/kernel/events/uprobes.c
> > +++ b/kernel/events/uprobes.c
> > @@ -832,7 +832,7 @@ static struct uprobe *hprobe_expire(struct hprobe *hprobe, bool get)
> >               if (try_cmpxchg(&hprobe->state, &hstate, uprobe ? HPROBE_STABLE : HPROBE_GONE)) {
> >                       /* We won the race, we are the ones to unlock SRCU */
> >                       __srcu_read_unlock(&uretprobes_srcu, hprobe->srcu_idx);
> > -                     return get ? get_uprobe(uprobe) : uprobe;
> > +                     return get && uprobe ? get_uprobe(uprobe) : uprobe;
>
> Well, looks "obviously correct". At least the current code is obviously
> wrong, it even checks uprobe != NULL 3 lines above.
>
> Andrii ?
>

Yes, indeed, I'm more surprised this didn't come up much earlier
(probably it's rare enough to have uretprobe with refcnt at zero
during fork). The fix looks good, thanks!

Acked-by: Andrii Nakryiko <andrii@kernel.org>

> Acked-by: Oleg Nesterov <oleg@redhat.com>
>
>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] uprobes: Fix NULL pointer dereference in hprobe_expire()
  2026-07-29 19:31   ` Andrii Nakryiko
@ 2026-07-29 23:54     ` Masami Hiramatsu
  2026-07-30 10:38       ` Peter Zijlstra
  0 siblings, 1 reply; 5+ messages in thread
From: Masami Hiramatsu @ 2026-07-29 23:54 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Oleg Nesterov, Breno Leitao, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
	James Clark, Masami Hiramatsu, Andrii Nakryiko, linux-perf-users,
	linux-kernel, linux-trace-kernel, kernel-team, stable

On Wed, 29 Jul 2026 12:31:08 -0700
Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote:

> On Wed, Jul 29, 2026 at 9:02 AM Oleg Nesterov <oleg@redhat.com> wrote:
> >
> > On 07/29, Breno Leitao wrote:
> > >
> > > --- a/kernel/events/uprobes.c
> > > +++ b/kernel/events/uprobes.c
> > > @@ -832,7 +832,7 @@ static struct uprobe *hprobe_expire(struct hprobe *hprobe, bool get)
> > >               if (try_cmpxchg(&hprobe->state, &hstate, uprobe ? HPROBE_STABLE : HPROBE_GONE)) {
> > >                       /* We won the race, we are the ones to unlock SRCU */
> > >                       __srcu_read_unlock(&uretprobes_srcu, hprobe->srcu_idx);
> > > -                     return get ? get_uprobe(uprobe) : uprobe;
> > > +                     return get && uprobe ? get_uprobe(uprobe) : uprobe;
> >
> > Well, looks "obviously correct". At least the current code is obviously
> > wrong, it even checks uprobe != NULL 3 lines above.
> >
> > Andrii ?
> >
> 
> Yes, indeed, I'm more surprised this didn't come up much earlier
> (probably it's rare enough to have uretprobe with refcnt at zero
> during fork). The fix looks good, thanks!
> 
> Acked-by: Andrii Nakryiko <andrii@kernel.org>
> 
> > Acked-by: Oleg Nesterov <oleg@redhat.com>
> >

Thanks, this seems good to me. (uprobe is NULL checked in try_cmpxchg(),
so it could be NULL.)

Can I pick this to probes/fixes branch?

Thank you,

-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] uprobes: Fix NULL pointer dereference in hprobe_expire()
  2026-07-29 23:54     ` Masami Hiramatsu
@ 2026-07-30 10:38       ` Peter Zijlstra
  0 siblings, 0 replies; 5+ messages in thread
From: Peter Zijlstra @ 2026-07-30 10:38 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Andrii Nakryiko, Oleg Nesterov, Breno Leitao, Ingo Molnar,
	Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
	James Clark, Andrii Nakryiko, linux-perf-users, linux-kernel,
	linux-trace-kernel, kernel-team, stable

On Thu, Jul 30, 2026 at 08:54:21AM +0900, Masami Hiramatsu wrote:
> On Wed, 29 Jul 2026 12:31:08 -0700
> Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote:
> 
> > On Wed, Jul 29, 2026 at 9:02 AM Oleg Nesterov <oleg@redhat.com> wrote:
> > >
> > > On 07/29, Breno Leitao wrote:
> > > >
> > > > --- a/kernel/events/uprobes.c
> > > > +++ b/kernel/events/uprobes.c
> > > > @@ -832,7 +832,7 @@ static struct uprobe *hprobe_expire(struct hprobe *hprobe, bool get)
> > > >               if (try_cmpxchg(&hprobe->state, &hstate, uprobe ? HPROBE_STABLE : HPROBE_GONE)) {
> > > >                       /* We won the race, we are the ones to unlock SRCU */
> > > >                       __srcu_read_unlock(&uretprobes_srcu, hprobe->srcu_idx);
> > > > -                     return get ? get_uprobe(uprobe) : uprobe;
> > > > +                     return get && uprobe ? get_uprobe(uprobe) : uprobe;
> > >
> > > Well, looks "obviously correct". At least the current code is obviously
> > > wrong, it even checks uprobe != NULL 3 lines above.
> > >
> > > Andrii ?
> > >
> > 
> > Yes, indeed, I'm more surprised this didn't come up much earlier
> > (probably it's rare enough to have uretprobe with refcnt at zero
> > during fork). The fix looks good, thanks!
> > 
> > Acked-by: Andrii Nakryiko <andrii@kernel.org>
> > 
> > > Acked-by: Oleg Nesterov <oleg@redhat.com>
> > >
> 
> Thanks, this seems good to me. (uprobe is NULL checked in try_cmpxchg(),
> so it could be NULL.)
> 
> Can I pick this to probes/fixes branch?

tip/perf/urgent ?

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-07-30 10:38 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-29 14:44 [PATCH] uprobes: Fix NULL pointer dereference in hprobe_expire() Breno Leitao
2026-07-29 16:02 ` Oleg Nesterov
2026-07-29 19:31   ` Andrii Nakryiko
2026-07-29 23:54     ` Masami Hiramatsu
2026-07-30 10:38       ` Peter Zijlstra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox