svn commit: r285420 - head/usr.sbin/jexec

Jamie Gritton jamie at FreeBSD.org
Sun Jul 12 17:03:52 UTC 2015


Author: jamie
Date: Sun Jul 12 17:03:50 2015
New Revision: 285420
URL: https://svnweb.freebsd.org/changeset/base/285420

Log:
  Run a shell in the jail when no command is specified.
  Add a new flag, -l, for a clean environment, same as jail(8) exec.clean.
  Change the GET_USER_INFO macro into a function.
  
  PR:		201300
  Submitted by:	Willem Jan Withagen
  MFC after:	3 days

Modified:
  head/usr.sbin/jexec/jexec.8
  head/usr.sbin/jexec/jexec.c

Modified: head/usr.sbin/jexec/jexec.8
==============================================================================
--- head/usr.sbin/jexec/jexec.8	Sun Jul 12 15:24:05 2015	(r285419)
+++ head/usr.sbin/jexec/jexec.8	Sun Jul 12 17:03:50 2015	(r285420)
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd May 27, 2009
+.Dd Jul 11, 2015
 .Dt JEXEC 8
 .Os
 .Sh NAME
@@ -33,8 +33,9 @@
 .Nd "execute a command inside an existing jail"
 .Sh SYNOPSIS
 .Nm
+.Op Fl l
 .Op Fl u Ar username | Fl U Ar username
-.Ar jail command ...
+.Ar jail Op Ar command ...
 .Sh DESCRIPTION
 The
 .Nm
@@ -43,9 +44,17 @@ utility executes
 inside the
 .Ar jail
 identified by its jid or name.
+If
+.Ar command
+is not specified then the user's shell is used.
 .Pp
 The following options are available:
 .Bl -tag -width indent
+.It Fl l
+Execute in a clean environment.
+The environment is discarded except for
+.Ev HOME , SHELL , TERM , USER ,
+and anything from the login class capability database for the user.
 .It Fl u Ar username
 The user name from host environment as whom the
 .Ar command

Modified: head/usr.sbin/jexec/jexec.c
==============================================================================
--- head/usr.sbin/jexec/jexec.c	Sun Jul 12 15:24:05 2015	(r285419)
+++ head/usr.sbin/jexec/jexec.c	Sun Jul 12 17:03:50 2015	(r285420)
@@ -40,49 +40,37 @@
 #include <jail.h>
 #include <limits.h>
 #include <login_cap.h>
+#include <paths.h>
+#include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <pwd.h>
 #include <unistd.h>
 
-static void	usage(void);
+extern char **environ;
 
-#define GET_USER_INFO do {						\
-	pwd = getpwnam(username);					\
-	if (pwd == NULL) {						\
-		if (errno)						\
-			err(1, "getpwnam: %s", username);		\
-		else							\
-			errx(1, "%s: no such user", username);		\
-	}								\
-	lcap = login_getpwclass(pwd);					\
-	if (lcap == NULL)						\
-		err(1, "getpwclass: %s", username);			\
-	ngroups = ngroups_max;						\
-	if (getgrouplist(username, pwd->pw_gid, groups, &ngroups) != 0)	\
-		err(1, "getgrouplist: %s", username);			\
-} while (0)
+static void	get_user_info(const char *username, const struct passwd **pwdp,
+    login_cap_t **lcapp);
+static void	usage(void);
 
 int
 main(int argc, char *argv[])
 {
 	int jid;
 	login_cap_t *lcap = NULL;
-	struct passwd *pwd = NULL;
-	gid_t *groups = NULL;
-	int ch, ngroups, uflag, Uflag;
-	long ngroups_max;
-	char *username;
+	int ch, clean, uflag, Uflag;
+	char *cleanenv;
+	const struct passwd *pwd = NULL;
+	const char *username, *shell, *term;
 
-	ch = uflag = Uflag = 0;
+	ch = clean = uflag = Uflag = 0;
 	username = NULL;
-	ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
-	if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
-		err(1, "malloc");
 
-	while ((ch = getopt(argc, argv, "nu:U:")) != -1) {
+	while ((ch = getopt(argc, argv, "lnu:U:")) != -1) {
 		switch (ch) {
+		case 'l':
+			clean = 1;
+			break;
 		case 'n':
 			/* Specified name, now unused */
 			break;
@@ -100,12 +88,15 @@ main(int argc, char *argv[])
 	}
 	argc -= optind;
 	argv += optind;
-	if (argc < 2)
+	if (argc < 1)
 		usage();
 	if (uflag && Uflag)
 		usage();
-	if (uflag)
-		GET_USER_INFO;
+	if (uflag || (clean && !Uflag))
+		/* User info from the home environment */
+		get_user_info(username, &pwd, &lcap);
+
+	/* Attach to the jail */
 	jid = jail_getid(argv[0]);
 	if (jid < 0)
 		errx(1, "%s", jail_errmsg);
@@ -113,28 +104,88 @@ main(int argc, char *argv[])
 		err(1, "jail_attach(%d)", jid);
 	if (chdir("/") == -1)
 		err(1, "chdir(): /");
-	if (username != NULL) {
+
+	/* Set up user environment */
+	if (clean || username != NULL) {
 		if (Uflag)
-			GET_USER_INFO;
-		if (setgroups(ngroups, groups) != 0)
-			err(1, "setgroups");
+			/* User info from the jail environment */
+			get_user_info(username, &pwd, &lcap);
+		if (clean) {
+			term = getenv("TERM");
+			cleanenv = NULL;
+			environ = &cleanenv;
+			setenv("PATH", "/bin:/usr/bin", 1);
+			if (term != NULL)
+				setenv("TERM", term, 1);
+		}
 		if (setgid(pwd->pw_gid) != 0)
 			err(1, "setgid");
-		if (setusercontext(lcap, pwd, pwd->pw_uid,
-		    LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN) != 0)
+		if (setusercontext(lcap, pwd, pwd->pw_uid, username
+		    ? LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN
+		    : LOGIN_SETPATH | LOGIN_SETENV) != 0)
 			err(1, "setusercontext");
 		login_close(lcap);
+		setenv("USER", pwd->pw_name, 1);
+		setenv("HOME", pwd->pw_dir, 1);
+		setenv("SHELL",
+		    *pwd->pw_shell ? pwd->pw_shell : _PATH_BSHELL, 1);
+		if (clean && chdir(pwd->pw_dir) < 0)
+			err(1, "chdir: %s", pwd->pw_dir);
+		endpwent();
+	}
+
+	/* Run the specified command, or the shell */
+	if (argc > 1) {
+		if (execvp(argv[1], argv + 1) < 0)
+			err(1, "execvp: %s", argv[1]);
+	} else {
+		if (!(shell = getenv("SHELL")))
+			shell = _PATH_BSHELL;
+		if (execlp(shell, shell, "-i", NULL) < 0)
+			err(1, "execlp: %s", shell);
 	}
-	if (execvp(argv[1], argv + 1) == -1)
-		err(1, "execvp(): %s", argv[1]);
 	exit(0);
 }
 
 static void
+get_user_info(const char *username, const struct passwd **pwdp,
+    login_cap_t **lcapp)
+{
+	uid_t uid;
+	const struct passwd *pwd;
+
+	errno = 0;
+	if (username) {
+		pwd = getpwnam(username);
+		if (pwd == NULL) {
+			if (errno)
+				err(1, "getpwnam: %s", username);
+			else
+				errx(1, "%s: no such user", username);
+		}
+	} else {
+		uid = getuid();
+		pwd = getpwuid(uid);
+		if (pwd == NULL) {
+			if (errno)
+				err(1, "getpwuid: %d", uid);
+			else
+				errx(1, "unknown uid: %d", uid);
+		}
+	}
+	*pwdp = pwd;
+	*lcapp = login_getpwclass(pwd);
+	if (*lcapp == NULL)
+		err(1, "getpwclass: %s", pwd->pw_name);
+	if (initgroups(pwd->pw_name, pwd->pw_gid) < 0)
+		err(1, "initgroups: %s", pwd->pw_name);
+}
+
+static void
 usage(void)
 {
 
 	fprintf(stderr, "%s\n",
-		"usage: jexec [-u username | -U username] jail command ...");
+	    "usage: jexec [-l] [-u username | -U username] jail [command ...]");
 	exit(1); 
 }


More information about the svn-src-head mailing list