Deleted Added
full compact
kern_jail.c (185404) kern_jail.c (185435)
1/*-
1/*-
2 * Copyright (c) 1999 Poul-Henning Kamp. All rights reserved.
2 * Copyright (c) 1999 Poul-Henning Kamp.
3 * Copyright (c) 2008 Bjoern A. Zeeb.
4 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the

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

19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#include <sys/cdefs.h>
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
12 * notice, this list of conditions and the following disclaimer in the

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

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 */
27
28#include <sys/cdefs.h>
27__FBSDID("$FreeBSD: head/sys/kern/kern_jail.c 185404 2008-11-28 19:23:46Z bz $");
29__FBSDID("$FreeBSD: head/sys/kern/kern_jail.c 185435 2008-11-29 14:32:14Z bz $");
28
30
31#include "opt_ddb.h"
32#include "opt_inet.h"
33#include "opt_inet6.h"
29#include "opt_mac.h"
30
31#include <sys/param.h>
32#include <sys/types.h>
33#include <sys/kernel.h>
34#include <sys/systm.h>
35#include <sys/errno.h>
36#include <sys/sysproto.h>

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

49#include <sys/socket.h>
50#include <sys/syscallsubr.h>
51#include <sys/sysctl.h>
52#include <sys/vnode.h>
53#include <sys/vimage.h>
54#include <sys/osd.h>
55#include <net/if.h>
56#include <netinet/in.h>
34#include "opt_mac.h"
35
36#include <sys/param.h>
37#include <sys/types.h>
38#include <sys/kernel.h>
39#include <sys/systm.h>
40#include <sys/errno.h>
41#include <sys/sysproto.h>

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

54#include <sys/socket.h>
55#include <sys/syscallsubr.h>
56#include <sys/sysctl.h>
57#include <sys/vnode.h>
58#include <sys/vimage.h>
59#include <sys/osd.h>
60#include <net/if.h>
61#include <netinet/in.h>
62#ifdef DDB
63#include <ddb/ddb.h>
64#ifdef INET6
65#include <netinet6/in6_var.h>
66#endif /* INET6 */
67#endif /* DDB */
57
58#include <security/mac/mac_framework.h>
59
60MALLOC_DEFINE(M_PRISON, "prison", "Prison structures");
61
62SYSCTL_NODE(_security, OID_AUTO, jail, CTLFLAG_RW, 0,
63 "Jail rules");
64
65int jail_set_hostname_allowed = 1;
66SYSCTL_INT(_security_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,
67 &jail_set_hostname_allowed, 0,
68 "Processes in jail can set their hostnames");
69
70int jail_socket_unixiproute_only = 1;
71SYSCTL_INT(_security_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,
72 &jail_socket_unixiproute_only, 0,
68
69#include <security/mac/mac_framework.h>
70
71MALLOC_DEFINE(M_PRISON, "prison", "Prison structures");
72
73SYSCTL_NODE(_security, OID_AUTO, jail, CTLFLAG_RW, 0,
74 "Jail rules");
75
76int jail_set_hostname_allowed = 1;
77SYSCTL_INT(_security_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,
78 &jail_set_hostname_allowed, 0,
79 "Processes in jail can set their hostnames");
80
81int jail_socket_unixiproute_only = 1;
82SYSCTL_INT(_security_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,
83 &jail_socket_unixiproute_only, 0,
73 "Processes in jail are limited to creating UNIX/IPv4/route sockets only");
84 "Processes in jail are limited to creating UNIX/IP/route sockets only");
74
75int jail_sysvipc_allowed = 0;
76SYSCTL_INT(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
77 &jail_sysvipc_allowed, 0,
78 "Processes in jail can use System V IPC primitives");
79
80static int jail_enforce_statfs = 2;
81SYSCTL_INT(_security_jail, OID_AUTO, enforce_statfs, CTLFLAG_RW,

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

92 &jail_chflags_allowed, 0,
93 "Processes in jail can alter system file flags");
94
95int jail_mount_allowed = 0;
96SYSCTL_INT(_security_jail, OID_AUTO, mount_allowed, CTLFLAG_RW,
97 &jail_mount_allowed, 0,
98 "Processes in jail can mount/unmount jail-friendly file systems");
99
85
86int jail_sysvipc_allowed = 0;
87SYSCTL_INT(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
88 &jail_sysvipc_allowed, 0,
89 "Processes in jail can use System V IPC primitives");
90
91static int jail_enforce_statfs = 2;
92SYSCTL_INT(_security_jail, OID_AUTO, enforce_statfs, CTLFLAG_RW,

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

103 &jail_chflags_allowed, 0,
104 "Processes in jail can alter system file flags");
105
106int jail_mount_allowed = 0;
107SYSCTL_INT(_security_jail, OID_AUTO, mount_allowed, CTLFLAG_RW,
108 &jail_mount_allowed, 0,
109 "Processes in jail can mount/unmount jail-friendly file systems");
110
111int jail_max_af_ips = 255;
112SYSCTL_INT(_security_jail, OID_AUTO, jail_max_af_ips, CTLFLAG_RW,
113 &jail_max_af_ips, 0,
114 "Number of IP addresses a jail may have at most per address family");
115
100/* allprison, lastprid, and prisoncount are protected by allprison_lock. */
101struct prisonlist allprison;
102struct sx allprison_lock;
103int lastprid = 0;
104int prisoncount = 0;
105
106static void init_prison(void *);
107static void prison_complete(void *context, int pending);
108static int sysctl_jail_list(SYSCTL_HANDLER_ARGS);
116/* allprison, lastprid, and prisoncount are protected by allprison_lock. */
117struct prisonlist allprison;
118struct sx allprison_lock;
119int lastprid = 0;
120int prisoncount = 0;
121
122static void init_prison(void *);
123static void prison_complete(void *context, int pending);
124static int sysctl_jail_list(SYSCTL_HANDLER_ARGS);
125#ifdef INET
126static int _prison_check_ip4(struct prison *, struct in_addr *);
127#endif
128#ifdef INET6
129static int _prison_check_ip6(struct prison *, struct in6_addr *);
130#endif
109
110static void
111init_prison(void *data __unused)
112{
113
114 sx_init(&allprison_lock, "allprison");
115 LIST_INIT(&allprison);
116}
117
118SYSINIT(prison, SI_SUB_INTRINSIC, SI_ORDER_ANY, init_prison, NULL);
119
131
132static void
133init_prison(void *data __unused)
134{
135
136 sx_init(&allprison_lock, "allprison");
137 LIST_INIT(&allprison);
138}
139
140SYSINIT(prison, SI_SUB_INTRINSIC, SI_ORDER_ANY, init_prison, NULL);
141
142#ifdef INET
143static int
144qcmp_v4(const void *ip1, const void *ip2)
145{
146 in_addr_t iaa, iab;
147
148 /*
149 * We need to compare in HBO here to get the list sorted as expected
150 * by the result of the code. Sorting NBO addresses gives you
151 * interesting results. If you do not understand, do not try.
152 */
153 iaa = ntohl(((const struct in_addr *)ip1)->s_addr);
154 iab = ntohl(((const struct in_addr *)ip2)->s_addr);
155
156 /*
157 * Do not simply return the difference of the two numbers, the int is
158 * not wide enough.
159 */
160 if (iaa > iab)
161 return (1);
162 else if (iaa < iab)
163 return (-1);
164 else
165 return (0);
166}
167#endif
168
169#ifdef INET6
170static int
171qcmp_v6(const void *ip1, const void *ip2)
172{
173 const struct in6_addr *ia6a, *ia6b;
174 int i, rc;
175
176 ia6a = (const struct in6_addr *)ip1;
177 ia6b = (const struct in6_addr *)ip2;
178
179 rc = 0;
180 for (i=0; rc == 0 && i < sizeof(struct in6_addr); i++) {
181 if (ia6a->s6_addr[i] > ia6b->s6_addr[i])
182 rc = 1;
183 else if (ia6a->s6_addr[i] < ia6b->s6_addr[i])
184 rc = -1;
185 }
186 return (rc);
187}
188#endif
189
190#if defined(INET) || defined(INET6)
191static int
192prison_check_conflicting_ips(struct prison *p)
193{
194 struct prison *pr;
195 int i;
196
197 sx_assert(&allprison_lock, SX_LOCKED);
198
199 if (p->pr_ip4s == 0 && p->pr_ip6s == 0)
200 return (0);
201
202 LIST_FOREACH(pr, &allprison, pr_list) {
203 /*
204 * Skip 'dying' prisons to avoid problems when
205 * restarting multi-IP jails.
206 */
207 if (pr->pr_state == PRISON_STATE_DYING)
208 continue;
209
210 /*
211 * We permit conflicting IPs if there is no
212 * more than 1 IP on eeach jail.
213 * In case there is one duplicate on a jail with
214 * more than one IP stop checking and return error.
215 */
216#ifdef INET
217 if ((p->pr_ip4s >= 1 && pr->pr_ip4s > 1) ||
218 (p->pr_ip4s > 1 && pr->pr_ip4s >= 1)) {
219 for (i = 0; i < p->pr_ip4s; i++) {
220 if (_prison_check_ip4(pr, &p->pr_ip4[i]))
221 return (EINVAL);
222 }
223 }
224#endif
225#ifdef INET6
226 if ((p->pr_ip6s >= 1 && pr->pr_ip6s > 1) ||
227 (p->pr_ip6s > 1 && pr->pr_ip6s >= 1)) {
228 for (i = 0; i < p->pr_ip6s; i++) {
229 if (_prison_check_ip6(pr, &p->pr_ip6[i]))
230 return (EINVAL);
231 }
232 }
233#endif
234 }
235
236 return (0);
237}
238
239static int
240jail_copyin_ips(struct jail *j)
241{
242#ifdef INET
243 struct in_addr *ip4;
244#endif
245#ifdef INET6
246 struct in6_addr *ip6;
247#endif
248 int error, i;
249
250 /*
251 * Copy in addresses, check for duplicate addresses and do some
252 * simple 0 and broadcast checks. If users give other bogus addresses
253 * it is their problem.
254 *
255 * IP addresses are all sorted but ip[0] to preserve the primary IP
256 * address as given from userland. This special IP is used for
257 * unbound outgoing connections as well for "loopback" traffic.
258 */
259#ifdef INET
260 ip4 = NULL;
261#endif
262#ifdef INET6
263 ip6 = NULL;
264#endif
265#ifdef INET
266 if (j->ip4s > 0) {
267 ip4 = (struct in_addr *)malloc(j->ip4s * sizeof(struct in_addr),
268 M_PRISON, M_WAITOK | M_ZERO);
269 error = copyin(j->ip4, ip4, j->ip4s * sizeof(struct in_addr));
270 if (error)
271 goto e_free_ip;
272 /* Sort all but the first IPv4 address. */
273 if (j->ip4s > 1)
274 qsort((ip4 + 1), j->ip4s - 1,
275 sizeof(struct in_addr), qcmp_v4);
276
277 /*
278 * We do not have to care about byte order for these checks
279 * so we will do them in NBO.
280 */
281 for (i=0; i<j->ip4s; i++) {
282 if (ip4[i].s_addr == htonl(INADDR_ANY) ||
283 ip4[i].s_addr == htonl(INADDR_BROADCAST)) {
284 error = EINVAL;
285 goto e_free_ip;
286 }
287 if ((i+1) < j->ip4s &&
288 (ip4[0].s_addr == ip4[i+1].s_addr ||
289 ip4[i].s_addr == ip4[i+1].s_addr)) {
290 error = EINVAL;
291 goto e_free_ip;
292 }
293 }
294
295 j->ip4 = ip4;
296 }
297#endif
298#ifdef INET6
299 if (j->ip6s > 0) {
300 ip6 = (struct in6_addr *)malloc(j->ip6s * sizeof(struct in6_addr),
301 M_PRISON, M_WAITOK | M_ZERO);
302 error = copyin(j->ip6, ip6, j->ip6s * sizeof(struct in6_addr));
303 if (error)
304 goto e_free_ip;
305 /* Sort all but the first IPv6 address. */
306 if (j->ip6s > 1)
307 qsort((ip6 + 1), j->ip6s - 1,
308 sizeof(struct in6_addr), qcmp_v6);
309 for (i=0; i<j->ip6s; i++) {
310 if (IN6_IS_ADDR_UNSPECIFIED(&ip6[i])) {
311 error = EINVAL;
312 goto e_free_ip;
313 }
314 if ((i+1) < j->ip6s &&
315 (IN6_ARE_ADDR_EQUAL(&ip6[0], &ip6[i+1]) ||
316 IN6_ARE_ADDR_EQUAL(&ip6[i], &ip6[i+1]))) {
317 error = EINVAL;
318 goto e_free_ip;
319 }
320 }
321
322 j->ip6 = ip6;
323 }
324#endif
325 return (0);
326
327e_free_ip:
328#ifdef INET6
329 free(ip6, M_PRISON);
330#endif
331#ifdef INET
332 free(ip4, M_PRISON);
333#endif
334 return (error);
335}
336#endif /* INET || INET6 */
337
338static int
339jail_handle_ips(struct jail *j)
340{
341#if defined(INET) || defined(INET6)
342 int error;
343#endif
344
345 /*
346 * Finish conversion for older versions, copyin and setup IPs.
347 */
348 switch (j->version) {
349 case 0:
350 {
351#ifdef INET
352 /* FreeBSD single IPv4 jails. */
353 struct in_addr *ip4;
354
355 if (j->ip4s == INADDR_ANY || j->ip4s == INADDR_BROADCAST)
356 return (EINVAL);
357 ip4 = (struct in_addr *)malloc(sizeof(struct in_addr),
358 M_PRISON, M_WAITOK | M_ZERO);
359
360 /*
361 * Jail version 0 still used HBO for the IPv4 address.
362 */
363 ip4->s_addr = htonl(j->ip4s);
364 j->ip4s = 1;
365 j->ip4 = ip4;
366 break;
367#else
368 return (EINVAL);
369#endif
370 }
371
372 case 1:
373 /*
374 * Version 1 was used by multi-IPv4 jail implementations
375 * that never made it into the official kernel.
376 * We should never hit this here; jail() should catch it.
377 */
378 return (EINVAL);
379
380 case 2: /* JAIL_API_VERSION */
381 /* FreeBSD multi-IPv4/IPv6,noIP jails. */
382#if defined(INET) || defined(INET6)
383#ifdef INET
384 if (j->ip4s > jail_max_af_ips)
385 return (EINVAL);
386#else
387 if (j->ip4s != 0)
388 return (EINVAL);
389#endif
390#ifdef INET6
391 if (j->ip6s > jail_max_af_ips)
392 return (EINVAL);
393#else
394 if (j->ip6s != 0)
395 return (EINVAL);
396#endif
397 error = jail_copyin_ips(j);
398 if (error)
399 return (error);
400#endif
401 break;
402
403 default:
404 /* Sci-Fi jails are not supported, sorry. */
405 return (EINVAL);
406 }
407
408 return (0);
409}
410
411
120/*
121 * struct jail_args {
122 * struct jail *jail;
123 * };
124 */
125int
126jail(struct thread *td, struct jail_args *uap)
127{
412/*
413 * struct jail_args {
414 * struct jail *jail;
415 * };
416 */
417int
418jail(struct thread *td, struct jail_args *uap)
419{
420 uint32_t version;
421 int error;
422 struct jail j;
423
424 error = copyin(uap->jail, &version, sizeof(uint32_t));
425 if (error)
426 return (error);
427
428 switch (version) {
429 case 0:
430 /* FreeBSD single IPv4 jails. */
431 {
432 struct jail_v0 j0;
433
434 bzero(&j, sizeof(struct jail));
435 error = copyin(uap->jail, &j0, sizeof(struct jail_v0));
436 if (error)
437 return (error);
438 j.version = j0.version;
439 j.path = j0.path;
440 j.hostname = j0.hostname;
441 j.ip4s = j0.ip_number;
442 break;
443 }
444
445 case 1:
446 /*
447 * Version 1 was used by multi-IPv4 jail implementations
448 * that never made it into the official kernel.
449 */
450 return (EINVAL);
451
452 case 2: /* JAIL_API_VERSION */
453 /* FreeBSD multi-IPv4/IPv6,noIP jails. */
454 error = copyin(uap->jail, &j, sizeof(struct jail));
455 if (error)
456 return (error);
457 break;
458
459 default:
460 /* Sci-Fi jails are not supported, sorry. */
461 return (EINVAL);
462 }
463 return (kern_jail(td, &j));
464}
465
466int
467kern_jail(struct thread *td, struct jail *j)
468{
128 struct nameidata nd;
129 struct prison *pr, *tpr;
469 struct nameidata nd;
470 struct prison *pr, *tpr;
130 struct jail j;
131 struct jail_attach_args jaa;
132 int vfslocked, error, tryprid;
133
471 struct jail_attach_args jaa;
472 int vfslocked, error, tryprid;
473
134 error = copyin(uap->jail, &j, sizeof(j));
474 KASSERT(j != NULL, ("%s: j is NULL", __func__));
475
476 /* Handle addresses - convert old structs, copyin, check IPs. */
477 error = jail_handle_ips(j);
135 if (error)
136 return (error);
478 if (error)
479 return (error);
137 if (j.version != 0)
138 return (EINVAL);
139
480
481 /* Allocate struct prison and fill it with life. */
140 pr = malloc(sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO);
141 mtx_init(&pr->pr_mtx, "jail mutex", NULL, MTX_DEF);
142 pr->pr_ref = 1;
482 pr = malloc(sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO);
483 mtx_init(&pr->pr_mtx, "jail mutex", NULL, MTX_DEF);
484 pr->pr_ref = 1;
143 error = copyinstr(j.path, &pr->pr_path, sizeof(pr->pr_path), 0);
485 error = copyinstr(j->path, &pr->pr_path, sizeof(pr->pr_path), NULL);
144 if (error)
145 goto e_killmtx;
146 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF, UIO_SYSSPACE,
147 pr->pr_path, td);
148 error = namei(&nd);
149 if (error)
150 goto e_killmtx;
151 vfslocked = NDHASGIANT(&nd);
152 pr->pr_root = nd.ni_vp;
153 VOP_UNLOCK(nd.ni_vp, 0);
154 NDFREE(&nd, NDF_ONLY_PNBUF);
155 VFS_UNLOCK_GIANT(vfslocked);
486 if (error)
487 goto e_killmtx;
488 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF, UIO_SYSSPACE,
489 pr->pr_path, td);
490 error = namei(&nd);
491 if (error)
492 goto e_killmtx;
493 vfslocked = NDHASGIANT(&nd);
494 pr->pr_root = nd.ni_vp;
495 VOP_UNLOCK(nd.ni_vp, 0);
496 NDFREE(&nd, NDF_ONLY_PNBUF);
497 VFS_UNLOCK_GIANT(vfslocked);
156 error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0);
498 error = copyinstr(j->hostname, &pr->pr_host, sizeof(pr->pr_host), NULL);
157 if (error)
158 goto e_dropvnref;
499 if (error)
500 goto e_dropvnref;
159 pr->pr_ip = j.ip_number;
501 if (j->jailname != NULL) {
502 error = copyinstr(j->jailname, &pr->pr_name,
503 sizeof(pr->pr_name), NULL);
504 if (error)
505 goto e_dropvnref;
506 }
507 if (j->ip4s > 0) {
508 pr->pr_ip4 = j->ip4;
509 pr->pr_ip4s = j->ip4s;
510 }
511#ifdef INET6
512 if (j->ip6s > 0) {
513 pr->pr_ip6 = j->ip6;
514 pr->pr_ip6s = j->ip6s;
515 }
516#endif
160 pr->pr_linux = NULL;
161 pr->pr_securelevel = securelevel;
162 bzero(&pr->pr_osd, sizeof(pr->pr_osd));
163
517 pr->pr_linux = NULL;
518 pr->pr_securelevel = securelevel;
519 bzero(&pr->pr_osd, sizeof(pr->pr_osd));
520
164 /* Determine next pr_id and add prison to allprison list. */
521 /*
522 * Pre-set prison state to ALIVE upon cration. This is needed so we
523 * can later attach the process to it, etc (avoiding another extra
524 * state for ther process of creation, complicating things).
525 */
526 pr->pr_state = PRISON_STATE_ALIVE;
527
528 /* Allocate a dedicated cpuset for each jail. */
529 error = cpuset_create_root(td, &pr->pr_cpuset);
530 if (error)
531 goto e_dropvnref;
532
165 sx_xlock(&allprison_lock);
533 sx_xlock(&allprison_lock);
534 /* Make sure we cannot run into problems with ambiguous bind()ings. */
535 error = prison_check_conflicting_ips(pr);
536 if (error) {
537 sx_xunlock(&allprison_lock);
538 goto e_dropcpuset;
539 }
540
541 /* Determine next pr_id and add prison to allprison list. */
166 tryprid = lastprid + 1;
167 if (tryprid == JAIL_MAX)
168 tryprid = 1;
169next:
170 LIST_FOREACH(tpr, &allprison, pr_list) {
171 if (tpr->pr_id == tryprid) {
172 tryprid++;
173 if (tryprid == JAIL_MAX) {
174 sx_xunlock(&allprison_lock);
175 error = EAGAIN;
542 tryprid = lastprid + 1;
543 if (tryprid == JAIL_MAX)
544 tryprid = 1;
545next:
546 LIST_FOREACH(tpr, &allprison, pr_list) {
547 if (tpr->pr_id == tryprid) {
548 tryprid++;
549 if (tryprid == JAIL_MAX) {
550 sx_xunlock(&allprison_lock);
551 error = EAGAIN;
176 goto e_dropvnref;
552 goto e_dropcpuset;
177 }
178 goto next;
179 }
180 }
181 pr->pr_id = jaa.jid = lastprid = tryprid;
182 LIST_INSERT_HEAD(&allprison, pr, pr_list);
183 prisoncount++;
184 sx_xunlock(&allprison_lock);

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

191 mtx_unlock(&pr->pr_mtx);
192 td->td_retval[0] = jaa.jid;
193 return (0);
194e_dropprref:
195 sx_xlock(&allprison_lock);
196 LIST_REMOVE(pr, pr_list);
197 prisoncount--;
198 sx_xunlock(&allprison_lock);
553 }
554 goto next;
555 }
556 }
557 pr->pr_id = jaa.jid = lastprid = tryprid;
558 LIST_INSERT_HEAD(&allprison, pr, pr_list);
559 prisoncount++;
560 sx_xunlock(&allprison_lock);

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

567 mtx_unlock(&pr->pr_mtx);
568 td->td_retval[0] = jaa.jid;
569 return (0);
570e_dropprref:
571 sx_xlock(&allprison_lock);
572 LIST_REMOVE(pr, pr_list);
573 prisoncount--;
574 sx_xunlock(&allprison_lock);
575e_dropcpuset:
576 cpuset_rel(pr->pr_cpuset);
199e_dropvnref:
200 vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount);
201 vrele(pr->pr_root);
202 VFS_UNLOCK_GIANT(vfslocked);
203e_killmtx:
204 mtx_destroy(&pr->pr_mtx);
205 free(pr, M_PRISON);
577e_dropvnref:
578 vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount);
579 vrele(pr->pr_root);
580 VFS_UNLOCK_GIANT(vfslocked);
581e_killmtx:
582 mtx_destroy(&pr->pr_mtx);
583 free(pr, M_PRISON);
584#ifdef INET6
585 free(j->ip6, M_PRISON);
586#endif
587#ifdef INET
588 free(j->ip4, M_PRISON);
589#endif
206 return (error);
207}
208
209/*
210 * struct jail_attach_args {
211 * int jid;
212 * };
213 */

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

233
234 p = td->td_proc;
235 sx_slock(&allprison_lock);
236 pr = prison_find(uap->jid);
237 if (pr == NULL) {
238 sx_sunlock(&allprison_lock);
239 return (EINVAL);
240 }
590 return (error);
591}
592
593/*
594 * struct jail_attach_args {
595 * int jid;
596 * };
597 */

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

617
618 p = td->td_proc;
619 sx_slock(&allprison_lock);
620 pr = prison_find(uap->jid);
621 if (pr == NULL) {
622 sx_sunlock(&allprison_lock);
623 return (EINVAL);
624 }
625
626 /*
627 * Do not allow a process to attach to a prison that is not
628 * considered to be "ALIVE".
629 */
630 if (pr->pr_state != PRISON_STATE_ALIVE) {
631 mtx_unlock(&pr->pr_mtx);
632 sx_sunlock(&allprison_lock);
633 return (EINVAL);
634 }
241 pr->pr_ref++;
242 mtx_unlock(&pr->pr_mtx);
243 sx_sunlock(&allprison_lock);
244
635 pr->pr_ref++;
636 mtx_unlock(&pr->pr_mtx);
637 sx_sunlock(&allprison_lock);
638
639 /*
640 * Reparent the newly attached process to this jail.
641 */
642 error = cpuset_setproc_update_set(p, pr->pr_cpuset);
643 if (error)
644 goto e_unref;
645
245 vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount);
246 vn_lock(pr->pr_root, LK_EXCLUSIVE | LK_RETRY);
247 if ((error = change_dir(pr->pr_root, td)) != 0)
248 goto e_unlock;
249#ifdef MAC
250 if ((error = mac_vnode_check_chroot(td->td_ucred, pr->pr_root)))
251 goto e_unlock;
252#endif
253 VOP_UNLOCK(pr->pr_root, 0);
254 change_root(pr->pr_root, td);
255 VFS_UNLOCK_GIANT(vfslocked);
256
257 newcred = crget();
258 PROC_LOCK(p);
259 oldcred = p->p_ucred;
260 setsugid(p);
261 crcopy(newcred, oldcred);
262 newcred->cr_prison = pr;
263 p->p_ucred = newcred;
646 vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount);
647 vn_lock(pr->pr_root, LK_EXCLUSIVE | LK_RETRY);
648 if ((error = change_dir(pr->pr_root, td)) != 0)
649 goto e_unlock;
650#ifdef MAC
651 if ((error = mac_vnode_check_chroot(td->td_ucred, pr->pr_root)))
652 goto e_unlock;
653#endif
654 VOP_UNLOCK(pr->pr_root, 0);
655 change_root(pr->pr_root, td);
656 VFS_UNLOCK_GIANT(vfslocked);
657
658 newcred = crget();
659 PROC_LOCK(p);
660 oldcred = p->p_ucred;
661 setsugid(p);
662 crcopy(newcred, oldcred);
663 newcred->cr_prison = pr;
664 p->p_ucred = newcred;
665 prison_proc_hold(pr);
264 PROC_UNLOCK(p);
265 crfree(oldcred);
266 return (0);
267e_unlock:
268 VOP_UNLOCK(pr->pr_root, 0);
269 VFS_UNLOCK_GIANT(vfslocked);
666 PROC_UNLOCK(p);
667 crfree(oldcred);
668 return (0);
669e_unlock:
670 VOP_UNLOCK(pr->pr_root, 0);
671 VFS_UNLOCK_GIANT(vfslocked);
672e_unref:
270 mtx_lock(&pr->pr_mtx);
271 pr->pr_ref--;
272 mtx_unlock(&pr->pr_mtx);
273 return (error);
274}
275
276/*
277 * Returns a locked prison instance, or NULL on failure.

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

326
327 pr = (struct prison *)context;
328
329 sx_xlock(&allprison_lock);
330 LIST_REMOVE(pr, pr_list);
331 prisoncount--;
332 sx_xunlock(&allprison_lock);
333
673 mtx_lock(&pr->pr_mtx);
674 pr->pr_ref--;
675 mtx_unlock(&pr->pr_mtx);
676 return (error);
677}
678
679/*
680 * Returns a locked prison instance, or NULL on failure.

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

729
730 pr = (struct prison *)context;
731
732 sx_xlock(&allprison_lock);
733 LIST_REMOVE(pr, pr_list);
734 prisoncount--;
735 sx_xunlock(&allprison_lock);
736
737 cpuset_rel(pr->pr_cpuset);
738
334 /* Free all OSD associated to this jail. */
335 osd_jail_exit(pr);
336
337 vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount);
338 vrele(pr->pr_root);
339 VFS_UNLOCK_GIANT(vfslocked);
340
341 mtx_destroy(&pr->pr_mtx);
739 /* Free all OSD associated to this jail. */
740 osd_jail_exit(pr);
741
742 vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount);
743 vrele(pr->pr_root);
744 VFS_UNLOCK_GIANT(vfslocked);
745
746 mtx_destroy(&pr->pr_mtx);
342 if (pr->pr_linux != NULL)
343 free(pr->pr_linux, M_PRISON);
747 free(pr->pr_linux, M_PRISON);
748#ifdef INET6
749 free(pr->pr_ip6, M_PRISON);
750#endif
751#ifdef INET
752 free(pr->pr_ip4, M_PRISON);
753#endif
344 free(pr, M_PRISON);
345}
346
347void
348prison_hold_locked(struct prison *pr)
349{
350
351 mtx_assert(&pr->pr_mtx, MA_OWNED);

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

358prison_hold(struct prison *pr)
359{
360
361 mtx_lock(&pr->pr_mtx);
362 prison_hold_locked(pr);
363 mtx_unlock(&pr->pr_mtx);
364}
365
754 free(pr, M_PRISON);
755}
756
757void
758prison_hold_locked(struct prison *pr)
759{
760
761 mtx_assert(&pr->pr_mtx, MA_OWNED);

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

768prison_hold(struct prison *pr)
769{
770
771 mtx_lock(&pr->pr_mtx);
772 prison_hold_locked(pr);
773 mtx_unlock(&pr->pr_mtx);
774}
775
366u_int32_t
367prison_getip(struct ucred *cred)
776void
777prison_proc_hold(struct prison *pr)
368{
369
778{
779
370 return (cred->cr_prison->pr_ip);
780 mtx_lock(&pr->pr_mtx);
781 KASSERT(pr->pr_state == PRISON_STATE_ALIVE,
782 ("Cannot add a process to a non-alive prison (id=%d).", pr->pr_id));
783 pr->pr_nprocs++;
784 mtx_unlock(&pr->pr_mtx);
371}
372
785}
786
787void
788prison_proc_free(struct prison *pr)
789{
790
791 mtx_lock(&pr->pr_mtx);
792 KASSERT(pr->pr_state == PRISON_STATE_ALIVE && pr->pr_nprocs > 0,
793 ("Trying to kill a process in a dead prison (id=%d).", pr->pr_id));
794 pr->pr_nprocs--;
795 if (pr->pr_nprocs == 0)
796 pr->pr_state = PRISON_STATE_DYING;
797 mtx_unlock(&pr->pr_mtx);
798}
799
800
801#ifdef INET
802/*
803 * Pass back primary IPv4 address of this jail.
804 *
805 * If not jailed return success but do not alter the address. Caller has to
806 * make sure to intialize it correctly (INADDR_ANY).
807 *
808 * Returns 0 on success, 1 on error. Address returned in NBO.
809 */
373int
810int
374prison_ip(struct ucred *cred, int flag, u_int32_t *ip)
811prison_getip4(struct ucred *cred, struct in_addr *ia)
375{
812{
376 u_int32_t tmp;
377
813
814 KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
815 KASSERT(ia != NULL, ("%s: ia is NULL", __func__));
816
378 if (!jailed(cred))
817 if (!jailed(cred))
818 /* Do not change address passed in. */
379 return (0);
819 return (0);
380 if (flag)
381 tmp = *ip;
382 else
383 tmp = ntohl(*ip);
384 if (tmp == INADDR_ANY) {
385 if (flag)
386 *ip = cred->cr_prison->pr_ip;
387 else
388 *ip = htonl(cred->cr_prison->pr_ip);
820
821 if (cred->cr_prison->pr_ip4 == NULL)
822 return (1);
823
824 ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr;
825 return (0);
826}
827
828/*
829 * Make sure our (source) address is set to something meaningful to this
830 * jail.
831 *
832 * Returns 0 on success, 1 on error. Address passed in in NBO and returned
833 * in NBO.
834 */
835int
836prison_local_ip4(struct ucred *cred, struct in_addr *ia)
837{
838 struct in_addr ia0;
839
840 KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
841 KASSERT(ia != NULL, ("%s: ia is NULL", __func__));
842
843 if (!jailed(cred))
389 return (0);
844 return (0);
845 if (cred->cr_prison->pr_ip4 == NULL)
846 return (1);
847
848 ia0.s_addr = ntohl(ia->s_addr);
849 if (ia0.s_addr == INADDR_LOOPBACK) {
850 ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr;
851 return (0);
390 }
852 }
391 if (tmp == INADDR_LOOPBACK) {
392 if (flag)
393 *ip = cred->cr_prison->pr_ip;
394 else
395 *ip = htonl(cred->cr_prison->pr_ip);
853
854 /*
855 * In case there is only 1 IPv4 address, bind directly.
856 */
857 if (ia0.s_addr == INADDR_ANY && cred->cr_prison->pr_ip4s == 1) {
858 ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr;
396 return (0);
397 }
859 return (0);
860 }
398 if (cred->cr_prison->pr_ip != tmp)
861
862 if (ia0.s_addr == INADDR_ANY || prison_check_ip4(cred, ia))
863 return (0);
864
865 return (1);
866}
867
868/*
869 * Rewrite destination address in case we will connect to loopback address.
870 *
871 * Returns 0 on success, 1 on error. Address passed in in NBO and returned
872 * in NBO.
873 */
874int
875prison_remote_ip4(struct ucred *cred, struct in_addr *ia)
876{
877
878 KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
879 KASSERT(ia != NULL, ("%s: ia is NULL", __func__));
880
881 if (!jailed(cred))
882 return (0);
883 if (cred->cr_prison->pr_ip4 == NULL)
399 return (1);
884 return (1);
885 if (ntohl(ia->s_addr) == INADDR_LOOPBACK) {
886 ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr;
887 return (0);
888 }
889
890 /*
891 * Return success because nothing had to be changed.
892 */
400 return (0);
401}
402
893 return (0);
894}
895
403void
404prison_remote_ip(struct ucred *cred, int flag, u_int32_t *ip)
896/*
897 * Check if given address belongs to the jail referenced by cred.
898 *
899 * Returns 1 if address belongs to jail, 0 if not. Address passed in in NBO.
900 */
901static int
902_prison_check_ip4(struct prison *pr, struct in_addr *ia)
405{
903{
406 u_int32_t tmp;
904 int i, a, z, d;
407
905
906 if (pr->pr_ip4 == NULL)
907 return (0);
908
909 /*
910 * Check the primary IP.
911 */
912 if (pr->pr_ip4[0].s_addr == ia->s_addr)
913 return (1);
914
915 /*
916 * All the other IPs are sorted so we can do a binary search.
917 */
918 a = 0;
919 z = pr->pr_ip4s - 2;
920 while (a <= z) {
921 i = (a + z) / 2;
922 d = qcmp_v4(&pr->pr_ip4[i+1], ia);
923 if (d > 0)
924 z = i - 1;
925 else if (d < 0)
926 a = i + 1;
927 else
928 return (1);
929 }
930 return (0);
931}
932
933int
934prison_check_ip4(struct ucred *cred, struct in_addr *ia)
935{
936
937 KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
938 KASSERT(ia != NULL, ("%s: ia is NULL", __func__));
939
408 if (!jailed(cred))
940 if (!jailed(cred))
409 return;
410 if (flag)
411 tmp = *ip;
412 else
413 tmp = ntohl(*ip);
414 if (tmp == INADDR_LOOPBACK) {
415 if (flag)
416 *ip = cred->cr_prison->pr_ip;
941 return (1);
942
943 return (_prison_check_ip4(cred->cr_prison, ia));
944}
945#endif
946
947#ifdef INET6
948/*
949 * Pass back primary IPv6 address for this jail.
950 *
951 * If not jailed return success but do not alter the address. Caller has to
952 * make sure to intialize it correctly (IN6ADDR_ANY_INIT).
953 *
954 * Returns 0 on success, 1 on error.
955 */
956int
957prison_getip6(struct ucred *cred, struct in6_addr *ia6)
958{
959
960 KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
961 KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
962
963 if (!jailed(cred))
964 return (0);
965 if (cred->cr_prison->pr_ip6 == NULL)
966 return (1);
967 bcopy(&cred->cr_prison->pr_ip6[0], ia6, sizeof(struct in6_addr));
968 return (0);
969}
970
971/*
972 * Make sure our (source) address is set to something meaningful to this jail.
973 *
974 * v6only should be set based on (inp->inp_flags & IN6P_IPV6_V6ONLY != 0)
975 * when needed while binding.
976 *
977 * Returns 0 on success, 1 on error.
978 */
979int
980prison_local_ip6(struct ucred *cred, struct in6_addr *ia6, int v6only)
981{
982
983 KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
984 KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
985
986 if (!jailed(cred))
987 return (0);
988 if (cred->cr_prison->pr_ip6 == NULL)
989 return (1);
990 if (IN6_IS_ADDR_LOOPBACK(ia6)) {
991 bcopy(&cred->cr_prison->pr_ip6[0], ia6,
992 sizeof(struct in6_addr));
993 return (0);
994 }
995
996 /*
997 * In case there is only 1 IPv6 address, and v6only is true, then
998 * bind directly.
999 */
1000 if (v6only != 0 && IN6_IS_ADDR_UNSPECIFIED(ia6) &&
1001 cred->cr_prison->pr_ip6s == 1) {
1002 bcopy(&cred->cr_prison->pr_ip6[0], ia6,
1003 sizeof(struct in6_addr));
1004 return (0);
1005 }
1006 if (IN6_IS_ADDR_UNSPECIFIED(ia6) || prison_check_ip6(cred, ia6))
1007 return (0);
1008 return (1);
1009}
1010
1011/*
1012 * Rewrite destination address in case we will connect to loopback address.
1013 *
1014 * Returns 0 on success, 1 on error.
1015 */
1016int
1017prison_remote_ip6(struct ucred *cred, struct in6_addr *ia6)
1018{
1019
1020 KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
1021 KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
1022
1023 if (!jailed(cred))
1024 return (0);
1025 if (cred->cr_prison->pr_ip6 == NULL)
1026 return (1);
1027 if (IN6_IS_ADDR_LOOPBACK(ia6)) {
1028 bcopy(&cred->cr_prison->pr_ip6[0], ia6,
1029 sizeof(struct in6_addr));
1030 return (0);
1031 }
1032
1033 /*
1034 * Return success because nothing had to be changed.
1035 */
1036 return (0);
1037}
1038
1039/*
1040 * Check if given address belongs to the jail referenced by cred.
1041 *
1042 * Returns 1 if address belongs to jail, 0 if not.
1043 */
1044static int
1045_prison_check_ip6(struct prison *pr, struct in6_addr *ia6)
1046{
1047 int i, a, z, d;
1048
1049 if (pr->pr_ip6 == NULL)
1050 return (0);
1051
1052 /*
1053 * Check the primary IP.
1054 */
1055 if (IN6_ARE_ADDR_EQUAL(&pr->pr_ip6[0], ia6))
1056 return (1);
1057
1058 /*
1059 * All the other IPs are sorted so we can do a binary search.
1060 */
1061 a = 0;
1062 z = pr->pr_ip6s - 2;
1063 while (a <= z) {
1064 i = (a + z) / 2;
1065 d = qcmp_v6(&pr->pr_ip6[i+1], ia6);
1066 if (d > 0)
1067 z = i - 1;
1068 else if (d < 0)
1069 a = i + 1;
417 else
1070 else
418 *ip = htonl(cred->cr_prison->pr_ip);
419 return;
1071 return (1);
420 }
1072 }
421 return;
1073 return (0);
422}
423
424int
1074}
1075
1076int
1077prison_check_ip6(struct ucred *cred, struct in6_addr *ia6)
1078{
1079
1080 KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
1081 KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
1082
1083 if (!jailed(cred))
1084 return (1);
1085
1086 return (_prison_check_ip6(cred->cr_prison, ia6));
1087}
1088#endif
1089
1090/*
1091 * Check if given address belongs to the jail referenced by cred (wrapper to
1092 * prison_check_ip[46]).
1093 *
1094 * Returns 1 if address belongs to jail, 0 if not. IPv4 Address passed in in
1095 * NBO.
1096 */
1097int
425prison_if(struct ucred *cred, struct sockaddr *sa)
426{
1098prison_if(struct ucred *cred, struct sockaddr *sa)
1099{
1100#ifdef INET
427 struct sockaddr_in *sai;
1101 struct sockaddr_in *sai;
1102#endif
1103#ifdef INET6
1104 struct sockaddr_in6 *sai6;
1105#endif
428 int ok;
429
1106 int ok;
1107
430 sai = (struct sockaddr_in *)sa;
431 if ((sai->sin_family != AF_INET) && jail_socket_unixiproute_only)
432 ok = 1;
433 else if (sai->sin_family != AF_INET)
434 ok = 0;
435 else if (cred->cr_prison->pr_ip != ntohl(sai->sin_addr.s_addr))
436 ok = 1;
437 else
438 ok = 0;
1108 KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
1109 KASSERT(sa != NULL, ("%s: sa is NULL", __func__));
1110
1111 ok = 0;
1112 switch(sa->sa_family)
1113 {
1114#ifdef INET
1115 case AF_INET:
1116 sai = (struct sockaddr_in *)sa;
1117 if (prison_check_ip4(cred, &sai->sin_addr))
1118 ok = 1;
1119 break;
1120
1121#endif
1122#ifdef INET6
1123 case AF_INET6:
1124 sai6 = (struct sockaddr_in6 *)sa;
1125 if (prison_check_ip6(cred, (struct in6_addr *)&sai6->sin6_addr))
1126 ok = 1;
1127 break;
1128
1129#endif
1130 default:
1131 if (!jail_socket_unixiproute_only)
1132 ok = 1;
1133 }
439 return (ok);
440}
441
442/*
443 * Return 0 if jails permit p1 to frob p2, otherwise ESRCH.
444 */
445int
446prison_check(struct ucred *cred1, struct ucred *cred2)

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

650 case PRIV_MQ_ADMIN:
651
652 /*
653 * Jail implements its own inter-process limits, so allow
654 * root processes in jail to change scheduling on other
655 * processes in the same jail. Likewise for signalling.
656 */
657 case PRIV_SCHED_DIFFCRED:
1134 return (ok);
1135}
1136
1137/*
1138 * Return 0 if jails permit p1 to frob p2, otherwise ESRCH.
1139 */
1140int
1141prison_check(struct ucred *cred1, struct ucred *cred2)

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

1345 case PRIV_MQ_ADMIN:
1346
1347 /*
1348 * Jail implements its own inter-process limits, so allow
1349 * root processes in jail to change scheduling on other
1350 * processes in the same jail. Likewise for signalling.
1351 */
1352 case PRIV_SCHED_DIFFCRED:
1353 case PRIV_SCHED_CPUSET:
658 case PRIV_SIGNAL_DIFFCRED:
659 case PRIV_SIGNAL_SUGID:
660
661 /*
662 * Allow jailed processes to write to sysctls marked as jail
663 * writable.
664 */
665 case PRIV_SYSCTL_WRITEJAIL:

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

759 }
760}
761
762static int
763sysctl_jail_list(SYSCTL_HANDLER_ARGS)
764{
765 struct xprison *xp, *sxp;
766 struct prison *pr;
1354 case PRIV_SIGNAL_DIFFCRED:
1355 case PRIV_SIGNAL_SUGID:
1356
1357 /*
1358 * Allow jailed processes to write to sysctls marked as jail
1359 * writable.
1360 */
1361 case PRIV_SYSCTL_WRITEJAIL:

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

1455 }
1456}
1457
1458static int
1459sysctl_jail_list(SYSCTL_HANDLER_ARGS)
1460{
1461 struct xprison *xp, *sxp;
1462 struct prison *pr;
1463 char *p;
1464 size_t len;
767 int count, error;
768
769 if (jailed(req->td->td_ucred))
770 return (0);
771
772 sx_slock(&allprison_lock);
773 if ((count = prisoncount) == 0) {
774 sx_sunlock(&allprison_lock);
775 return (0);
776 }
777
1465 int count, error;
1466
1467 if (jailed(req->td->td_ucred))
1468 return (0);
1469
1470 sx_slock(&allprison_lock);
1471 if ((count = prisoncount) == 0) {
1472 sx_sunlock(&allprison_lock);
1473 return (0);
1474 }
1475
778 sxp = xp = malloc(sizeof(*xp) * count, M_TEMP, M_WAITOK | M_ZERO);
1476 len = sizeof(*xp) * count;
1477 LIST_FOREACH(pr, &allprison, pr_list) {
1478#ifdef INET
1479 len += pr->pr_ip4s * sizeof(struct in_addr);
1480#endif
1481#ifdef INET6
1482 len += pr->pr_ip6s * sizeof(struct in6_addr);
1483#endif
1484 }
779
1485
1486 sxp = xp = malloc(len, M_TEMP, M_WAITOK | M_ZERO);
1487
780 LIST_FOREACH(pr, &allprison, pr_list) {
781 xp->pr_version = XPRISON_VERSION;
782 xp->pr_id = pr->pr_id;
1488 LIST_FOREACH(pr, &allprison, pr_list) {
1489 xp->pr_version = XPRISON_VERSION;
1490 xp->pr_id = pr->pr_id;
783 xp->pr_ip = pr->pr_ip;
1491 xp->pr_state = pr->pr_state;
1492 xp->pr_cpusetid = pr->pr_cpuset->cs_id;
784 strlcpy(xp->pr_path, pr->pr_path, sizeof(xp->pr_path));
785 mtx_lock(&pr->pr_mtx);
786 strlcpy(xp->pr_host, pr->pr_host, sizeof(xp->pr_host));
1493 strlcpy(xp->pr_path, pr->pr_path, sizeof(xp->pr_path));
1494 mtx_lock(&pr->pr_mtx);
1495 strlcpy(xp->pr_host, pr->pr_host, sizeof(xp->pr_host));
1496 strlcpy(xp->pr_name, pr->pr_name, sizeof(xp->pr_name));
787 mtx_unlock(&pr->pr_mtx);
1497 mtx_unlock(&pr->pr_mtx);
788 xp++;
1498#ifdef INET
1499 xp->pr_ip4s = pr->pr_ip4s;
1500#endif
1501#ifdef INET6
1502 xp->pr_ip6s = pr->pr_ip6s;
1503#endif
1504 p = (char *)(xp + 1);
1505#ifdef INET
1506 if (pr->pr_ip4s > 0) {
1507 bcopy(pr->pr_ip4, (struct in_addr *)p,
1508 pr->pr_ip4s * sizeof(struct in_addr));
1509 p += (pr->pr_ip4s * sizeof(struct in_addr));
1510 }
1511#endif
1512#ifdef INET6
1513 if (pr->pr_ip6s > 0) {
1514 bcopy(pr->pr_ip6, (struct in6_addr *)p,
1515 pr->pr_ip6s * sizeof(struct in6_addr));
1516 p += (pr->pr_ip6s * sizeof(struct in6_addr));
1517 }
1518#endif
1519 xp = (struct xprison *)p;
789 }
790 sx_sunlock(&allprison_lock);
791
1520 }
1521 sx_sunlock(&allprison_lock);
1522
792 error = SYSCTL_OUT(req, sxp, sizeof(*sxp) * count);
1523 error = SYSCTL_OUT(req, sxp, len);
793 free(sxp, M_TEMP);
794 return (error);
795}
796
797SYSCTL_OID(_security_jail, OID_AUTO, list, CTLTYPE_STRUCT | CTLFLAG_RD,
798 NULL, 0, sysctl_jail_list, "S", "List of active jails");
799
800static int
801sysctl_jail_jailed(SYSCTL_HANDLER_ARGS)
802{
803 int error, injail;
804
805 injail = jailed(req->td->td_ucred);
806 error = SYSCTL_OUT(req, &injail, sizeof(injail));
807
808 return (error);
809}
810SYSCTL_PROC(_security_jail, OID_AUTO, jailed, CTLTYPE_INT | CTLFLAG_RD,
811 NULL, 0, sysctl_jail_jailed, "I", "Process in jail?");
1524 free(sxp, M_TEMP);
1525 return (error);
1526}
1527
1528SYSCTL_OID(_security_jail, OID_AUTO, list, CTLTYPE_STRUCT | CTLFLAG_RD,
1529 NULL, 0, sysctl_jail_list, "S", "List of active jails");
1530
1531static int
1532sysctl_jail_jailed(SYSCTL_HANDLER_ARGS)
1533{
1534 int error, injail;
1535
1536 injail = jailed(req->td->td_ucred);
1537 error = SYSCTL_OUT(req, &injail, sizeof(injail));
1538
1539 return (error);
1540}
1541SYSCTL_PROC(_security_jail, OID_AUTO, jailed, CTLTYPE_INT | CTLFLAG_RD,
1542 NULL, 0, sysctl_jail_jailed, "I", "Process in jail?");
1543
1544#ifdef DDB
1545DB_SHOW_COMMAND(jails, db_show_jails)
1546{
1547 struct prison *pr;
1548#ifdef INET
1549 struct in_addr ia;
1550#endif
1551#ifdef INET6
1552 char ip6buf[INET6_ADDRSTRLEN];
1553#endif
1554 const char *state;
1555#if defined(INET) || defined(INET6)
1556 int i;
1557#endif
1558
1559 db_printf(
1560 " JID pr_ref pr_nprocs pr_ip4s pr_ip6s\n");
1561 db_printf(
1562 " Hostname Path\n");
1563 db_printf(
1564 " Name State\n");
1565 db_printf(
1566 " Cpusetid\n");
1567 db_printf(
1568 " IP Address(es)\n");
1569 LIST_FOREACH(pr, &allprison, pr_list) {
1570 db_printf("%6d %6d %9d %7d %7d\n",
1571 pr->pr_id, pr->pr_ref, pr->pr_nprocs,
1572 pr->pr_ip4s, pr->pr_ip6s);
1573 db_printf("%6s %-29.29s %.74s\n",
1574 "", pr->pr_host, pr->pr_path);
1575 if (pr->pr_state < 0 || pr->pr_state > (int)((sizeof(
1576 prison_states) / sizeof(struct prison_state))))
1577 state = "(bogus)";
1578 else
1579 state = prison_states[pr->pr_state].state_name;
1580 db_printf("%6s %-29.29s %.74s\n",
1581 "", (pr->pr_name != NULL) ? pr->pr_name : "", state);
1582 db_printf("%6s %-6d\n",
1583 "", pr->pr_cpuset->cs_id);
1584#ifdef INET
1585 for (i=0; i < pr->pr_ip4s; i++) {
1586 ia.s_addr = pr->pr_ip4[i].s_addr;
1587 db_printf("%6s %s\n", "", inet_ntoa(ia));
1588 }
1589#endif
1590#ifdef INET6
1591 for (i=0; i < pr->pr_ip6s; i++)
1592 db_printf("%6s %s\n",
1593 "", ip6_sprintf(ip6buf, &pr->pr_ip6[i]));
1594#endif /* INET6 */
1595 if (db_pager_quit)
1596 break;
1597 }
1598}
1599#endif /* DDB */