]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
unshare: new option to prevent environment variable inheritance
authorChristian Goeschel Ndjomouo <cgoesc2@wgu.edu>
Fri, 27 Mar 2026 23:57:53 +0000 (19:57 -0400)
committerChristian Goeschel Ndjomouo <cgoesc2@wgu.edu>
Sun, 29 Mar 2026 18:31:23 +0000 (14:31 -0400)
In some cases it is desirable to have a clean environment for
an unshared process and conveniently prevent any information
leakage into the new namespace.

This is what the --clear-env option can be used for; it makes
it so that unshare(1) clears the environment variable array,
obtained from the calling process, right before executing the
target program.

Signed-off-by: Christian Goeschel Ndjomouo <cgoesc2@wgu.edu>
sys-utils/unshare.1.adoc
sys-utils/unshare.c

index 888928147b0805abb41772abd8c68061012b8434..eebfbdd838576e345a1bb92955322116752050fa 100644 (file)
@@ -167,6 +167,9 @@ Set the offset of *CLOCK_MONOTONIC* which will be used in the entered time names
 *--boottime* _offset_::
 Set the offset of *CLOCK_BOOTTIME* which will be used in the entered time namespace. This option requires unsharing a time namespace with *--time*.
 
+*--clear-env**::
+Do not pass the environment variables of the calling process to the unshared process.
+
 include::man-common/help-version.adoc[]
 
 == NOTES
index 9a7c9f617dd8ec3b8a91d3537a07a36103084ac1..80de315a549e924e80e6585a9750389dae89f0c2 100644 (file)
 #include "strutils.h"
 #include "pwdutils.h"
 
+#ifndef HAVE_ENVIRON_DECL
+extern char **environ;
+#endif
+
 /* synchronize parent and child by pipe */
 #define PIPE_SYNC_BYTE 0x06
 
@@ -790,6 +794,7 @@ static void __attribute__((__noreturn__)) usage(void)
        fputs(USAGE_SEPARATOR, out);
        fputs(_(" --monotonic <offset>      set clock monotonic offset (seconds) in time namespaces\n"), out);
        fputs(_(" --boottime <offset>       set clock boottime offset (seconds) in time namespaces\n"), out);
+       fputs(_(" --clear-env               do not inherit environment variables from the calling process\n"), out);
 
        fputs(USAGE_SEPARATOR, out);
        fprintf(out, USAGE_HELP_OPTIONS(27));
@@ -817,6 +822,7 @@ int main(int argc, char *argv[])
                OPT_MAPSUBIDS,
                OPT_OWNER,
                OPT_FORWARD_SIGNALS,
+               OPT_CLEAR_ENV,
        };
        static const struct option longopts[] = {
                { "help",          no_argument,       NULL, 'h'             },
@@ -855,6 +861,7 @@ int main(int argc, char *argv[])
                { "monotonic",     required_argument, NULL, OPT_MONOTONIC   },
                { "boottime",      required_argument, NULL, OPT_BOOTTIME    },
                { "load-interp",   required_argument, NULL, 'l'             },
+               { "clear-env",   no_argument, NULL, OPT_CLEAR_ENV                   },
                { NULL, 0, NULL, 0 }
        };
 
@@ -888,6 +895,7 @@ int main(int argc, char *argv[])
        int64_t boottime = 0;
        int force_monotonic = 0;
        int force_boottime = 0;
+       int clear_env = 0;
 
        setlocale(LC_ALL, "");
        bindtextdomain(PACKAGE, LOCALEDIR);
@@ -1067,7 +1075,9 @@ int main(int argc, char *argv[])
                        }
                        newinterp = optarg;
                        break;
-
+               case OPT_CLEAR_ENV:
+                       clear_env = 1;
+                       break;
                case 'h':
                        usage();
                case 'V':
@@ -1321,6 +1331,13 @@ int main(int argc, char *argv[])
        if (keepcaps && (unshare_flags & CLONE_NEWUSER))
                cap_permitted_to_ambient();
 
+       if (clear_env)
+#ifdef HAVE_CLEARENV
+               clearenv();
+#else
+               environ = NULL;
+#endif
+
        if (optind < argc) {
                execvp(argv[optind], argv + optind);
                errexec(argv[optind]);