Summary: | Absolute pathnames not working with libmap.conf | ||||||
---|---|---|---|---|---|---|---|
Product: | Base System | Reporter: | Tatu Kilappa <tatu.kilappa> | ||||
Component: | kern | Assignee: | Konstantin Belousov <kib> | ||||
Status: | Closed FIXED | ||||||
Severity: | Affects Some People | CC: | emaste, feld, kib | ||||
Priority: | --- | Keywords: | feature, patch | ||||
Version: | 11.0-RELEASE | ||||||
Hardware: | Any | ||||||
OS: | Any | ||||||
Attachments: |
|
A commit references this bug: Author: kib Date: Thu Jul 27 08:33:31 UTC 2017 New revision: 321607 URL: https://svnweb.freebsd.org/changeset/base/321607 Log: Allow to specify targets by absolute paths in libmap.conf. Submitted by: Tatu Kilappa <tatu.kilappa@iki.fi> PR: 221032 MFC after: 2 weeks Changes: head/libexec/rtld-elf/rtld.c A commit references this bug: Author: kib Date: Thu Aug 10 09:02:45 UTC 2017 New revision: 322346 URL: https://svnweb.freebsd.org/changeset/base/322346 Log: MFC r321607: Allow to specify targets by absolute paths in libmap.conf. PR: 221032 Changes: _U stable/11/ stable/11/libexec/rtld-elf/rtld.c MFCed Thu Aug 10 09:02:45 UTC 2017. I would like to re-open this PR as it seems this patch may be the one that broke relative paths in libmap.conf. They no longer work as of 11.2-RELEASE and this PR appears to be the reason. Anyone upgrading to 11.2-RELEASE with relative paths in their libmap.conf (as previously required) will have binaries that refuse to work due to "missing" libraries. (In reply to Mark Felder from comment #4) You report does not contain a bit of the useful information. It works for me like this: orion% cat /usr/local/etc/libmap.d/gdb.conf [/usr/local/opt/gdb-8.1/bin/gdb] libgc-threaded.so.2 libgc-threaded.so.1 orion% ldd /usr/local/opt/gdb-8.1/bin/gdb /usr/local/opt/gdb-8.1/bin/gdb: ... libgc-threaded.so.2 => /usr/local/lib/libgc-threaded.so.1 (0x801972000) ... FreeBSD 11.1-RELEASE /usr/local/etc/libmap.d/sshd.conf: [/usr/sbin/sshd] libkrb5.so.11 talos/libkrb5.so.11 $ ldd /usr/sbin/sshd | grep libkrb5 libkrb5.so.11 => /usr/local/lib/talos/libkrb5.so.11 (0x801774000) FreeBSD 11.2-RELEASE $ ldd /usr/sbin/sshd | grep libkrb libkrb5.so.11 => not found (0) Unless I change libmap config to this: [/usr/sbin/sshd] libkrb5.so.11 /usr/local/lib/talos/libkrb5.so.11 Did you checked the output of ldconfig -r ? In particular, is the /usr/local/lib/talos/ directory present in the search dir line on the problematic machine ? It seems my original patch from last summer was erroneous. I'm sorry for the trouble. I did not consider the case where libmap configuration could introduce slashes to the name, but the resulting name still was not an absolute pathname. If this happens, the block: if (strchr(name, '/') != NULL) { ... } Will of course be hit, and since the slash is not at the beginning, the name will not be accepted. After running some tests, the following beginning to find_library accepts all combinations (no path, relative path, absolute path): objgiven = refobj != NULL; if (strchr(xname, '/') != NULL) { /* Hard coded pathname */ if (xname[0] != '/' && !trust) { _rtld_error("Absolute pathname required for shared object \"%s\"", xname); return NULL; } return (origin_subst(__DECONST(Obj_Entry *, refobj), __DECONST(char *, xname))); } if (libmap_disable || !objgiven || (name = lm_find(refobj->path, xname)) == NULL) name = (char *)xname; if (name != xname && name[0] == '/') { /* libmap hard coded pathname */ return (origin_subst(__DECONST(Obj_Entry *, refobj), __DECONST(char *, name))); } So, here the beginning of the function would be exactly as before r321607, but supposing libmap returns an absolute pathname, i.e. if lm_find returned something for that differs from xname, AND that returned name begins with '/', then it can be treated like the absolute pathname earlier. But please take this with a grain of salt now, seeing as I already made an error. In particular, I'm unsure if 'origin_subst' is really necessary at the later point. Yet again, I'm sorry for the earlier error. (In reply to Tatu Kilappa from comment #8) So it is really not the relative names that do not work. It is relative _path_ which does not, for setuid binaries. I cannot decide if this is a feature or not. We do not allow to specify relative pathes in the DT_NEEDED for the suid binaries. Why should we allow that if path comes from libmap.conf. If the relative path in DT_NEEDED is a problem, then the same path after libmap translation is the problem as well. And it is, since the motivation is that we do not really know where the path ends up resolving. For now I tend to think that it is better not allowed. I think there is an inconsistency no way we think about this. Let's write all the cases down. Before the patch from last summer: 1) Relative paths from DT_NEEDED do not work. - Unless 'trust' is set. 2) Absolute paths from DT_NEEDED work. 3) Relative paths from libmap.conf work. - 'trust' does not matter. 4) Absolute paths from libmap.conf do not work. This presents us with an inconsistency, since clearly absolute paths are okay if they're in the headers, but they somehow do not work coming from libmap.conf, because the full pathname is just subjected to normal library search. After the patch: 1) Relative paths from DT_NEEDED do not work. - Unless 'trust' is set. 2) Absolute paths from DT_NEEDED work. 3) Relative paths from libmap.conf do not work. - 'trust' does not matter. 4) Absolute paths from libmap.conf work. It's still not consistent, and this was my error, as said above. If relative paths work from DT_NEEDED should 'trust' be set, they propably should work the same way from libmap.conf to be consistent. About relative paths from libmap.conf working regardless of 'trust' I have no opinion of, since I'm not a security expert, and I'd like to not make any more of a fool of myself. (In reply to Tatu Kilappa from comment #10) From the find_library() code, it seems that relative pathes from libmap works iff trust is set, same as DT_NEEDED, no ? Yeah, true, they indeed work exactly the same way. But if I can still ask one question... As far as I can see, library names with relative path are never searched from library paths (if there's a '/', it never goes to the end of find_library). Doesn't it then open with relative path from current location? And if yes, why is this ok but searching is not? (In reply to Tatu Kilappa from comment #13) I can see the at least one purpose of allowing the relative pathes, it is the $ORIGIN token substitution. If you have the path like $ORIGIN/../lib/libmylib.so.1, it is 1. relative 2. should work. It might be that we can further tight the handling of the relative paths by requiring the absolute path after the tokens expansiton, but we might be also friendly for the developers who link locally for debugging purposes with the relative paths. I do not know enough of the real world usage there to state an opinion. |
Created attachment 184747 [details] Patch to enable absolute pathname as target in libmap.conf It seems it's not possible to replace entries in libmap configuration with absolute pathnames and have them work. For example, consider installing Nvidia driver from package or ports, it will create the following libmap directive: libGL.so libGL-NVIDIA.so libGL.so.1 libGL-NVIDIA.so.1 While investigating other things, I found out that replacing the target shared object with the following: libGL.so /usr/local/lib/libGL-NVIDIA.so.1 Creates an error: Shared object "/usr/local/lib/libGL-NVIDIA.so.1" not found, required by "<binary>" The problem lies in rtld.c line 1519 and onward, that checks for absolute path before going to lm_find. This means, that if libmap.conf contains a mapping with an absolute pathname, it will try to search that name from the library search paths, which will obviously not work. I've attached a patch that fixes the issue at least for me. If current behavior is intended, or if this should be handled elsewhere, please disregard this bug report.