Re: [PATCH] uprobes: Skip breakpoint installation on non executable vmas

Sumanth Korikkar <[email protected]>
Newsgroups gmane.linux.kernel
Message-ID <[email protected]>
On Wed, Aug 05, 2026 at 10:29:13AM -0700, Andrii Nakryiko wrote:
> On Wed, Aug 5, 2026 at 8:14 AM Oleg Nesterov <[email protected]> wrote:
> >
> > On 08/05, Sumanth Korikkar wrote:
> > >
> > > bpftrace  -e 'usdt:./testprogs/usdt_semaphore_test:tracetest:testprobe {
> > > printf("%s\n", str(arg1) ); exit(); }'
> >
> 
> does bpftrace care if USDT semaphore is set to 1 or 2, it shouldn't.
> As long as detaching decrements it from 2 back to zero we should be
> fine. Is that what's happening? If so, is there really a problem
> needing to be fixed?

USDT spec mentions the following:
https://sourceware.org/systemtap/wiki/UserSpaceProbeImplementation
 
If a semaphore is associated with a probe, it will be of type unsigned
short. A semaphore may gate invocations of a probe; it must be set to a
non-zero value to guarantee that the probe will be hit. "Semaphores are
treated as a counter"; your tool should increment the semaphore to enable
it, and decrement the semaphore when finished.
 
I do not know, if any application checks for exact value of 1
instead of semaphore > 0 check.

As suggested by Andrii and Oleg earlier - "uprobe_write() creates
the COW'ed anonymous page, so the 1st install_breakpoint() won't affect
the 2nd mapping to the same binary"

To me, the following looks like a valid point to consider the fix:
Installing a breakpoint on a non executable relro mapping is not useful
because instructions are not executed on it. Anonymous COW page sits
in memory untouched and memory is wasted.

> > I am hoping that Andrii and Jiri (cc'ed) can take a look, I know nothing
> > about usdt... And TBH, I don't even know what RELRO is ;)
> >
> > Let me ask a couple of questions for now.
> >
> > > expects a semaphore increment of 1, but semaphore gets double incremented
> > >
> > > Test program:
> > > https://github.com/bpftrace/bpftrace/blob/master/tests/testprogs/usdt_semaphore_test.c
> >
> > Perhaps you can provide the test-case which I could compile on my
> > machine without libbpf-usdt/usdt.h?
> >
> > And can you explain what the bpftrace cmd above actually does? I mean,
> > where does it put the uprobe? I guess the ref_ctr_offset argument of
> > uprobe_register() refers to USDT_DEFINE_SEMA() in that test-case...
> >
> > > Reason: .text mapping and RELRO mapping resolve to the same page aligned
> > > file offset 0
> > > 01000000-01001000 r-xp 00000000 5e:01 usdt_semaphore_test (.text)
> > > 01001000-01002000 r--p 00000000 5e:01 usdt_semaphore_test (RELRO)
> > > 01002000-01003000 rw-p 00001000 5e:01 usdt_semaphore_test (semaphore)
> > >
> > > valid_vma() currently accepts both mappings (which contains executable
> > > text and RELRO mapping) during uprobe registration, since both have
> > > VM_MAYEXEC set. This causes register_for_each_vma() to call
> > > install_breakpoint() twice for the same underlying uprobe offset in the
> > > process.  This means, update_ref_ctr() is called twice for the same
> > > process, so a usdt semaphore is incremented from 0 to 2.
> >
> > So, 2 vmas map the same binary, install_breakpoint() is called twice.
> > But, the 2nd install_breakpoint() -> ... -> uprobe_write() should see
> > that the original insn was already replaced by int3, in this case
> > verify_opcode() returns 0 and uprobe_write() should do nothing.
> >
> > And, if this uprobe was optimized before the 2nd install_breakpoint(),
> > uprobe_write() won't be called.
> >
> > Hmm.
> 
> Even though it's the same file offset, it is mapped to two different
> virtual addresses, so I think it should be two different memory pages
> that will have two separate int3 instructions. I don't think there is
> any contradiction or surprise, is there?

True. cross checked the behaviour with bpftrace stacktrace. Pasted the
output in previous thread.

> > > Installing a breakpoint for mapping without VM_EXEC and
> > > updating usdt reference counter in that case is not useful.
> > >
> > > Skip non VM_EXEC mappings in install_breakpoint(). This fixes semaphore
> > > double increment as shown in the above usecase.
> 
> You said that mapping is VM_MAYEXEC, which means that kernel allows to
> re-mmap it as executable, if that happens, we will miss uprobe in that
> location, so that's probably why breakpoint is installed for
> VM_MAYEXEC.

True. 
ref commit 78a320542e6c ("uprobes: Change valid_vma() to demand
VM_MAYEXEC rather than VM_EXEC")

Thank you
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.