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 */ |
|