Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 9 Jan 2020 09:14:54 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r356544 - stable/12/libexec/rtld-elf
Message-ID:  <202001090914.0099EsSn043756@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Thu Jan  9 09:14:54 2020
New Revision: 356544
URL: https://svnweb.freebsd.org/changeset/base/356544

Log:
  MFC r356300, r356503:
  Fix AT_EXECPATH for direct exec mode.

Modified:
  stable/12/libexec/rtld-elf/rtld.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/libexec/rtld-elf/rtld.c
==============================================================================
--- stable/12/libexec/rtld-elf/rtld.c	Thu Jan  9 08:29:31 2020	(r356543)
+++ stable/12/libexec/rtld-elf/rtld.c	Thu Jan  9 09:14:54 2020	(r356544)
@@ -134,7 +134,8 @@ static void objlist_push_head(Objlist *, Obj_Entry *);
 static void objlist_push_tail(Objlist *, Obj_Entry *);
 static void objlist_put_after(Objlist *, Obj_Entry *, Obj_Entry *);
 static void objlist_remove(Objlist *, Obj_Entry *);
-static int open_binary_fd(const char *argv0, bool search_in_path);
+static int open_binary_fd(const char *argv0, bool search_in_path,
+    const char **binpath_res);
 static int parse_args(char* argv[], int argc, bool *use_pathp, int *fdp);
 static int parse_integer(const char *);
 static void *path_enumerate(const char *, path_enum_proc, const char *, void *);
@@ -379,7 +380,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entr
     struct stat st;
     Elf_Addr *argcp;
     char **argv, **env, **envp, *kexecpath, *library_path_rpath;
-    const char *argv0;
+    const char *argv0, *binpath;
     caddr_t imgentry;
     char buf[MAXPATHLEN];
     int argc, fd, i, phnum, rtld_argc;
@@ -441,8 +442,9 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entr
 		rtld_argc = parse_args(argv, argc, &search_in_path, &fd);
 		argv0 = argv[rtld_argc];
 		explicit_fd = (fd != -1);
+		binpath = NULL;
 		if (!explicit_fd)
-		    fd = open_binary_fd(argv0, search_in_path);
+		    fd = open_binary_fd(argv0, search_in_path, &binpath);
 		if (fstat(fd, &st) == -1) {
 		    _rtld_error("Failed to fstat FD %d (%s): %s", fd,
 		      explicit_fd ? "user-provided descriptor" : argv0,
@@ -495,11 +497,24 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entr
 		} while (*envp != NULL);
 		aux = auxp = (Elf_Auxinfo *)envp;
 		auxpf = (Elf_Auxinfo *)(envp + rtld_argc);
+		/* XXXKIB insert place for AT_EXECPATH if not present */
 		for (;; auxp++, auxpf++) {
 		    *auxp = *auxpf;
 		    if (auxp->a_type == AT_NULL)
 			    break;
 		}
+
+		/* Point AT_EXECPATH auxv and aux_info to the binary path. */
+		if (binpath == NULL) {
+		    aux_info[AT_EXECPATH] = NULL;
+		} else {
+		    if (aux_info[AT_EXECPATH] == NULL) {
+			aux_info[AT_EXECPATH] = xmalloc(sizeof(Elf_Auxinfo));
+			aux_info[AT_EXECPATH]->a_type = AT_EXECPATH;
+		    }
+		    aux_info[AT_EXECPATH]->a_un.a_ptr = __DECONST(void *,
+		      binpath);
+		}
 	    } else {
 		_rtld_error("No binary");
 		rtld_die();
@@ -5453,12 +5468,14 @@ symlook_init_from_req(SymLook *dst, const SymLook *src
 }
 
 static int
-open_binary_fd(const char *argv0, bool search_in_path)
+open_binary_fd(const char *argv0, bool search_in_path,
+    const char **binpath_res)
 {
-	char *pathenv, *pe, binpath[PATH_MAX];
+	char *pathenv, *pe, *binpath;
 	int fd;
 
 	if (search_in_path && strchr(argv0, '/') == NULL) {
+		binpath = xmalloc(PATH_MAX);
 		pathenv = getenv("PATH");
 		if (pathenv == NULL) {
 			_rtld_error("-p and no PATH environment variable");
@@ -5472,24 +5489,25 @@ open_binary_fd(const char *argv0, bool search_in_path)
 		fd = -1;
 		errno = ENOENT;
 		while ((pe = strsep(&pathenv, ":")) != NULL) {
-			if (strlcpy(binpath, pe, sizeof(binpath)) >=
-			    sizeof(binpath))
+			if (strlcpy(binpath, pe, PATH_MAX) >= PATH_MAX)
 				continue;
 			if (binpath[0] != '\0' &&
-			    strlcat(binpath, "/", sizeof(binpath)) >=
-			    sizeof(binpath))
+			    strlcat(binpath, "/", PATH_MAX) >= PATH_MAX)
 				continue;
-			if (strlcat(binpath, argv0, sizeof(binpath)) >=
-			    sizeof(binpath))
+			if (strlcat(binpath, argv0, PATH_MAX) >= PATH_MAX)
 				continue;
 			fd = open(binpath, O_RDONLY | O_CLOEXEC | O_VERIFY);
-			if (fd != -1 || errno != ENOENT)
+			if (fd != -1 || errno != ENOENT) {
+				*binpath_res = binpath;
 				break;
+			}
 		}
 		free(pathenv);
 	} else {
 		fd = open(argv0, O_RDONLY | O_CLOEXEC | O_VERIFY);
+		*binpath_res = argv0;
 	}
+	/* XXXKIB Use getcwd() to resolve relative binpath to absolute. */
 
 	if (fd == -1) {
 		_rtld_error("Cannot open %s: %s", argv0, rtld_strerror(errno));



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202001090914.0099EsSn043756>