Bug 17251 - RPATH of shared libraries doesn't follow symlinks for $ORIGIN
Summary: RPATH of shared libraries doesn't follow symlinks for $ORIGIN
Status: NEW
Alias: None
Product: glibc
Classification: Unclassified
Component: dynamic-link (show other bugs)
Version: 2.19
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-08-10 17:00 UTC by Brennan Shacklett
Modified: 2018-06-06 03:50 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments
Patch to switch $ORIGIN to be calculated based on absolute path (4.05 KB, patch)
2014-08-12 16:05 UTC, Brennan Shacklett
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Brennan Shacklett 2014-08-10 17:00:28 UTC
t


I'm not 100% sure if this a bug or intended behavior, I can't find any evidence for either argument.
Comment 1 Brennan Shacklett 2014-08-10 17:10:55 UTC
Oops, sorry for the empty description, firefox decided to submit the form when I hit enter.
The issue is that if a shared library has $ORIGIN in its RPATH, $ORIGIN is not calculated as the real path of the library.

This can easily be shown with two shared libraries and a symlink:

libone.so and libtwo.so are both in a directory named ~/lib
libone.so needs libtwo.so, and has an RPATH of "$ORIGIN" so libtwo.so can be found.
If I cd into ~/lib and run ldd on libone.so, libtwo.so is found.
If I create a symlink from ~/libone.so to ~/lib/libone.so, and run ldd on the symlink at ~/libone.so, libtwo.so can no longer be found because $ORIGIN is not calculated as ~ rather than ~/lib
Comment 2 Brennan Shacklett 2014-08-12 04:25:09 UTC
s/is not calculated/is calculated/ in the last sentence.
Comment 3 Brennan Shacklett 2014-08-12 16:05:07 UTC
Created attachment 7744 [details]
Patch to switch $ORIGIN to be calculated based on absolute path

This patch fixes the behavior for me, I'll also post it to the mailing list with an explanation.
Comment 4 Florian Weimer 2014-08-14 12:47:26 UTC
I'm not sure if you can use __realpath from the dynamic linker.  And PATH_MAX could be too small; the __realpath function with a non-NULL second argument is basically broken.
Comment 5 Brennan Shacklett 2014-08-14 15:59:07 UTC
Well I defined __realpath in dl-realpath.c and included that into rtld-routines, doesn't that allow the linker to use it?
I'm not sure what you mean about __realpath being broken with a non null 2nd argument, the version which I defined in dl-realpath doesn't even handle a NULL second argument (I didn't think it was necessary). Are you saying I should rewrite the dl-realpath version to handle that NULL and dynamically allocate its own memory?

There is a more detailed explanation in my mailing list post here: https://sourceware.org/ml/libc-alpha/2014-08/msg00160.html if you want more details.
Comment 6 Florian Weimer 2014-08-18 15:28:35 UTC
(In reply to Brennan Shacklett from comment #5)
> Well I defined __realpath in dl-realpath.c and included that into
> rtld-routines, doesn't that allow the linker to use it?

Ah, I missed the reimplementation.  I'll post further questions to the mailing list.
Comment 7 Carlos O'Donell 2018-06-05 03:46:15 UTC
Note that the gABI says:
~~~
Within a string provided by dynamic array entries with the DT_NEEDED or DT_RUNPATH tags and in pathnames passed as parameters to the dlopen() routine, a dollar sign ($) introduces a substitution sequence.
...
If the name is ``ORIGIN'', then the substitution sequence is replaced by the dynamic linker with the absolute pathname of the directory in which the object containing the substitution sequence originated. Moreover, the pathname will contain no symbolic links or use of ``.'' or ``..'' components. Otherwise (when the name is not ``ORIGIN'') the behavior of the dynamic linker is unspecified. 
~~~
http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#shobj_dependencies

It seems to me that the entire sequence, including $ORIGIN, is considered a "pathname", and that "pathname" should contain no symbolic links, ".", or ".." components.

Therefore following symlinks seems against the specification of $ORIGIN?
Comment 8 Florian Weimer 2018-06-05 03:56:25 UTC
(In reply to Carlos O'Donell from comment #7)
> Note that the gABI says:
> ~~~
> Within a string provided by dynamic array entries with the DT_NEEDED or
> DT_RUNPATH tags and in pathnames passed as parameters to the dlopen()
> routine, a dollar sign ($) introduces a substitution sequence.
> ...
> If the name is ``ORIGIN'', then the substitution sequence is replaced by the
> dynamic linker with the absolute pathname of the directory in which the
> object containing the substitution sequence originated. Moreover, the
> pathname will contain no symbolic links or use of ``.'' or ``..''
> components. Otherwise (when the name is not ``ORIGIN'') the behavior of the
> dynamic linker is unspecified. 
> ~~~
> http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#shobj_dependencies
> 
> It seems to me that the entire sequence, including $ORIGIN, is considered a
> "pathname", and that "pathname" should contain no symbolic links, ".", or
> ".." components.
> 
> Therefore following symlinks seems against the specification of $ORIGIN?

Isn't it saying the opposite, that symbolic links must be resolved in the expansion of $ORIGIN?
Comment 9 Carlos O'Donell 2018-06-05 11:39:12 UTC
(In reply to Florian Weimer from comment #8)
> (In reply to Carlos O'Donell from comment #7)
> > Note that the gABI says:
> > ~~~
> > Within a string provided by dynamic array entries with the DT_NEEDED or
> > DT_RUNPATH tags and in pathnames passed as parameters to the dlopen()
> > routine, a dollar sign ($) introduces a substitution sequence.
> > ...
> > If the name is ``ORIGIN'', then the substitution sequence is replaced by the
> > dynamic linker with the absolute pathname of the directory in which the
> > object containing the substitution sequence originated. Moreover, the
> > pathname will contain no symbolic links or use of ``.'' or ``..''
> > components. Otherwise (when the name is not ``ORIGIN'') the behavior of the
> > dynamic linker is unspecified. 
> > ~~~
> > http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#shobj_dependencies
> > 
> > It seems to me that the entire sequence, including $ORIGIN, is considered a
> > "pathname", and that "pathname" should contain no symbolic links, ".", or
> > ".." components.
> > 
> > Therefore following symlinks seems against the specification of $ORIGIN?
> 
> Isn't it saying the opposite, that symbolic links must be resolved in the
> expansion of $ORIGIN?

Oh, I see how you could interpret that.

You are saying that the phrasing "absolute pathname of the directory" means that symbolic links *must* be dereferenced?

I was looking at the phrasing "the pathname will contain no symbolic links" as meaning that the pathname *before* the expansion shall contain no symbolic links, otherwise the behaviour of the dynamic linker is unspecified. That the intent of the authors was to simplify the dynamic linker implementation to not have to handle the path expansion and symbolic link following to compute the path name.

Which interpretation was yours?
Comment 10 Andreas Schwab 2018-06-05 12:15:42 UTC
Symbolic links must be resolved, like realpath.
Comment 11 Carlos O'Donell 2018-06-05 13:21:33 UTC
(In reply to Andreas Schwab from comment #10)
> Symbolic links must be resolved, like realpath.

Is your suggestion that the final absolute path computed from the DT_NEEDED or DT_RPATH or DT_RUNPATH, contain a path that has no symbolic links or back/current references?
Comment 12 Andreas Schwab 2018-06-05 13:47:18 UTC
As written in the gABI, $ORIGIN must be fully resolved.  This is unambigous.
Comment 13 Carlos O'Donell 2018-06-06 03:50:40 UTC
(In reply to Andreas Schwab from comment #12)
> As written in the gABI, $ORIGIN must be fully resolved.  This is unambigous.

I agree.

I'm not going to fix this issue in my current round of cleanups, it's sufficiently orthogonal that it can be cleaned up later. Though I am fixing bug 23102, and bug 23259 (with a patch based on your Fedora patch).