diff options
author | Karel Zak | 2018-08-22 11:43:32 +0200 |
---|---|---|
committer | Karel Zak | 2018-08-22 11:43:32 +0200 |
commit | 89f95425746e0371c033260c2bc0ef176eba6a37 (patch) | |
tree | aab4a1fc2bdd8f9da9c3087b437c32dac46f14a3 /sys-utils/setpriv.c | |
parent | su: add note about merged /usr (diff) | |
download | kernel-qcow2-util-linux-89f95425746e0371c033260c2bc0ef176eba6a37.tar.gz kernel-qcow2-util-linux-89f95425746e0371c033260c2bc0ef176eba6a37.tar.xz kernel-qcow2-util-linux-89f95425746e0371c033260c2bc0ef176eba6a37.zip |
setpriv: add --reset-env
Clear environment in way like su(1), but PATH is set to hard-coded
defaults and /etc/login.defs is not used at all (I guess we want to
keep setpriv(1) simple).
If you need anything more advanced than use env(1).
Addresses: https://github.com/karelzak/util-linux/issues/325
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'sys-utils/setpriv.c')
-rw-r--r-- | sys-utils/setpriv.c | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/sys-utils/setpriv.c b/sys-utils/setpriv.c index 564c56d48..eba5decab 100644 --- a/sys-utils/setpriv.c +++ b/sys-utils/setpriv.c @@ -39,6 +39,7 @@ #include "xalloc.h" #include "pathnames.h" #include "signames.h" +#include "env.h" #ifndef PR_SET_NO_NEW_PRIVS # define PR_SET_NO_NEW_PRIVS 38 @@ -56,6 +57,9 @@ #define SETPRIV_EXIT_PRIVERR 127 /* how we exit when we fail to set privs */ +/* The shell to set SHELL env.variable if none is given in the user's passwd entry. */ +#define DEFAULT_SHELL "/bin/sh" + static gid_t get_group(const char *s, const char *err); enum cap_type { @@ -85,6 +89,7 @@ struct privctx { keep_groups:1, /* keep groups */ clear_groups:1, /* remove groups */ init_groups:1, /* initialize groups */ + reset_env:1, /* reset environment */ have_securebits:1; /* remove groups */ /* uids and gids */ @@ -140,10 +145,13 @@ static void __attribute__((__noreturn__)) usage(void) fputs(_(" --init-groups initialize supplementary groups\n"), out); fputs(_(" --groups <group,...> set supplementary groups by UID or name\n"), out); fputs(_(" --securebits <bits> set securebits\n"), out); + fputs(_(" --reset-env reset environment variables\n"), out); fputs(_(" --pdeathsig keep|clear|<signame>\n" " set or clear parent death signal\n"), out); fputs(_(" --selinux-label <label> set SELinux label\n"), out); fputs(_(" --apparmor-profile <pr> set AppArmor profile\n"), out); + fputs(_(" --reset-env clear all environment and initialize\n" + " HOME, SHELL, USER, LOGNAME and PATH\n"), out); fputs(USAGE_SEPARATOR, out); printf(USAGE_HELP_OPTIONS(29)); @@ -681,6 +689,36 @@ static void do_apparmor_profile(const char *label) _("write failed: %s"), _PATH_PROC_ATTR_EXEC); } + +static void do_reset_environ(struct passwd *pw) +{ + char *term = getenv("TERM"); + + if (term) + term = xstrdup(term); +#ifdef HAVE_CLEARENV + clearenv(); +#else + environ = NULL; +#endif + if (term) + xsetenv("TERM", term, 1); + + if (pw->pw_shell && *pw->pw_shell) + xsetenv("SHELL", pw->pw_shell, 1); + else + xsetenv("SHELL", DEFAULT_SHELL, 1); + + xsetenv("HOME", pw->pw_dir, 1); + xsetenv("USER", pw->pw_name, 1); + xsetenv("LOGNAME", pw->pw_name, 1); + + if (pw->pw_uid) + xsetenv("PATH", _PATH_DEFPATH, 1); + else + xsetenv("PATH", _PATH_DEFPATH_ROOT, 1); +} + static uid_t get_user(const char *s, const char *err) { struct passwd *pw; @@ -751,7 +789,8 @@ int main(int argc, char **argv) SECUREBITS, PDEATHSIG, SELINUX_LABEL, - APPARMOR_PROFILE + APPARMOR_PROFILE, + RESET_ENV }; static const struct option longopts[] = { @@ -777,6 +816,7 @@ int main(int argc, char **argv) { "selinux-label", required_argument, NULL, SELINUX_LABEL }, { "apparmor-profile", required_argument, NULL, APPARMOR_PROFILE }, { "help", no_argument, NULL, 'h' }, + { "reset-env", no_argument, NULL, RESET_ENV, }, { "version", no_argument, NULL, 'V' }, { NULL, 0, NULL, 0 } }; @@ -929,6 +969,9 @@ int main(int argc, char **argv) _("duplicate --apparmor-profile option")); opts.apparmor_profile = optarg; break; + case RESET_ENV: + opts.reset_env = 1; + break; case 'h': usage(); case 'V': @@ -974,6 +1017,16 @@ int main(int argc, char **argv) "can be found on the system"), (long) opts.ruid); + if (opts.reset_env) { + if (opts.have_passwd) + /* pwd according to --ruid or --reuid */ + pw = &opts.passwd; + else + /* pwd for the current user */ + pw = getpwuid(getuid()); + do_reset_environ(pw); + } + if (opts.nnp && prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) err(EXIT_FAILURE, _("disallow granting new privileges failed")); |