37cb5e
From 29d625a085497be8babec7d2adfb3eeaa7114736 Mon Sep 17 00:00:00 2001
ead27a
From: Karel Zak <kzak@redhat.com>
ead27a
Date: Wed, 22 Aug 2018 11:43:32 +0200
37cb5e
Subject: [PATCH 1/2] setpriv: add --reset-env
ead27a
ead27a
Clear environment in way like su(1), but PATH is set to hard-coded
ead27a
defaults and /etc/login.defs is not used at all (I guess we want to
ead27a
keep setpriv(1) simple).
ead27a
ead27a
If you need anything more advanced than use env(1).
ead27a
ead27a
Addresses: https://github.com/karelzak/util-linux/issues/325
ead27a
Signed-off-by: Karel Zak <kzak@redhat.com>
ead27a
---
37cb5e
 sys-utils/setpriv.1 |  9 +++++++
37cb5e
 sys-utils/setpriv.c | 57 ++++++++++++++++++++++++++++++++++++++++++++-
37cb5e
 2 files changed, 65 insertions(+), 1 deletion(-)
ead27a
ead27a
diff --git a/sys-utils/setpriv.1 b/sys-utils/setpriv.1
37cb5e
index f989bf33c..e915316a9 100644
ead27a
--- a/sys-utils/setpriv.1
ead27a
+++ b/sys-utils/setpriv.1
37cb5e
@@ -165,6 +165,15 @@ to abort if AppArmor is not in use, and the transition may be ignored or cause
ead27a
 .BR execve (2)
ead27a
 to fail at AppArmor's whim.
ead27a
 .TP
ead27a
+.BI \-\-reset\-env
ead27a
+Clears all the environment variables except TERM; initializes the environment variables HOME, SHELL, USER, LOGNAME
ead27a
+according to the user's passwd entry; sets PATH to \fI/usr/local/bin:/bin:/usr/bin\fR for a regual user and to
ead27a
+\fI/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin\fR for root.
ead27a
+.sp
ead27a
+The environment variable PATH may be different on systems where /bin and /sbin
ead27a
+are merged into /usr.  The environment variable SHELL defaults to \fI/bin/sh\fR if none is given in the user's
ead27a
+passwd entry.
ead27a
+.TP
ead27a
 .BR \-V , " \-\-version"
ead27a
 Display version information and exit.
ead27a
 .TP
ead27a
diff --git a/sys-utils/setpriv.c b/sys-utils/setpriv.c
37cb5e
index 0d3a3b3c9..402b1cf1a 100644
ead27a
--- a/sys-utils/setpriv.c
ead27a
+++ b/sys-utils/setpriv.c
37cb5e
@@ -39,6 +39,7 @@
ead27a
 #include "xalloc.h"
ead27a
 #include "pathnames.h"
37cb5e
 #include "signames.h"
ead27a
+#include "env.h"
ead27a
 
ead27a
 #ifndef PR_SET_NO_NEW_PRIVS
ead27a
 # define PR_SET_NO_NEW_PRIVS 38
37cb5e
@@ -56,6 +57,11 @@
ead27a
 
ead27a
 #define SETPRIV_EXIT_PRIVERR 127	/* how we exit when we fail to set privs */
ead27a
 
ead27a
+/* The shell to set SHELL env.variable if none is given in the user's passwd entry.  */
ead27a
+#define DEFAULT_SHELL "/bin/sh"
ead27a
+
37cb5e
+static gid_t get_group(const char *s, const char *err);
37cb5e
+
ead27a
 enum cap_type {
ead27a
 	CAP_TYPE_EFFECTIVE   = CAPNG_EFFECTIVE,
ead27a
 	CAP_TYPE_PERMITTED   = CAPNG_PERMITTED,
37cb5e
@@ -83,6 +89,7 @@ struct privctx {
ead27a
 		keep_groups:1,		/* keep groups */
ead27a
 		clear_groups:1,		/* remove groups */
ead27a
 		init_groups:1,		/* initialize groups */
ead27a
+		reset_env:1,		/* reset environment */
ead27a
 		have_securebits:1;	/* remove groups */
ead27a
 
ead27a
 	/* uids and gids */
37cb5e
@@ -138,10 +145,13 @@ static void __attribute__((__noreturn__)) usage(void)
37cb5e
 	fputs(_(" --init-groups               initialize supplementary groups\n"), out);
37cb5e
 	fputs(_(" --groups <group,...>        set supplementary groups\n"), out);
ead27a
 	fputs(_(" --securebits <bits>         set securebits\n"), out);
37cb5e
+	fputs(_(" --reset-env                 reset environment variables\n"), out);
37cb5e
 	fputs(_(" --pdeathsig keep|clear|<signame>\n"
37cb5e
 	        "                             set or clear parent death signal\n"), out);
ead27a
 	fputs(_(" --selinux-label <label>     set SELinux label\n"), out);
ead27a
 	fputs(_(" --apparmor-profile <pr>     set AppArmor profile\n"), out);
ead27a
+	fputs(_(" --reset-env                 clear all environment and initialize\n"
ead27a
+		"                               HOME, SHELL, USER, LOGNAME and PATH\n"), out);
ead27a
 
ead27a
 	fputs(USAGE_SEPARATOR, out);
ead27a
 	printf(USAGE_HELP_OPTIONS(29));
37cb5e
@@ -680,6 +690,36 @@ static void do_apparmor_profile(const char *label)
ead27a
 		    _("write failed: %s"), _PATH_PROC_ATTR_EXEC);
ead27a
 }
ead27a
 
ead27a
+
ead27a
+static void do_reset_environ(struct passwd *pw)
ead27a
+{
ead27a
+	char *term = getenv("TERM");
ead27a
+
ead27a
+	if (term)
ead27a
+		term = xstrdup(term);
ead27a
+#ifdef HAVE_CLEARENV
ead27a
+	clearenv();
ead27a
+#else
ead27a
+	environ = NULL;
ead27a
+#endif
ead27a
+	if (term)
ead27a
+		xsetenv("TERM", term, 1);
ead27a
+
ead27a
+	if (pw->pw_shell && *pw->pw_shell)
ead27a
+		xsetenv("SHELL", pw->pw_shell, 1);
ead27a
+	else
ead27a
+		xsetenv("SHELL", DEFAULT_SHELL, 1);
ead27a
+
ead27a
+	xsetenv("HOME", pw->pw_dir, 1);
ead27a
+	xsetenv("USER", pw->pw_name, 1);
ead27a
+	xsetenv("LOGNAME", pw->pw_name, 1);
ead27a
+
ead27a
+	if (pw->pw_uid)
ead27a
+		xsetenv("PATH", _PATH_DEFPATH, 1);
ead27a
+	else
ead27a
+		xsetenv("PATH", _PATH_DEFPATH_ROOT, 1);
ead27a
+}
ead27a
+
ead27a
 static uid_t get_user(const char *s, const char *err)
ead27a
 {
ead27a
 	struct passwd *pw;
37cb5e
@@ -750,7 +790,8 @@ int main(int argc, char **argv)
ead27a
 		SECUREBITS,
37cb5e
 		PDEATHSIG,
ead27a
 		SELINUX_LABEL,
ead27a
-		APPARMOR_PROFILE
ead27a
+		APPARMOR_PROFILE,
ead27a
+		RESET_ENV
ead27a
 	};
ead27a
 
ead27a
 	static const struct option longopts[] = {
37cb5e
@@ -776,6 +817,7 @@ int main(int argc, char **argv)
ead27a
 		{ "selinux-label",    required_argument, NULL, SELINUX_LABEL    },
ead27a
 		{ "apparmor-profile", required_argument, NULL, APPARMOR_PROFILE },
ead27a
 		{ "help",             no_argument,       NULL, 'h'              },
ead27a
+		{ "reset-env",        no_argument,       NULL, RESET_ENV,       },
ead27a
 		{ "version",          no_argument,       NULL, 'V'              },
ead27a
 		{ NULL, 0, NULL, 0 }
ead27a
 	};
37cb5e
@@ -928,6 +970,9 @@ int main(int argc, char **argv)
ead27a
 				     _("duplicate --apparmor-profile option"));
ead27a
 			opts.apparmor_profile = optarg;
ead27a
 			break;
ead27a
+		case RESET_ENV:
ead27a
+			opts.reset_env = 1;
ead27a
+			break;
ead27a
 		case 'h':
ead27a
 			usage();
ead27a
 		case 'V':
37cb5e
@@ -973,6 +1018,16 @@ int main(int argc, char **argv)
ead27a
 		       "can be found on the system"),
ead27a
 		     (long) opts.ruid);
ead27a
 
ead27a
+	if (opts.reset_env) {
ead27a
+		if (opts.have_passwd)
ead27a
+			/* pwd according to --ruid or --reuid */
ead27a
+			pw = &opts.passwd;
ead27a
+		else
ead27a
+			/* pwd for the current user */
ead27a
+			pw = getpwuid(getuid());
ead27a
+		do_reset_environ(pw);
ead27a
+	}
ead27a
+
ead27a
 	if (opts.nnp && prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1)
ead27a
 		err(EXIT_FAILURE, _("disallow granting new privileges failed"));
ead27a
 
ead27a
-- 
37cb5e
2.38.1
37cb5e
37cb5e
37cb5e
From 7f2c086340c755b3044f1786d4647c40c20200e3 Mon Sep 17 00:00:00 2001
37cb5e
From: John W Higgins <wishdev@gmail.com>
37cb5e
Date: Mon, 17 Dec 2018 17:11:44 -0800
37cb5e
Subject: [PATCH 2/2] Remove duplicate entry for reset-env from usage
37cb5e
37cb5e
I assume the second entry was not desired in the original commit. Line 153-154 would appear to be a duplicate
37cb5e
---
37cb5e
 sys-utils/setpriv.c | 1 -
37cb5e
 1 file changed, 1 deletion(-)
37cb5e
37cb5e
diff --git a/sys-utils/setpriv.c b/sys-utils/setpriv.c
37cb5e
index 402b1cf1a..f4344bd52 100644
37cb5e
--- a/sys-utils/setpriv.c
37cb5e
+++ b/sys-utils/setpriv.c
37cb5e
@@ -145,7 +145,6 @@ static void __attribute__((__noreturn__)) usage(void)
37cb5e
 	fputs(_(" --init-groups               initialize supplementary groups\n"), out);
37cb5e
 	fputs(_(" --groups <group,...>        set supplementary groups\n"), out);
37cb5e
 	fputs(_(" --securebits <bits>         set securebits\n"), out);
37cb5e
-	fputs(_(" --reset-env                 reset environment variables\n"), out);
37cb5e
 	fputs(_(" --pdeathsig keep|clear|<signame>\n"
37cb5e
 	        "                             set or clear parent death signal\n"), out);
37cb5e
 	fputs(_(" --selinux-label <label>     set SELinux label\n"), out);
37cb5e
-- 
37cb5e
2.38.1
ead27a