138 sets NODEFLIB on the user app (the root of the dynamic object tree) in an attempt to prevent libraries from the target system from ever being loaded. This, coupled with RPATH, was supposed to give the (runtime patched) app complete control over the set of libraries loaded.
The problem is that if any object down the tree has RUNPATH set, not only is the root RPATH ignored, but somehow NODEFLIB seems to be ignored too! I don't actually see this in the source code yet, but it's a bit hard to follow.
One might think that the solution would be for Staticx to use RUNPATH instead, but alas, that only applies to the object on which it is applied, and not the tree.
The trouble with RUNPATH and the reason we won’t use it is that it’s search semantics are fundamentally broken. It isn’t just a difference in precedence. Whereas an RPATH’d binary will search its RPATH, it’s loading object’s RPATH, all the way up to the executable if need be, RUNPATH gives up after searching the RUNPATH of the object itself. This means that the executable can’t enforce consistent link semantics...
In other words:
RPATH binary will search
Its own RPATH
The loading object's RPATH
...
The executable's RPATH
Stop
RUNPATH binary will search
Its own RUNPATH
Stop
This is extremely discouraging. I'm running out of tricks for defeating GLIBC.
138 sets
NODEFLIB
on the user app (the root of the dynamic object tree) in an attempt to prevent libraries from the target system from ever being loaded. This, coupled withRPATH
, was supposed to give the (runtime patched) app complete control over the set of libraries loaded.The problem is that if any object down the tree has
RUNPATH
set, not only is the rootRPATH
ignored, but somehowNODEFLIB
seems to be ignored too! I don't actually see this in the source code yet, but it's a bit hard to follow.See https://github.com/JonathonReinhart/staticx/issues/159#issuecomment-711414273 where I originally figured all of this out.
One might think that the solution would be for Staticx to use
RUNPATH
instead, but alas, that only applies to the object on which it is applied, and not the tree.From this comment:
In other words:
RPATH
binary will searchRPATH
RPATH
RPATH
RUNPATH
binary will searchRUNPATH
This is extremely discouraging. I'm running out of tricks for defeating GLIBC.
Damn you, @drepper! :smiling_imp: (Reference: https://github.com/bminor/glibc/commit/fcf70d4114db9ff7923f5dfeb3fea6e2d623e5c2)
My original comment had some half-baked ideas for fixing/working-around/acknowledging this.