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?

> 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?

>
> > 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.

Anyways, I'm just not sure whether there is a real issue we are
fixing, or it's just a proactive fix just in case. Can you elaborate?

> >
> > Signed-off-by: Sumanth Korikkar <[email protected]>
> > ---
> >  kernel/events/uprobes.c | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> > index 6300b216012c..9e0bbc3cf401 100644
> > --- a/kernel/events/uprobes.c
> > +++ b/kernel/events/uprobes.c
> > @@ -1155,6 +1155,9 @@ static int install_breakpoint(struct uprobe *uprobe, 
> > struct vm_area_struct *vma,
> >       bool first_uprobe;
> >       int ret;
> >
> > +     if (!(vma->vm_flags & VM_EXEC))
> > +             return 0;
> > +
>
> Well, but then it makes more sense to change valid_vma() to nack the
> non VM_EXEC mappings ?
>
> Oleg.
>

Reply via email to