bin/88117: support of $ORIGIN in rtld-elf.

Nakata Maho maho at FreeBSD.org
Fri Oct 28 00:00:30 PDT 2005


>Number:         88117
>Category:       bin
>Synopsis:       support of $ORIGIN in rtld-elf.
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Oct 28 07:00:28 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Nakata Maho
>Release:        5.4-RELEASE
>Organization:
FreeBSD.org
>Environment:
FreeBSD satie.private.org 5.4-RELEASE-p6 FreeBSD 5.4-RELEASE-p6 #0: Sat Sep  3 09:47:26 JST 2005     maho at satie.private.org:/usr/src/sys/i386/compile/MAHO  i386
>Description:
if $ORIGIN is passed via -rpath, option of ld, we replace $ORIGIN
by full path of current directory where the execultables or shared
libs exist.

e.g.
% pwd
/u/l/c
gcc -Wl,-rpath,'$ORIGIN' foo.o -ltest1 -ltest2
ldd ./a.out
./a.out
        libc.so.5 => /lib/libc.so.5 (0x123333)
        libtest1.so.6 => /u/l/c/libtest1.so.6 (0x12345678)
        libtest2.so.3 => /u/l/c/libtest2.so.3 (0x90ABCDEF)

etc. we also allow such usage as well, like LD_LIBRARY_PATH.
gcc -Wl,-rpath,'$ORIGIN/../:$ORIGIN' foo.o -ltest1 -ltest2


>How-To-Repeat:
              
>Fix:
              --- /usr/src/libexec/rtld-elf/rtld.c.org        Sun Oct 23 19:11:26 2005
+++ /usr/src/libexec/rtld-elf/rtld.c    Tue Oct 25 14:49:34 2005
@@ -862,6 +862,10 @@
 {
     char *pathname;
     char *name;
+    char *rpath;
+    char *origin_realpath;
+    char *p, *q, *r;
+    int i;

     if (strchr(xname, '/') != NULL) {  /* Hard coded pathname */
        if (xname[0] != '/' && !trust) {
@@ -878,9 +882,31 @@

     dbg(" Searching for \"%s\"", name);

+/* expand $ORIGIN in refobj->rpath if not NULL */
+    rpath=NULL;
+    if(refobj->rpath!=NULL){
+      rpath = xmalloc(PATH_MAX);           /* full rpath with $ORIGIN expanded */
+      origin_realpath = xmalloc(PATH_MAX);
+      realpath(refobj->path, origin_realpath); /* expand $ORIGIN by real path */
+      i=strlen(origin_realpath);
+      while(origin_realpath[i]!='/') {origin_realpath[i--]='\0';} origin_realpath[i]='\0';/* basename */
+      q=(char *)refobj->rpath;
+      p=strstr(q,"$ORIGIN");
+      r=rpath;
+      if(p==NULL) {rpath=(char *)refobj->rpath;}else{
+       while(p!=NULL){
+       for(i=0;q+i<p;i++){ *(r++)=*(q+i);}
+       strcpy(r,origin_realpath);
+       r=r+strlen(origin_realpath);
+       q=p+strlen("$ORIGIN");
+       p=strstr(q,"$ORIGIN");
+       }
+      }
+    }
+
     if ((pathname = search_library_path(name, ld_library_path)) != NULL ||
       (refobj != NULL &&
-      (pathname = search_library_path(name, refobj->rpath)) != NULL) ||
+      (pathname = search_library_path(name, rpath)) != NULL) ||
       (pathname = search_library_path(name, gethints())) != NULL ||
       (pathname = search_library_path(name, STANDARD_LIBRARY_PATH)) != NULL)
        return pathname;


I don't know how to free rpath and origin_realpath...

>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list