tech-toolchain archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Fixing $ORGIN RPATHs - at least some of them
Hey folks,
an increasing amount of software nowadays does side-by-side shared
objects (the rust compiler being the one that triggered this for
me recently), that is for example a tree structure like:
$arbitrary-install-directory/bin/mybinary
$arbitrary-install-directory/lib/liba.so
$arbitrary-install-directory/lib/libb.so
$arbitrary-install-directory/lib/libc.so
and they embed an RPATH like $ORIGIN/../lib inside mybinary.
This looks like:
Dynamic section at offset 0xaa8 contains 21 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libtest.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.12]
0x000000000000000f (RPATH) Library rpath: [$ORIGIN/../lib]
0x000000000000000c (INIT) 0x690
0x000000000000000d (FINI) 0x940
and it usually just works fine on NetBSD.
The way we do this now is pretty cheap: if the path used to exec the binary
is an absolute path, we copy it to the AUX vector and ld.elf_so retrieves
it from there.
For relative paths we have code that might work depending on the vnode
name cache, but it is racy/not always successfull and so has been
disabled for now.
Since none of our base binaries nor most pkgs from pkgsrc need $ORIGIN,
it is good to avoid expensive operations in the exec path before we even
know if $ORIGIN might be used.
We have a second method to query that path, and that is with /proc
being mounted on procfs. The code in procfs is a bit expensive, and might
fail in some environments (directory has been removed or is unaccessible),
but I guess for many programs using $ORIGIN it will not matter at all.
The patch below makes ld.elf_so try to fall back to /proc/current/exe
if the kernel did not pass an execname in AUX and $ORIGIN needs to
be expanded.
I tested it, it works, and size difference in ld.elf_so is minimal.
Any objections?
One detail I'm always unsure about: is PATH_MAX inclusive the terminating 0?
Martin
Index: expand.c
===================================================================
RCS file: /cvsroot/src/libexec/ld.elf_so/expand.c,v
retrieving revision 1.6
diff -u -p -r1.6 expand.c
--- expand.c 6 May 2013 08:02:20 -0000 1.6
+++ expand.c 5 Nov 2017 13:47:32 -0000
@@ -35,6 +35,7 @@ __RCSID("$NetBSD: expand.c,v 1.6 2013/05
#include <ctype.h>
#include <string.h>
+#include <unistd.h>
#include <sys/sysctl.h>
#ifdef DEBUG_EXPAND
@@ -75,6 +76,8 @@ expand(char *buf, const char *execname,
char *bp = buf;
size_t len;
char name[32];
+ char path[PATH_MAX];
+ ssize_t l;
switch (what) {
case 0: /* HWCAP XXX: Not yet */
@@ -82,8 +85,20 @@ expand(char *buf, const char *execname,
return 0;
case 2: /* ORIGIN */
+ if (execname == NULL) {
+ /*
+ * The kernel did not pass execname in AUX, but
+ * maybe we have /proc mounted and can get
+ * it from there?
+ */
+ l = readlink("/proc/curproc/exe", path, PATH_MAX);
+ if (l > 0) {
+ path[l] = '\0';
+ execname = path;
+ }
+ }
if (execname == NULL)
- xerr(1, "execname not specified in AUX vector");
+ xerr(1, "execname not available");
if ((ep = strrchr(p = execname, '/')) == NULL)
xerr(1, "bad execname `%s' in AUX vector", execname);
break;
Home |
Main Index |
Thread Index |
Old Index