Author: kib
Date: Thu Jan  9 10:00:24 2020
New Revision: 356548
URL: https://svnweb.freebsd.org/changeset/base/356548

Log:
  Resolve relative argv0 for direct exec mode to absolute path for AT_EXECPATH.
  
  We know the binary relative name and can reliably calculate cwd path.
  Because realpath(3) was already linked into ld-elf.so.1, reuse it
  there to resolve dots and dotdots making the path more canonical.
  
  Sponsored by: The FreeBSD Foundation
  MFC after:    1 week
  Differential revision:        https://reviews.freebsd.org/D23014

Modified:
  head/libexec/rtld-elf/rtld.c

Modified: head/libexec/rtld-elf/rtld.c
==============================================================================
--- head/libexec/rtld-elf/rtld.c        Thu Jan  9 09:47:23 2020        
(r356547)
+++ head/libexec/rtld-elf/rtld.c        Thu Jan  9 10:00:24 2020        
(r356548)
@@ -5513,9 +5513,12 @@ static int
 open_binary_fd(const char *argv0, bool search_in_path,
     const char **binpath_res)
 {
-       char *pathenv, *pe, *binpath;
+       char *abspath, *absres, *binpath, *pathenv, *pe, *res1;
+       const char *res;
        int fd;
 
+       binpath = NULL;
+       res = NULL;
        if (search_in_path && strchr(argv0, '/') == NULL) {
                binpath = xmalloc(PATH_MAX);
                pathenv = getenv("PATH");
@@ -5540,20 +5543,45 @@ open_binary_fd(const char *argv0, bool search_in_path,
                                continue;
                        fd = open(binpath, O_RDONLY | O_CLOEXEC | O_VERIFY);
                        if (fd != -1 || errno != ENOENT) {
-                               *binpath_res = binpath;
+                               res = binpath;
                                break;
                        }
                }
                free(pathenv);
        } else {
                fd = open(argv0, O_RDONLY | O_CLOEXEC | O_VERIFY);
-               *binpath_res = argv0;
+               res = argv0;
        }
-       /* XXXKIB Use getcwd() to resolve relative binpath to absolute. */
 
        if (fd == -1) {
                _rtld_error("Cannot open %s: %s", argv0, rtld_strerror(errno));
                rtld_die();
+       }
+       if (res != NULL && res[0] != '/') {
+               abspath = getcwd(NULL, 0);
+               if (abspath != NULL) {
+                       res1 = xmalloc(PATH_MAX);
+                       if (realpath(res, res1) != NULL) {
+                               if (res != argv0)
+                                       free(__DECONST(char *, res));
+                               res = res1;
+                       } else {
+                               free(res1);
+                       }
+                       absres = xmalloc(strlen(abspath) +
+                           strlen(res) + 2);
+                       strcpy(absres, abspath);
+                       strcat(absres, "/");
+                       strcat(absres, res);
+                       free(abspath);
+                       if (res != argv0)
+                               free(__DECONST(char *, res));
+                       *binpath_res = absres;
+               } else {
+                       *binpath_res = res;
+               }
+       } else {
+               *binpath_res = res;
        }
        return (fd);
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to