#include "signames.h"
#include "strutils.h"
#include "pwdutils.h"
+#include "env.h"
#ifndef HAVE_ENVIRON_DECL
extern char **environ;
close(dirfd);
}
+static void set_whitelist_envs(struct ul_env_list **el)
+{
+ if (env_list_setenv(*el, 0) != 0)
+ err(EXIT_FAILURE, _("failed to set whitelisted environment variables"));
+
+ env_list_free(*el);
+ *el = NULL;
+}
+
static void __attribute__((__noreturn__)) usage(void)
{
FILE *out = stdout;
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(_(" --whitelist-env <list> clear environment except for specified variables\n"), out);
fputs(USAGE_SEPARATOR, out);
fprintf(out, USAGE_HELP_OPTIONS(27));
OPT_OWNER,
OPT_FORWARD_SIGNALS,
OPT_CLEAR_ENV,
+ OPT_WHITELIST_ENV,
};
static const struct option longopts[] = {
{ "help", no_argument, NULL, 'h' },
{ "boottime", required_argument, NULL, OPT_BOOTTIME },
{ "load-interp", required_argument, NULL, 'l' },
{ "clear-env", no_argument, NULL, OPT_CLEAR_ENV },
+ { "whitelist-env", required_argument, NULL, OPT_WHITELIST_ENV },
{ NULL, 0, NULL, 0 }
};
gid_t mapgroup = -1, ownergroup = -1;
struct map_range *usermap = NULL;
struct map_range *groupmap = NULL;
+ struct ul_env_list *env_whitelist = NULL; /* environment whitelist */
int kill_child_signo = 0; /* 0 means --kill-child was not used */
const char *procmnt = NULL;
const char *binfmt_mnt = NULL;
case OPT_CLEAR_ENV:
clear_env = 1;
break;
+ case OPT_WHITELIST_ENV:
+ env_whitelist = env_list_add_getenvs(env_whitelist, optarg);
+ break;
case 'h':
usage();
case 'V':
if (keepcaps && (unshare_flags & CLONE_NEWUSER))
cap_permitted_to_ambient();
- if (clear_env)
+ if (clear_env || env_whitelist)
#ifdef HAVE_CLEARENV
clearenv();
#else
environ = NULL;
#endif
+ if (env_whitelist)
+ set_whitelist_envs(&env_whitelist);
+
if (optind < argc) {
execvp(argv[optind], argv + optind);
errexec(argv[optind]);
ts_check_test_command "$TS_CMD_UNSHARE"
ts_check_test_command "$TS_HELPER_STRERROR"
+
+ts_init_subtest "clear-env"
export UL_TEST_ENV=foo
-res="$("$TS_CMD_UNSHARE" --clear-env /bin/bash -c 'echo $UL_TEST_ENV' 2>&1)"
+"$TS_CMD_UNSHARE" --clear-env /bin/bash -c 'echo "${UL_TEST_ENV:-CLEARED}"' >>"$TS_OUTPUT" 2>>"$TS_ERRLOG"
unset -v UL_TEST_ENV
-if echo "$res" | grep -q "$($TS_HELPER_STRERROR EPERM)"; then
- ts_skip "missing permissions"
+if grep -q "$($TS_HELPER_STRERROR EPERM)" "$TS_OUTPUT" "$TS_ERRLOG"; then
+ ts_skip_subtest "missing permissions"
+else
+ ts_finalize_subtest
fi
-if [[ -n "$res" ]]; then
- ts_failed "environment not cleared correctly: $res"
+
+ts_init_subtest "whitelist-env"
+export UL_TEST_ENV1=foo
+export UL_TEST_ENV2=bar
+"$TS_CMD_UNSHARE" --whitelist-env UL_TEST_ENV1 /bin/bash -c 'echo "${UL_TEST_ENV1}${UL_TEST_ENV2}"' >>"$TS_OUTPUT" 2>>"$TS_ERRLOG"
+
+if grep -q "$($TS_HELPER_STRERROR EPERM)" "$TS_OUTPUT" "$TS_ERRLOG"; then
+ ts_skip_subtest "missing permissions"
+else
+ ts_finalize_subtest
fi
ts_finalize