Deleted Added
full compact
jexec.c (179415) jexec.c (185435)
1/*-
2 * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
1/*-
2 * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
3 * Copyright (c) 2008 Bjoern A. Zeeb <bz@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright

--- 7 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright

--- 7 unchanged lines hidden (view full) ---

19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
26 * $FreeBSD: head/usr.sbin/jexec/jexec.c 179415 2008-05-29 17:00:01Z mr $
27 * $FreeBSD: head/usr.sbin/jexec/jexec.c 185435 2008-11-29 14:32:14Z bz $
27 */
28
29#include <sys/param.h>
30#include <sys/jail.h>
31#include <sys/sysctl.h>
32
28 */
29
30#include <sys/param.h>
31#include <sys/jail.h>
32#include <sys/sysctl.h>
33
33#include <arpa/inet.h>
34#include <netinet/in.h>
34
35#include <err.h>
36#include <errno.h>
35
36#include <err.h>
37#include <errno.h>
37#include <limits.h>
38#include <login_cap.h>
39#include <stdio.h>
40#include <stdlib.h>
38#include <login_cap.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
41#include <pwd.h>
42#include <unistd.h>
42#include <pwd.h>
43#include <unistd.h>
43#include <string.h>
44
45static void usage(void);
44
45static void usage(void);
46static int addr2jid(const char *addr);
47
46
47#ifdef SUPPORT_OLD_XPRISON
48static
49char *lookup_xprison_v1(void *p, char *end, int *id)
50{
51 struct xprison_v1 *xp;
52
53 if (id == NULL)
54 errx(1, "Internal error. Invalid ID pointer.");
55
56 if ((char *)p + sizeof(struct xprison_v1) > end)
57 errx(1, "Invalid length for jail");
58
59 xp = (struct xprison_v1 *)p;
60
61 *id = xp->pr_id;
62 return ((char *)(xp + 1));
63}
64#endif
65
66static
67char *lookup_xprison_v3(void *p, char *end, int *id, char *jailname)
68{
69 struct xprison *xp;
70 char *q;
71 int ok;
72
73 if (id == NULL)
74 errx(1, "Internal error. Invalid ID pointer.");
75
76 if ((char *)p + sizeof(struct xprison) > end)
77 errx(1, "Invalid length for jail");
78
79 xp = (struct xprison *)p;
80 ok = 1;
81
82 /* Jail state and name. */
83 if (xp->pr_state < 0 || xp->pr_state >
84 (int)((sizeof(prison_states) / sizeof(struct prison_state))))
85 errx(1, "Invalid jail state.");
86 else if (xp->pr_state != PRISON_STATE_ALIVE)
87 ok = 0;
88 if (jailname != NULL) {
89 if (xp->pr_name == NULL)
90 ok = 0;
91 else if (strcmp(jailname, xp->pr_name) != 0)
92 ok = 0;
93 }
94
95 q = (char *)(xp + 1);
96 /* IPv4 addresses. */
97 q += (xp->pr_ip4s * sizeof(struct in_addr));
98 if ((char *)q > end)
99 errx(1, "Invalid length for jail");
100 /* IPv6 addresses. */
101 q += (xp->pr_ip6s * sizeof(struct in6_addr));
102 if ((char *)q > end)
103 errx(1, "Invalid length for jail");
104
105 if (ok)
106 *id = xp->pr_id;
107 return (q);
108}
109
110static int
111lookup_jail(int jid, char *jailname)
112{
113 size_t i, j, len;
114 void *p, *q;
115 int version, id, xid, count;
116
117 if (sysctlbyname("security.jail.list", NULL, &len, NULL, 0) == -1)
118 err(1, "sysctlbyname(): security.jail.list");
119
120 j = len;
121 for (i = 0; i < 4; i++) {
122 if (len <= 0)
123 exit(0);
124 p = q = malloc(len);
125 if (p == NULL)
126 err(1, "malloc()");
127
128 if (sysctlbyname("security.jail.list", q, &len, NULL, 0) == -1) {
129 if (errno == ENOMEM) {
130 free(p);
131 p = NULL;
132 len += j;
133 continue;
134 }
135 err(1, "sysctlbyname(): security.jail.list");
136 }
137 break;
138 }
139 if (p == NULL)
140 err(1, "sysctlbyname(): security.jail.list");
141 if (len < sizeof(int))
142 errx(1, "This is no prison. Kernel and userland out of sync?");
143 version = *(int *)p;
144 if (version > XPRISON_VERSION)
145 errx(1, "Sci-Fi prison. Kernel/userland out of sync?");
146
147 count = 0;
148 xid = -1;
149 for (; q != NULL && (char *)q + sizeof(int) < (char *)p + len;) {
150 version = *(int *)q;
151 if (version > XPRISON_VERSION)
152 errx(1, "Sci-Fi prison. Kernel/userland out of sync?");
153 id = -1;
154 switch (version) {
155#ifdef SUPPORT_OLD_XPRISON
156 case 1:
157 if (jailname != NULL)
158 errx(1, "Version 1 prisons did not "
159 "support jail names.");
160 q = lookup_xprison_v1(q, (char *)p + len, &id);
161 break;
162 case 2:
163 errx(1, "Version 2 was used by multi-IPv4 jail "
164 "implementations that never made it into the "
165 "official kernel.");
166 /* NOTREACHED */
167 break;
168#endif
169 case 3:
170 q = lookup_xprison_v3(q, (char *)p + len, &id, jailname);
171 break;
172 default:
173 errx(1, "Prison unknown. Kernel/userland out of sync?");
174 /* NOTREACHED */
175 break;
176 }
177 /* Possible match. */
178 if (id > 0) {
179 /* Do we have a jail ID to match as well? */
180 if (jid > 0) {
181 if (jid == id) {
182 xid = id;
183 count++;
184 }
185 } else {
186 xid = id;
187 count++;
188 }
189 }
190 }
191
192 free(p);
193
194 if (count != 1)
195 errx(1, "Could not uniquely identify the jail.");
196
197 return (xid);
198}
199
48#define GET_USER_INFO do { \
49 pwd = getpwnam(username); \
50 if (pwd == NULL) { \
51 if (errno) \
52 err(1, "getpwnam: %s", username); \
53 else \
54 errx(1, "%s: no such user", username); \
55 } \

--- 7 unchanged lines hidden (view full) ---

63
64int
65main(int argc, char *argv[])
66{
67 int jid;
68 login_cap_t *lcap = NULL;
69 struct passwd *pwd = NULL;
70 gid_t groups[NGROUPS];
200#define GET_USER_INFO do { \
201 pwd = getpwnam(username); \
202 if (pwd == NULL) { \
203 if (errno) \
204 err(1, "getpwnam: %s", username); \
205 else \
206 errx(1, "%s: no such user", username); \
207 } \

--- 7 unchanged lines hidden (view full) ---

215
216int
217main(int argc, char *argv[])
218{
219 int jid;
220 login_cap_t *lcap = NULL;
221 struct passwd *pwd = NULL;
222 gid_t groups[NGROUPS];
71 int ch, ngroups, uflag, Uflag, hflag;
72 char *username;
73 ch = uflag = Uflag = hflag = 0;
74 username = NULL;
223 int ch, ngroups, uflag, Uflag;
224 char *jailname, *username;
75
225
76 while ((ch = getopt(argc, argv, "u:U:h")) != -1) {
226 ch = uflag = Uflag = 0;
227 jailname = username = NULL;
228 jid = -1;
229
230 while ((ch = getopt(argc, argv, "i:n:u:U:")) != -1) {
77 switch (ch) {
231 switch (ch) {
232 case 'n':
233 jailname = optarg;
234 break;
78 case 'u':
79 username = optarg;
80 uflag = 1;
81 break;
82 case 'U':
83 username = optarg;
84 Uflag = 1;
85 break;
235 case 'u':
236 username = optarg;
237 uflag = 1;
238 break;
239 case 'U':
240 username = optarg;
241 Uflag = 1;
242 break;
86 case 'h':
87 hflag = 1;
88 break;
89 default:
90 usage();
91 }
92 }
93 argc -= optind;
94 argv += optind;
95 if (argc < 2)
96 usage();
243 default:
244 usage();
245 }
246 }
247 argc -= optind;
248 argv += optind;
249 if (argc < 2)
250 usage();
251 if (strlen(argv[0]) > 0) {
252 jid = (int)strtol(argv[0], NULL, 10);
253 if (errno)
254 err(1, "Unable to parse jail ID.");
255 }
256 if (jid <= 0 && jailname == NULL) {
257 fprintf(stderr, "Neither jail ID nor jail name given.\n");
258 usage();
259 }
97 if (uflag && Uflag)
98 usage();
99 if (uflag)
100 GET_USER_INFO;
260 if (uflag && Uflag)
261 usage();
262 if (uflag)
263 GET_USER_INFO;
101 if (hflag) {
102 if ((jid = addr2jid(argv[0])) == 0)
103 errx(1, "jail_attach(): Cannot convert %s to jid", argv[0]);
104 } else
105 jid = (int)strtol(argv[0], NULL, 10);
264 jid = lookup_jail(jid, jailname);
265 if (jid <= 0)
266 errx(1, "Cannot identify jail.");
106 if (jail_attach(jid) == -1)
107 err(1, "jail_attach(): %d", jid);
108 if (chdir("/") == -1)
109 err(1, "chdir(): /");
110 if (username != NULL) {
111 if (Uflag)
112 GET_USER_INFO;
113 if (setgroups(ngroups, groups) != 0)

--- 11 unchanged lines hidden (view full) ---

125}
126
127static void
128usage(void)
129{
130
131 fprintf(stderr, "%s%s\n",
132 "usage: jexec [-u username | -U username]",
267 if (jail_attach(jid) == -1)
268 err(1, "jail_attach(): %d", jid);
269 if (chdir("/") == -1)
270 err(1, "chdir(): /");
271 if (username != NULL) {
272 if (Uflag)
273 GET_USER_INFO;
274 if (setgroups(ngroups, groups) != 0)

--- 11 unchanged lines hidden (view full) ---

286}
287
288static void
289usage(void)
290{
291
292 fprintf(stderr, "%s%s\n",
293 "usage: jexec [-u username | -U username]",
133 " [-h hostname | -h ip-number | jid] command ...");
294 " [-n jailname] jid command ...");
134 exit(1);
135}
295 exit(1);
296}
136
137static int
138addr2jid(const char *addr)
139{
140 struct xprison *sxp, *xp;
141 struct in_addr in;
142 size_t i, len;
143 int jid, cnt;
144 jid = cnt = 0;
145
146 if (sysctlbyname("security.jail.list", NULL, &len, NULL, 0) == -1)
147 err(1, "sysctlbyname(): security.jail.list");
148 for (i = 0; i < 4; i++) {
149 if (len <= 0)
150 err(1, "sysctlbyname(): len <=0");
151 sxp = xp = malloc(len);
152 if (sxp == NULL)
153 err(1, "malloc()");
154 if (sysctlbyname("security.jail.list", xp, &len, NULL, 0) == -1) {
155 if (errno == ENOMEM) {
156 free(sxp);
157 sxp = NULL;
158 continue;
159 }
160 err(1, "sysctlbyname(): security.jail.list");
161 }
162 break;
163 }
164 if (sxp == NULL)
165 err(1, "sysctlbyname(): security.jail.list");
166 if (len < sizeof(*xp) || len % sizeof(*xp) ||
167 xp->pr_version != XPRISON_VERSION)
168 errx(1, "Kernel and userland out of sync");
169 for (i = 0; i < len / sizeof(*xp); i++) {
170 in.s_addr = ntohl(xp->pr_ip);
171 if ((strcmp(inet_ntoa(in), addr) == 0) ||
172 (strcmp(xp->pr_host, addr) == 0)) {
173 jid = xp->pr_id;
174 cnt++;
175 }
176 xp++;
177 }
178 free(sxp);
179 if (cnt == 1)
180 return (jid);
181 else
182 return(0);
183}