On Mon, 23 Dec 2024, Florian Weimer via Gcc wrote:

> * Alexander Monakov:
> >> Does this work on all primary GCC targets?
> >
> > Yes? I'm not sure why you think it might not work. What are your
> > concerns?
> 
> Targets not setting up REGISTER_NAMES, not mentioning the static chain
> pointer register in it (not sure if that is even logically possible).

I provided one example where static chain pointer becomes unavailable
(32-bit x86 with -mregparm=3), I suspect there may be others.

> >> > This is the only approach I'm aware of, apart of generating wrappers
> >> > in asm (speaking of, is there some reason that wouldn't work for you?).
> >> 
> >> You mean wrappers that inject the extra argument?  That doesn't work for
> >> variadic functions.
> >
> > Why not? I find that generating a _tailcalling_ wrapper works much better
> > in asm than in C.
> 
> Sure, but tail-calling wrappers are not really wrappers, they are a bit
> too one-sided for that.
> 
> >> It's also likely to break with unexpected calling
> >> conventions.  Variadic functions are always problematic because you
> >> can't directly forward to the original function.
> >
> > Erm, what? Surely you can, by performing a tailcall (in asm).
> 
> But that's about it.  You can't actually wrap the call (running your own
> code before and after it) because the original argument area won't be at
> the right offset, and working around that in a generic fashion requires
> really weird tricks.  At this point you are likely better offer with
> uprobes and similar tools.

Well, the first paragraph in your initial mail was talking very explicitly
about making a tailcall from the wrapper, so I guess the goalpost has moved.

If audit authors need to hook returns, let them do it in whatever manner
they find most suitable, like invoking the auditee from the hook if they
know its prototype, or finding a place to stash the replaced return address.
You cannot provide efficient return hooking from libc side anyway.

> LD_AUDIT offers outright replacement of the address for this scenario,
> but it breaks down if the targeted shared object is loaded multiple
> times (either literally into different dynamic linker namespaces, or
> conceptually, with different sonames).  This is where LD_PRELOAD
> wrapping becomes problematic, true.  With address replacement, there is
> just no contextual information at all provided by the dynamic linker.
> If you need it, you need to generate your own trampoline.  And then we
> end up with the question how the trampoline can forward the information
> to the wrapping function.  (Without multiple instances, you could just
> store the real implementation address and information about the shared
> object or the implementation in global variables.)

If audit authors need that kind of dynamic granularity, teach them how
to create new copies of hooks at runtime (place hooks in a DSO without
an soname, create a new symlink to that dso, dlopen the symlink). Or
provide a dlopen flag to achieve the same without the symlink.

HTH
Alexander

Reply via email to