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

Reply via email to