Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Aug 2021 12:06:49 GMT
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 451dc2b7cc0c - main - rtld: rework how environment variables are named
Message-ID:  <202108171206.17HC6nwI038586@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=451dc2b7cc0c845a3f76f9ee670f16699c49b491

commit 451dc2b7cc0c845a3f76f9ee670f16699c49b491
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2021-08-15 18:57:42 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2021-08-17 12:05:46 +0000

    rtld: rework how environment variables are named
    
    Instead of specifying the main name part of the environment variable as the
    string literal, create array of the var names and access them by symbolic
    index.  Convert main name parts into complete names by prefixing with
    ABI-specific ld_env_vars.
    
    This way the name is not repeated, and also it can carry additional
    proporties explicitly.  For instance, cleanup of the environment for
    the setuid image does not require retyping all names.
    
    Reviewed by:    arichardson, markj
    MFC after:      1 week
    Sponsored by:   The FreeBSD Foundation
    Differential revision:  https://reviews.freebsd.org/D31545
---
 libexec/rtld-elf/arm/rtld_machdep.h |   1 -
 libexec/rtld-elf/rtld.c             | 178 ++++++++++++++++++++++++++----------
 2 files changed, 131 insertions(+), 48 deletions(-)

diff --git a/libexec/rtld-elf/arm/rtld_machdep.h b/libexec/rtld-elf/arm/rtld_machdep.h
index d890cb377fa3..26e677f26d5a 100644
--- a/libexec/rtld-elf/arm/rtld_machdep.h
+++ b/libexec/rtld-elf/arm/rtld_machdep.h
@@ -80,7 +80,6 @@ extern void arm_abi_variant_hook(Elf_Auxinfo **);
 
 #ifdef __ARM_FP
 #define md_abi_variant_hook(x)		arm_abi_variant_hook(x)
-#define RTLD_VARIANT_ENV_NAMES
 #else
 #define md_abi_variant_hook(x)
 #endif
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 61b823aaacf8..6826dde8a160 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -342,23 +342,106 @@ ld_utrace_log(int event, void *handle, void *mapbase, size_t mapsize,
 	utrace(&ut, sizeof(ut));
 }
 
-#ifdef RTLD_VARIANT_ENV_NAMES
-/*
- * construct the env variable based on the type of binary that's
- * running.
- */
-static inline const char *
-_LD(const char *var)
+enum {
+	LD_BIND_NOW = 0,
+	LD_PRELOAD,
+	LD_LIBMAP,
+	LD_LIBRARY_PATH,
+	LD_LIBRARY_PATH_FDS,
+	LD_LIBMAP_DISABLE,
+	LD_BIND_NOT,
+	LD_DEBUG,
+	LD_ELF_HINTS_PATH,
+	LD_LOADFLTR,
+	LD_LIBRARY_PATH_RPATH,
+	LD_PRELOAD_FDS,
+	LD_DYNAMIC_WEAK,
+	LD_TRACE_LOADED_OBJECTS,
+	LD_UTRACE,
+	LD_DUMP_REL_PRE,
+	LD_DUMP_REL_POST,
+	LD_TRACE_LOADED_OBJECTS_PROGNAME,
+	LD_TRACE_LOADED_OBJECTS_FMT1,
+	LD_TRACE_LOADED_OBJECTS_FMT2,
+	LD_TRACE_LOADED_OBJECTS_ALL,
+};
+
+struct ld_env_var_desc {
+	char n[64];
+	bool unsecure;
+};
+
+static struct ld_env_var_desc ld_env_vars[] = {
+	[LD_BIND_NOW] =
+	    { .n = "BIND_NOW", .unsecure = false },
+	[LD_PRELOAD] =
+	    { .n = "PRELOAD", .unsecure = true },
+	[LD_LIBMAP] =
+	    { .n = "LIBMAP", .unsecure = true },
+	[LD_LIBRARY_PATH] =
+	    { .n = "LIBRARY_PATH", .unsecure = true },
+	[LD_LIBRARY_PATH_FDS] =
+	    { .n = "LIBRARY_PATH_FDS", .unsecure = true },
+	[LD_LIBMAP_DISABLE] =
+	    { .n = "LIBMAP_DISABLE", .unsecure = true },
+	[LD_BIND_NOT] =
+	    { .n = "BIND_NOT", .unsecure = true },
+	[LD_DEBUG] =
+	    { .n = "DEBUG", .unsecure = true },
+	[LD_ELF_HINTS_PATH] =
+	    { .n = "ELF_HINTS_PATH", .unsecure = true },
+	[LD_LOADFLTR] =
+	    { .n = "LOADFLTR", .unsecure = true },
+	[LD_LIBRARY_PATH_RPATH] =
+	    { .n = "LIBRARY_PATH_RPATH", .unsecure = true },
+	[LD_PRELOAD_FDS] =
+	    { .n = "PRELOAD_FDS", .unsecure = true },
+	[LD_DYNAMIC_WEAK] =
+	    { .n = "DYNAMIC_WEAK", .unsecure = true },
+	[LD_TRACE_LOADED_OBJECTS] =
+	    { .n = "TRACE_LOADED_OBJECTS", .unsecure = false },
+	[LD_UTRACE] =
+	    { .n = "UTRACE", .unsecure = false },
+	[LD_DUMP_REL_PRE] =
+	    { .n = "DUMP_REL_PRE", .unsecure = false },
+	[LD_DUMP_REL_POST] =
+	    { .n = "DUMP_REL_POST", .unsecure = false },
+	[LD_TRACE_LOADED_OBJECTS_PROGNAME] =
+	    { .n = "TRACE_LOADED_OBJECTS_PROGNAME", .unsecure = false},
+	[LD_TRACE_LOADED_OBJECTS_FMT1] =
+	    { .n = "TRACE_LOADED_OBJECTS_FMT1", .unsecure = false},
+	[LD_TRACE_LOADED_OBJECTS_FMT2] =
+	    { .n = "TRACE_LOADED_OBJECTS_FMT2", .unsecure = false},
+	[LD_TRACE_LOADED_OBJECTS_ALL] =
+	    { .n = "TRACE_LOADED_OBJECTS_ALL", .unsecure = false},
+};
+
+static const char *
+ld_var(int idx)
 {
-	static char buffer[128];
+	return (ld_env_vars[idx].n);
+}
 
-	strlcpy(buffer, ld_env_prefix, sizeof(buffer));
-	strlcat(buffer, var, sizeof(buffer));
-	return (buffer);
+static char *
+ld_get_env_var(int idx)
+{
+	return (getenv(ld_var(idx)));
+}
+
+static void
+rtld_init_env_vars(void)
+{
+	struct ld_env_var_desc *lvd;
+	size_t sz;
+	int i;
+
+	sz = strlen(ld_env_prefix);
+	for (i = 0; i < (int)nitems(ld_env_vars); i++) {
+		lvd = &ld_env_vars[i];
+		memmove(lvd->n + sz, lvd->n, strlen(lvd->n) + 1);
+		memcpy(lvd->n, ld_env_prefix, sz);
+	}
 }
-#else
-#define _LD(x)	LD_ x
-#endif
 
 /*
  * Main entry point for dynamic linking.  The first argument is the
@@ -389,6 +472,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
     Elf_Addr *argcp;
     char **argv, **env, **envp, *kexecpath, *library_path_rpath;
     const char *argv0, *binpath;
+    struct ld_env_var_desc *lvd;
     caddr_t imgentry;
     char buf[MAXPATHLEN];
     int argc, fd, i, mib[4], old_osrel, osrel, phnum, rtld_argc;
@@ -464,6 +548,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
     direct_exec = false;
 
     md_abi_variant_hook(aux_info);
+    rtld_init_env_vars();
 
     fd = -1;
     if (aux_info[AT_EXECFD] != NULL) {
@@ -571,7 +656,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
 	}
     }
 
-    ld_bind_now = getenv(_LD("BIND_NOW"));
+    ld_bind_now = ld_get_env_var(LD_BIND_NOW);
 
     /*
      * If the process is tainted, then we un-set the dangerous environment
@@ -580,29 +665,27 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
      * future processes to honor the potentially un-safe variables.
      */
     if (!trust) {
-	if (unsetenv(_LD("PRELOAD")) || unsetenv(_LD("LIBMAP")) ||
-	    unsetenv(_LD("LIBRARY_PATH")) || unsetenv(_LD("LIBRARY_PATH_FDS")) ||
-	    unsetenv(_LD("LIBMAP_DISABLE")) || unsetenv(_LD("BIND_NOT")) ||
-	    unsetenv(_LD("DEBUG")) || unsetenv(_LD("ELF_HINTS_PATH")) ||
-	    unsetenv(_LD("LOADFLTR")) || unsetenv(_LD("LIBRARY_PATH_RPATH")) ||
-	    unsetenv(_LD("PRELOAD_FDS")) || unsetenv(_LD("DYNAMIC_WEAK"))) {
-		_rtld_error("environment corrupt; aborting");
-		rtld_die();
-	}
+	    for (i = 0; i < (int)nitems(ld_env_vars); i++) {
+		    lvd = &ld_env_vars[i];
+		    if (lvd->unsecure && unsetenv(lvd->n)) {
+			    _rtld_error("environment corrupt; aborting");
+			    rtld_die();
+		    }
+	    }
     }
-    ld_debug = getenv(_LD("DEBUG"));
+    ld_debug = ld_get_env_var(LD_DEBUG);
     if (ld_bind_now == NULL)
-	    ld_bind_not = getenv(_LD("BIND_NOT")) != NULL;
-    ld_dynamic_weak = getenv(_LD("DYNAMIC_WEAK")) == NULL;
-    libmap_disable = getenv(_LD("LIBMAP_DISABLE")) != NULL;
-    libmap_override = getenv(_LD("LIBMAP"));
-    ld_library_path = getenv(_LD("LIBRARY_PATH"));
-    ld_library_dirs = getenv(_LD("LIBRARY_PATH_FDS"));
-    ld_preload = getenv(_LD("PRELOAD"));
-    ld_preload_fds = getenv(_LD("PRELOAD_FDS"));
-    ld_elf_hints_path = getenv(_LD("ELF_HINTS_PATH"));
-    ld_loadfltr = getenv(_LD("LOADFLTR")) != NULL;
-    library_path_rpath = getenv(_LD("LIBRARY_PATH_RPATH"));
+	    ld_bind_not = ld_get_env_var(LD_BIND_NOT) != NULL;
+    ld_dynamic_weak = ld_get_env_var(LD_DYNAMIC_WEAK) == NULL;
+    libmap_disable = ld_get_env_var(LD_LIBMAP_DISABLE) != NULL;
+    libmap_override = ld_get_env_var(LD_LIBMAP);
+    ld_library_path = ld_get_env_var(LD_LIBRARY_PATH);
+    ld_library_dirs = ld_get_env_var(LD_LIBRARY_PATH_FDS);
+    ld_preload = ld_get_env_var(LD_PRELOAD);
+    ld_preload_fds = ld_get_env_var(LD_PRELOAD_FDS);
+    ld_elf_hints_path = ld_get_env_var(LD_ELF_HINTS_PATH);
+    ld_loadfltr = ld_get_env_var(LD_LOADFLTR) != NULL;
+    library_path_rpath = ld_get_env_var(LD_LIBRARY_PATH_RPATH);
     if (library_path_rpath != NULL) {
 	    if (library_path_rpath[0] == 'y' ||
 		library_path_rpath[0] == 'Y' ||
@@ -611,11 +694,11 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
 	    else
 		    ld_library_path_rpath = false;
     }
-    dangerous_ld_env = libmap_disable || (libmap_override != NULL) ||
-	(ld_library_path != NULL) || (ld_preload != NULL) ||
-	(ld_elf_hints_path != NULL) || ld_loadfltr || ld_dynamic_weak;
-    ld_tracing = getenv(_LD("TRACE_LOADED_OBJECTS"));
-    ld_utrace = getenv(_LD("UTRACE"));
+    dangerous_ld_env = libmap_disable || libmap_override != NULL ||
+	ld_library_path != NULL || ld_preload != NULL ||
+	ld_elf_hints_path != NULL || ld_loadfltr || ld_dynamic_weak;
+    ld_tracing = ld_get_env_var(LD_TRACE_LOADED_OBJECTS);
+    ld_utrace = ld_get_env_var(LD_UTRACE);
 
     if ((ld_elf_hints_path == NULL) || strlen(ld_elf_hints_path) == 0)
 	ld_elf_hints_path = ld_elf_hints_default;
@@ -751,7 +834,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
 	exit(0);
     }
 
-    if (getenv(_LD("DUMP_REL_PRE")) != NULL) {
+    if (ld_get_env_var(LD_DUMP_REL_PRE) != NULL) {
        dump_relocations(obj_main);
        exit (0);
     }
@@ -779,7 +862,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
     if (do_copy_relocations(obj_main) == -1)
 	rtld_die();
 
-    if (getenv(_LD("DUMP_REL_POST")) != NULL) {
+    if (ld_get_env_var(LD_DUMP_REL_POST) != NULL) {
        dump_relocations(obj_main);
        exit (0);
     }
@@ -4715,16 +4798,17 @@ trace_loaded_objects(Obj_Entry *obj)
     const char *fmt1, *fmt2, *fmt, *main_local, *list_containers;
     int c;
 
-    if ((main_local = getenv(_LD("TRACE_LOADED_OBJECTS_PROGNAME"))) == NULL)
+    if ((main_local = ld_get_env_var(LD_TRACE_LOADED_OBJECTS_PROGNAME)) ==
+      NULL)
 	main_local = "";
 
-    if ((fmt1 = getenv(_LD("TRACE_LOADED_OBJECTS_FMT1"))) == NULL)
+    if ((fmt1 = ld_get_env_var(LD_TRACE_LOADED_OBJECTS_FMT1)) == NULL)
 	fmt1 = "\t%o => %p (%x)\n";
 
-    if ((fmt2 = getenv(_LD("TRACE_LOADED_OBJECTS_FMT2"))) == NULL)
+    if ((fmt2 = ld_get_env_var(LD_TRACE_LOADED_OBJECTS_FMT2)) == NULL)
 	fmt2 = "\t%o (%x)\n";
 
-    list_containers = getenv(_LD("TRACE_LOADED_OBJECTS_ALL"));
+    list_containers = ld_get_env_var(LD_TRACE_LOADED_OBJECTS_ALL);
 
     for (; obj != NULL; obj = TAILQ_NEXT(obj, next)) {
 	Needed_Entry *needed;



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