Author: jamie
Date: Thu Jul 30 04:53:53 2015
New Revision: 286064
URL: https://svnweb.freebsd.org/changeset/base/286064

Log:
  MFC r285420:
  
    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

Modified:
  stable/10/usr.sbin/jexec/jexec.8
  stable/10/usr.sbin/jexec/jexec.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/usr.sbin/jexec/jexec.8
==============================================================================
--- stable/10/usr.sbin/jexec/jexec.8    Thu Jul 30 04:01:00 2015        
(r286063)
+++ stable/10/usr.sbin/jexec/jexec.8    Thu Jul 30 04:53:53 2015        
(r286064)
@@ -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: stable/10/usr.sbin/jexec/jexec.c
==============================================================================
--- stable/10/usr.sbin/jexec/jexec.c    Thu Jul 30 04:01:00 2015        
(r286063)
+++ stable/10/usr.sbin/jexec/jexec.c    Thu Jul 30 04:53:53 2015        
(r286064)
@@ -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); 
 }
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to