View | Details | Raw Unified | Return to bug 201300 | Differences between
and this patch

Collapse All | Expand All

(-)usr.sbin/jexec/jexec.8 (-2 / +11 lines)
Lines 25-31 Link Here
25
.\"
25
.\"
26
.\" $FreeBSD$
26
.\" $FreeBSD$
27
.\"
27
.\"
28
.Dd May 27, 2009
28
.Dd Jul 11, 2015
29
.Dt JEXEC 8
29
.Dt JEXEC 8
30
.Os
30
.Os
31
.Sh NAME
31
.Sh NAME
Lines 33-40 Link Here
33
.Nd "execute a command inside an existing jail"
33
.Nd "execute a command inside an existing jail"
34
.Sh SYNOPSIS
34
.Sh SYNOPSIS
35
.Nm
35
.Nm
36
.Op Fl l
36
.Op Fl u Ar username | Fl U Ar username
37
.Op Fl u Ar username | Fl U Ar username
37
.Ar jail command ...
38
.Ar jail Op Ar command ...
38
.Sh DESCRIPTION
39
.Sh DESCRIPTION
39
The
40
The
40
.Nm
41
.Nm
Lines 43-51 Link Here
43
inside the
44
inside the
44
.Ar jail
45
.Ar jail
45
identified by its jid or name.
46
identified by its jid or name.
47
If
48
.Ar command
49
is not specified then the user's shell is used.
46
.Pp
50
.Pp
47
The following options are available:
51
The following options are available:
48
.Bl -tag -width indent
52
.Bl -tag -width indent
53
.It Fl l
54
Execute in a clean environment.
55
The environment is discarded except for
56
.Ev HOME , SHELL , TERM , USER
57
and anything from the login class capability database for the user.
49
.It Fl u Ar username
58
.It Fl u Ar username
50
The user name from host environment as whom the
59
The user name from host environment as whom the
51
.Ar command
60
.Ar command
(-)usr.sbin/jexec/jexec.c (-39 / +90 lines)
Lines 40-88 Link Here
40
#include <jail.h>
40
#include <jail.h>
41
#include <limits.h>
41
#include <limits.h>
42
#include <login_cap.h>
42
#include <login_cap.h>
43
#include <paths.h>
44
#include <pwd.h>
43
#include <stdio.h>
45
#include <stdio.h>
44
#include <stdlib.h>
46
#include <stdlib.h>
45
#include <string.h>
47
#include <string.h>
46
#include <pwd.h>
47
#include <unistd.h>
48
#include <unistd.h>
48
49
50
extern char **environ;
51
52
static void	get_user_info(const char *username, const struct passwd **pwdp,
53
    login_cap_t **lcapp);
49
static void	usage(void);
54
static void	usage(void);
50
55
51
#define GET_USER_INFO do {						\
52
	pwd = getpwnam(username);					\
53
	if (pwd == NULL) {						\
54
		if (errno)						\
55
			err(1, "getpwnam: %s", username);		\
56
		else							\
57
			errx(1, "%s: no such user", username);		\
58
	}								\
59
	lcap = login_getpwclass(pwd);					\
60
	if (lcap == NULL)						\
61
		err(1, "getpwclass: %s", username);			\
62
	ngroups = ngroups_max;						\
63
	if (getgrouplist(username, pwd->pw_gid, groups, &ngroups) != 0)	\
64
		err(1, "getgrouplist: %s", username);			\
65
} while (0)
66
67
int
56
int
68
main(int argc, char *argv[])
57
main(int argc, char *argv[])
69
{
58
{
70
	int jid;
59
	int jid;
71
	login_cap_t *lcap = NULL;
60
	login_cap_t *lcap = NULL;
72
	struct passwd *pwd = NULL;
61
	int ch, clean, uflag, Uflag;
73
	gid_t *groups = NULL;
62
	char *cleanenv;
74
	int ch, ngroups, uflag, Uflag;
63
	const struct passwd *pwd = NULL;
75
	long ngroups_max;
64
	const char *username, *shell, *term;
76
	char *username;
77
65
78
	ch = uflag = Uflag = 0;
66
	ch = clean = uflag = Uflag = 0;
79
	username = NULL;
67
	username = NULL;
80
	ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
81
	if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
82
		err(1, "malloc");
83
68
84
	while ((ch = getopt(argc, argv, "nu:U:")) != -1) {
69
	while ((ch = getopt(argc, argv, "lnu:U:")) != -1) {
85
		switch (ch) {
70
		switch (ch) {
71
		case 'l':
72
			clean = 1;
73
			break;
86
		case 'n':
74
		case 'n':
87
			/* Specified name, now unused */
75
			/* Specified name, now unused */
88
			break;
76
			break;
Lines 100-111 Link Here
100
	}
88
	}
101
	argc -= optind;
89
	argc -= optind;
102
	argv += optind;
90
	argv += optind;
103
	if (argc < 2)
91
	if (argc < 1)
104
		usage();
92
		usage();
105
	if (uflag && Uflag)
93
	if (uflag && Uflag)
106
		usage();
94
		usage();
107
	if (uflag)
95
	if (uflag || (clean && !Uflag))
108
		GET_USER_INFO;
96
		/* User info from the home environment */
97
		get_user_info(username, &pwd, &lcap);
98
99
	/* Attach to the jail */
109
	jid = jail_getid(argv[0]);
100
	jid = jail_getid(argv[0]);
110
	if (jid < 0)
101
	if (jid < 0)
111
		errx(1, "%s", jail_errmsg);
102
		errx(1, "%s", jail_errmsg);
Lines 113-140 Link Here
113
		err(1, "jail_attach(%d)", jid);
104
		err(1, "jail_attach(%d)", jid);
114
	if (chdir("/") == -1)
105
	if (chdir("/") == -1)
115
		err(1, "chdir(): /");
106
		err(1, "chdir(): /");
116
	if (username != NULL) {
107
108
	/* Set up user environment */
109
	if (clean || username != NULL) {
117
		if (Uflag)
110
		if (Uflag)
118
			GET_USER_INFO;
111
			/* User info from the jail environment */
119
		if (setgroups(ngroups, groups) != 0)
112
			get_user_info(username, &pwd, &lcap);
120
			err(1, "setgroups");
113
		if (clean) {
114
			term = getenv("TERM");
115
			cleanenv = NULL;
116
			environ = &cleanenv;
117
			setenv("PATH", "/bin:/usr/bin", 1);
118
			if (term != NULL)
119
				setenv("TERM", term, 1);
120
		}
121
		if (setgid(pwd->pw_gid) != 0)
121
		if (setgid(pwd->pw_gid) != 0)
122
			err(1, "setgid");
122
			err(1, "setgid");
123
		if (setusercontext(lcap, pwd, pwd->pw_uid,
123
		if (setusercontext(lcap, pwd, pwd->pw_uid, username
124
		    LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN) != 0)
124
		    ? LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN
125
		    : LOGIN_SETPATH | LOGIN_SETENV) != 0)
125
			err(1, "setusercontext");
126
			err(1, "setusercontext");
126
		login_close(lcap);
127
		login_close(lcap);
128
		setenv("USER", pwd->pw_name, 1);
129
		setenv("HOME", pwd->pw_dir, 1);
130
		setenv("SHELL",
131
		    *pwd->pw_shell ? pwd->pw_shell : _PATH_BSHELL, 1);
132
		if (clean && chdir(pwd->pw_dir) < 0)
133
			err(1, "chdir: %s", pwd->pw_dir);
134
		endpwent();
127
	}
135
	}
128
	if (execvp(argv[1], argv + 1) == -1)
136
129
		err(1, "execvp(): %s", argv[1]);
137
	/* Run the specified command, or the shell */
138
	if (argc > 1) {
139
		if (execvp(argv[1], argv + 1) < 0)
140
			err(1, "execvp: %s", argv[1]);
141
	} else {
142
		if (!(shell = getenv("SHELL")))
143
			shell = _PATH_BSHELL;
144
		if (execlp(shell, shell, "-i", NULL) < 0)
145
			err(1, "execlp: %s", shell);
146
	}
130
	exit(0);
147
	exit(0);
131
}
148
}
132
149
133
static void
150
static void
151
get_user_info(const char *username, const struct passwd **pwdp,
152
    login_cap_t **lcapp)
153
{
154
	uid_t uid;
155
	const struct passwd *pwd;
156
157
	errno = 0;
158
	if (username) {
159
		pwd = getpwnam(username);
160
		if (pwd == NULL) {
161
			if (errno)
162
				err(1, "getpwnam: %s", username);
163
			else
164
				errx(1, "%s: no such user", username);
165
		}
166
	} else {
167
		uid = getuid();
168
		pwd = getpwuid(uid);
169
		if (pwd == NULL) {
170
			if (errno)
171
				err(1, "getpwuid: %d", uid);
172
			else
173
				errx(1, "unknown uid: %d", uid);
174
		}
175
	}
176
	*pwdp = pwd;
177
	*lcapp = login_getpwclass(pwd);
178
	if (*lcapp == NULL)
179
		err(1, "getpwclass: %s", pwd->pw_name);
180
	if (initgroups(pwd->pw_name, pwd->pw_gid) < 0)
181
		err(1, "initgroups: %s", pwd->pw_name);
182
}
183
184
static void
134
usage(void)
185
usage(void)
135
{
186
{
136
187
137
	fprintf(stderr, "%s\n",
188
	fprintf(stderr, "%s\n",
138
		"usage: jexec [-u username | -U username] jail command ...");
189
	    "usage: jexec [-l] [-u username | -U username] jail [command ...]");
139
	exit(1); 
190
	exit(1); 
140
}
191
}

Return to bug 201300