? sys/sys/.arch-ids ? libexec/rtld-elf/.arch-ids ? libexec/rtld-elf/alpha/.arch-ids ? libexec/rtld-elf/amd64/.arch-ids ? libexec/rtld-elf/arm/.arch-ids ? libexec/rtld-elf/i386/.arch-ids ? libexec/rtld-elf/ia64/.arch-ids ? libexec/rtld-elf/powerpc/.arch-ids ? libexec/rtld-elf/sparc64/.arch-ids Index: sys/sys/elf_common.h =================================================================== RCS file: /usr/local/arch/ncvs/src/sys/sys/elf_common.h,v retrieving revision 1.22 diff -u -r1.22 elf_common.h --- sys/sys/elf_common.h 3 Apr 2007 01:47:07 -0000 1.22 +++ sys/sys/elf_common.h 18 Apr 2007 12:01:01 -0000 @@ -398,6 +398,11 @@ executable contains code using a static thread-local storage scheme. */ +/* Values for DT_FLAGS_1 */ +#define DF_1_BIND_NOW 0x00000001 /* Same as DF_BIND_NOW */ +#define DF_1_GLOBAL 0x00000002 /* Set the RTLD_GLOBAL for object */ +#define DF_1_ORIGIN 0x00000080 /* Process $ORIGIN */ + /* Values for n_type. Used in core files. */ #define NT_PRSTATUS 1 /* Process status. */ #define NT_FPREGSET 2 /* Floating point registers. */ Index: libexec/rtld-elf/map_object.c =================================================================== RCS file: /usr/local/arch/ncvs/src/libexec/rtld-elf/map_object.c,v retrieving revision 1.18 diff -u -r1.18 map_object.c --- libexec/rtld-elf/map_object.c 3 Apr 2007 18:31:20 -0000 1.18 +++ libexec/rtld-elf/map_object.c 18 Apr 2007 12:01:01 -0000 @@ -346,8 +346,10 @@ } if (obj->vertab) free(obj->vertab); - if (obj->origin_path) + if (obj->origin_path) { + free((char *)obj->rpath); free(obj->origin_path); + } if (obj->priv) free(obj->priv); if (obj->path) Index: libexec/rtld-elf/rtld.c =================================================================== RCS file: /usr/local/arch/ncvs/src/libexec/rtld-elf/rtld.c,v retrieving revision 1.122 diff -u -r1.122 rtld.c --- libexec/rtld-elf/rtld.c 7 Apr 2007 23:17:00 -0000 1.122 +++ libexec/rtld-elf/rtld.c 18 Apr 2007 12:01:01 -0000 @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -134,6 +135,9 @@ static void unload_object(Obj_Entry *); static void unref_dag(Obj_Entry *); static void ref_dag(Obj_Entry *); +static int origin_subst_one(char **res, const char *real, const char *kw, + const char *subst, int may_free); +static const char *origin_subst(const char *real, const char *origin_path); static int rtld_verify_versions(const Objlist *); static int rtld_verify_object_versions(Obj_Entry *); static void object_add_name(Obj_Entry *, const char *); @@ -602,6 +606,85 @@ return p != NULL ? p + 1 : name; } +static struct utsname uts; + +static int +origin_subst_one(char **res, const char *real, const char *kw, + const char *subst, int may_free) +{ + const char *p, *p1; + char *res1; + int subst_len; + int kw_len; + + res1 = *res = NULL; + p = real; + subst_len = kw_len = 0; + for (;;) { + p1 = strstr(p, kw); + if (p1 != NULL) { + if (subst_len == 0) { + subst_len = strlen(subst); + kw_len = strlen(kw); + } + if (*res == NULL) { + *res = xmalloc(PATH_MAX); + res1 = *res; + } + if ((res1 - *res) + subst_len + (p1 - p) >= PATH_MAX) { + _rtld_error("Substitution of %s in %s cannot " + "be performed", kw, real); + if (may_free) + free((char *)real); + free(res); + return (false); + } + memcpy(res1, p, p1 - p); + res1 += p1 - p; + memcpy(res1, subst, subst_len); + res1 += subst_len; + p = p1 + kw_len; + } else { + if (*res == NULL) { + *res = (char *)real; + return (true); + } + *res1 = '\0'; + if (may_free) + free((char *)real); + if (strlcat(res1, p, PATH_MAX - (res1 - *res)) >= + PATH_MAX) { + free(res); + return (false); + } + return (true); + } + } +} + +static const char * +origin_subst(const char *real, const char *origin_path) +{ + char *res1, *res2, *res3, *res4; + + if (uts.sysname[0] == '\0') { + if (uname(&uts) != 0) { + _rtld_error("utsname failed: %d", errno); + return NULL; + } + } + if (!origin_subst_one(&res1, real, "$ORIGIN", + origin_path, false) || + !origin_subst_one(&res2, res1, "$OSNAME", + uts.sysname, res1 != real) || + !origin_subst_one(&res3, res2, "$OSREL", + uts.release, res2 != real) || + !origin_subst_one(&res4, res3, "$PLATFORM", + uts.machine, res3 != real)) + return (NULL); + return (res4); +} + static void die(void) { @@ -771,10 +854,11 @@ break; case DT_FLAGS: - if (dynp->d_un.d_val & DF_ORIGIN) { - obj->origin_path = xmalloc(PATH_MAX); - if (rtld_dirname(obj->path, obj->origin_path) == -1) - die(); + if ((dynp->d_un.d_val & DF_ORIGIN) && trust && + obj->origin_path == NULL) { + obj->origin_path = xmalloc(PATH_MAX); + if (rtld_dirname(obj->path, obj->origin_path) == -1) + die(); } if (dynp->d_un.d_val & DF_SYMBOLIC) obj->symbolic = true; @@ -786,6 +870,19 @@ ; break; + case DT_FLAGS_1: + if ((dynp->d_un.d_val & DF_1_ORIGIN) && !issetugid() && + obj->origin_path == NULL) { + obj->origin_path = xmalloc(PATH_MAX); + if (rtld_dirname(obj->path, obj->origin_path) == -1) + die(); + } + if (dynp->d_un.d_val & DF_1_GLOBAL) + /* XXX */; + if (dynp->d_un.d_val & DF_1_BIND_NOW) + obj->bind_now = true; + break; + default: if (!early) { dbg("Ignoring d_tag %ld = %#lx", (long)dynp->d_tag, @@ -804,8 +901,11 @@ obj->pltrelsize = 0; } - if (dyn_rpath != NULL) + if (dyn_rpath != NULL) { obj->rpath = obj->strtab + dyn_rpath->d_un.d_val; + if (obj->origin_path != NULL) + obj->rpath = origin_subst(obj->rpath, obj->origin_path); + } if (dyn_soname != NULL) object_add_name(obj, obj->strtab + dyn_soname->d_un.d_val); @@ -956,6 +1056,7 @@ { char *pathname; char *name; + char *rname; if (strchr(xname, '/') != NULL) { /* Hard coded pathname */ if (xname[0] != '/' && !trust) { @@ -963,6 +1064,12 @@ xname); return NULL; } + if (refobj->origin_path) { + rname = (char *)origin_subst(xname, refobj->origin_path); + if (rname == xname) + rname = xstrdup(rname); + return rname; + } return xstrdup(xname); }