30 31#include "opt_ddb.h" 32#include "opt_inet.h" 33#include "opt_inet6.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> 42#include <sys/malloc.h> 43#include <sys/priv.h> 44#include <sys/proc.h> 45#include <sys/taskqueue.h> 46#include <sys/fcntl.h> 47#include <sys/jail.h> 48#include <sys/lock.h> 49#include <sys/mutex.h> 50#include <sys/sx.h> 51#include <sys/namei.h> 52#include <sys/mount.h> 53#include <sys/queue.h> 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 */ 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, 84 "Processes in jail are limited to creating UNIX/IP/route sockets only"); 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, 93 &jail_enforce_statfs, 0, 94 "Processes in jail cannot see all mounted file systems"); 95 96int jail_allow_raw_sockets = 0; 97SYSCTL_INT(_security_jail, OID_AUTO, allow_raw_sockets, CTLFLAG_RW, 98 &jail_allow_raw_sockets, 0, 99 "Prison root can create raw sockets"); 100 101int jail_chflags_allowed = 0; 102SYSCTL_INT(_security_jail, OID_AUTO, chflags_allowed, CTLFLAG_RW, 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 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 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 } else 297 j->ip4 = NULL; 298#endif 299#ifdef INET6 300 if (j->ip6s > 0) { 301 ip6 = (struct in6_addr *)malloc(j->ip6s * sizeof(struct in6_addr), 302 M_PRISON, M_WAITOK | M_ZERO); 303 error = copyin(j->ip6, ip6, j->ip6s * sizeof(struct in6_addr)); 304 if (error) 305 goto e_free_ip; 306 /* Sort all but the first IPv6 address. */ 307 if (j->ip6s > 1) 308 qsort((ip6 + 1), j->ip6s - 1, 309 sizeof(struct in6_addr), qcmp_v6); 310 for (i=0; i<j->ip6s; i++) { 311 if (IN6_IS_ADDR_UNSPECIFIED(&ip6[i])) { 312 error = EINVAL; 313 goto e_free_ip; 314 } 315 if ((i+1) < j->ip6s && 316 (IN6_ARE_ADDR_EQUAL(&ip6[0], &ip6[i+1]) || 317 IN6_ARE_ADDR_EQUAL(&ip6[i], &ip6[i+1]))) { 318 error = EINVAL; 319 goto e_free_ip; 320 } 321 } 322 323 j->ip6 = ip6; 324 } else 325 j->ip6 = NULL; 326#endif 327 return (0); 328 329e_free_ip: 330#ifdef INET6 331 free(ip6, M_PRISON); 332#endif 333#ifdef INET 334 free(ip4, M_PRISON); 335#endif 336 return (error); 337} 338#endif /* INET || INET6 */ 339 340static int 341jail_handle_ips(struct jail *j) 342{ 343#if defined(INET) || defined(INET6) 344 int error; 345#endif 346 347 /* 348 * Finish conversion for older versions, copyin and setup IPs. 349 */ 350 switch (j->version) { 351 case 0: 352 { 353#ifdef INET 354 /* FreeBSD single IPv4 jails. */ 355 struct in_addr *ip4; 356 357 if (j->ip4s == INADDR_ANY || j->ip4s == INADDR_BROADCAST) 358 return (EINVAL); 359 ip4 = (struct in_addr *)malloc(sizeof(struct in_addr), 360 M_PRISON, M_WAITOK | M_ZERO); 361 362 /* 363 * Jail version 0 still used HBO for the IPv4 address. 364 */ 365 ip4->s_addr = htonl(j->ip4s); 366 j->ip4s = 1; 367 j->ip4 = ip4; 368 break; 369#else 370 return (EINVAL); 371#endif 372 } 373 374 case 1: 375 /* 376 * Version 1 was used by multi-IPv4 jail implementations 377 * that never made it into the official kernel. 378 * We should never hit this here; jail() should catch it. 379 */ 380 return (EINVAL); 381 382 case 2: /* JAIL_API_VERSION */ 383 /* FreeBSD multi-IPv4/IPv6,noIP jails. */ 384#if defined(INET) || defined(INET6) 385#ifdef INET 386 if (j->ip4s > jail_max_af_ips) 387 return (EINVAL); 388#else 389 if (j->ip4s != 0) 390 return (EINVAL); 391#endif 392#ifdef INET6 393 if (j->ip6s > jail_max_af_ips) 394 return (EINVAL); 395#else 396 if (j->ip6s != 0) 397 return (EINVAL); 398#endif 399 error = jail_copyin_ips(j); 400 if (error) 401 return (error); 402#endif 403 break; 404 405 default: 406 /* Sci-Fi jails are not supported, sorry. */ 407 return (EINVAL); 408 } 409 410 return (0); 411} 412 413 414/* 415 * struct jail_args { 416 * struct jail *jail; 417 * }; 418 */ 419int 420jail(struct thread *td, struct jail_args *uap) 421{ 422 uint32_t version; 423 int error; 424 struct jail j; 425 426 error = copyin(uap->jail, &version, sizeof(uint32_t)); 427 if (error) 428 return (error); 429 430 switch (version) { 431 case 0: 432 /* FreeBSD single IPv4 jails. */ 433 { 434 struct jail_v0 j0; 435 436 bzero(&j, sizeof(struct jail)); 437 error = copyin(uap->jail, &j0, sizeof(struct jail_v0)); 438 if (error) 439 return (error); 440 j.version = j0.version; 441 j.path = j0.path; 442 j.hostname = j0.hostname; 443 j.ip4s = j0.ip_number; 444 break; 445 } 446 447 case 1: 448 /* 449 * Version 1 was used by multi-IPv4 jail implementations 450 * that never made it into the official kernel. 451 */ 452 return (EINVAL); 453 454 case 2: /* JAIL_API_VERSION */ 455 /* FreeBSD multi-IPv4/IPv6,noIP jails. */ 456 error = copyin(uap->jail, &j, sizeof(struct jail)); 457 if (error) 458 return (error); 459 break; 460 461 default: 462 /* Sci-Fi jails are not supported, sorry. */ 463 return (EINVAL); 464 } 465 return (kern_jail(td, &j)); 466} 467 468int 469kern_jail(struct thread *td, struct jail *j) 470{ 471 struct nameidata nd; 472 struct prison *pr, *tpr; 473 struct jail_attach_args jaa; 474 int vfslocked, error, tryprid; 475 476 KASSERT(j != NULL, ("%s: j is NULL", __func__)); 477 478 /* Handle addresses - convert old structs, copyin, check IPs. */ 479 error = jail_handle_ips(j); 480 if (error) 481 return (error); 482 483 /* Allocate struct prison and fill it with life. */ 484 pr = malloc(sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO); 485 mtx_init(&pr->pr_mtx, "jail mutex", NULL, MTX_DEF); 486 pr->pr_ref = 1; 487 error = copyinstr(j->path, &pr->pr_path, sizeof(pr->pr_path), NULL); 488 if (error) 489 goto e_killmtx; 490 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF, UIO_SYSSPACE, 491 pr->pr_path, td); 492 error = namei(&nd); 493 if (error) 494 goto e_killmtx; 495 vfslocked = NDHASGIANT(&nd); 496 pr->pr_root = nd.ni_vp; 497 VOP_UNLOCK(nd.ni_vp, 0); 498 NDFREE(&nd, NDF_ONLY_PNBUF); 499 VFS_UNLOCK_GIANT(vfslocked); 500 error = copyinstr(j->hostname, &pr->pr_host, sizeof(pr->pr_host), NULL); 501 if (error) 502 goto e_dropvnref; 503 if (j->jailname != NULL) { 504 error = copyinstr(j->jailname, &pr->pr_name, 505 sizeof(pr->pr_name), NULL); 506 if (error) 507 goto e_dropvnref; 508 } 509 if (j->ip4s > 0) { 510 pr->pr_ip4 = j->ip4; 511 pr->pr_ip4s = j->ip4s; 512 } 513#ifdef INET6 514 if (j->ip6s > 0) { 515 pr->pr_ip6 = j->ip6; 516 pr->pr_ip6s = j->ip6s; 517 } 518#endif 519 pr->pr_linux = NULL; 520 pr->pr_securelevel = securelevel; 521 bzero(&pr->pr_osd, sizeof(pr->pr_osd)); 522 523 /* 524 * Pre-set prison state to ALIVE upon cration. This is needed so we 525 * can later attach the process to it, etc (avoiding another extra 526 * state for ther process of creation, complicating things). 527 */ 528 pr->pr_state = PRISON_STATE_ALIVE; 529 530 /* Allocate a dedicated cpuset for each jail. */ 531 error = cpuset_create_root(td, &pr->pr_cpuset); 532 if (error) 533 goto e_dropvnref; 534 535 sx_xlock(&allprison_lock); 536 /* Make sure we cannot run into problems with ambiguous bind()ings. */ 537#if defined(INET) || defined(INET6) 538 error = prison_check_conflicting_ips(pr); 539 if (error) { 540 sx_xunlock(&allprison_lock); 541 goto e_dropcpuset; 542 } 543#endif 544 545 /* Determine next pr_id and add prison to allprison list. */ 546 tryprid = lastprid + 1; 547 if (tryprid == JAIL_MAX) 548 tryprid = 1; 549next: 550 LIST_FOREACH(tpr, &allprison, pr_list) { 551 if (tpr->pr_id == tryprid) { 552 tryprid++; 553 if (tryprid == JAIL_MAX) { 554 sx_xunlock(&allprison_lock); 555 error = EAGAIN; 556 goto e_dropcpuset; 557 } 558 goto next; 559 } 560 } 561 pr->pr_id = jaa.jid = lastprid = tryprid; 562 LIST_INSERT_HEAD(&allprison, pr, pr_list); 563 prisoncount++; 564 sx_xunlock(&allprison_lock); 565 566 error = jail_attach(td, &jaa); 567 if (error) 568 goto e_dropprref; 569 mtx_lock(&pr->pr_mtx); 570 pr->pr_ref--; 571 mtx_unlock(&pr->pr_mtx); 572 td->td_retval[0] = jaa.jid; 573 return (0); 574e_dropprref: 575 sx_xlock(&allprison_lock); 576 LIST_REMOVE(pr, pr_list); 577 prisoncount--; 578 sx_xunlock(&allprison_lock); 579e_dropcpuset: 580 cpuset_rel(pr->pr_cpuset); 581e_dropvnref: 582 vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount); 583 vrele(pr->pr_root); 584 VFS_UNLOCK_GIANT(vfslocked); 585e_killmtx: 586 mtx_destroy(&pr->pr_mtx); 587 free(pr, M_PRISON); 588#ifdef INET6 589 free(j->ip6, M_PRISON); 590#endif 591#ifdef INET 592 free(j->ip4, M_PRISON); 593#endif 594 return (error); 595} 596 597/* 598 * struct jail_attach_args { 599 * int jid; 600 * }; 601 */ 602int 603jail_attach(struct thread *td, struct jail_attach_args *uap) 604{ 605 struct proc *p; 606 struct ucred *newcred, *oldcred; 607 struct prison *pr; 608 int vfslocked, error; 609 610 /* 611 * XXX: Note that there is a slight race here if two threads 612 * in the same privileged process attempt to attach to two 613 * different jails at the same time. It is important for 614 * user processes not to do this, or they might end up with 615 * a process root from one prison, but attached to the jail 616 * of another. 617 */ 618 error = priv_check(td, PRIV_JAIL_ATTACH); 619 if (error) 620 return (error); 621 622 p = td->td_proc; 623 sx_slock(&allprison_lock); 624 pr = prison_find(uap->jid); 625 if (pr == NULL) { 626 sx_sunlock(&allprison_lock); 627 return (EINVAL); 628 } 629 630 /* 631 * Do not allow a process to attach to a prison that is not 632 * considered to be "ALIVE". 633 */ 634 if (pr->pr_state != PRISON_STATE_ALIVE) { 635 mtx_unlock(&pr->pr_mtx); 636 sx_sunlock(&allprison_lock); 637 return (EINVAL); 638 } 639 pr->pr_ref++; 640 mtx_unlock(&pr->pr_mtx); 641 sx_sunlock(&allprison_lock); 642 643 /* 644 * Reparent the newly attached process to this jail. 645 */ 646 error = cpuset_setproc_update_set(p, pr->pr_cpuset); 647 if (error) 648 goto e_unref; 649 650 vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount); 651 vn_lock(pr->pr_root, LK_EXCLUSIVE | LK_RETRY); 652 if ((error = change_dir(pr->pr_root, td)) != 0) 653 goto e_unlock; 654#ifdef MAC 655 if ((error = mac_vnode_check_chroot(td->td_ucred, pr->pr_root))) 656 goto e_unlock; 657#endif 658 VOP_UNLOCK(pr->pr_root, 0); 659 change_root(pr->pr_root, td); 660 VFS_UNLOCK_GIANT(vfslocked); 661 662 newcred = crget(); 663 PROC_LOCK(p); 664 oldcred = p->p_ucred; 665 setsugid(p); 666 crcopy(newcred, oldcred); 667 newcred->cr_prison = pr; 668 p->p_ucred = newcred; 669 prison_proc_hold(pr); 670 PROC_UNLOCK(p); 671 crfree(oldcred); 672 return (0); 673e_unlock: 674 VOP_UNLOCK(pr->pr_root, 0); 675 VFS_UNLOCK_GIANT(vfslocked); 676e_unref: 677 mtx_lock(&pr->pr_mtx); 678 pr->pr_ref--; 679 mtx_unlock(&pr->pr_mtx); 680 return (error); 681} 682 683/* 684 * Returns a locked prison instance, or NULL on failure. 685 */ 686struct prison * 687prison_find(int prid) 688{ 689 struct prison *pr; 690 691 sx_assert(&allprison_lock, SX_LOCKED); 692 LIST_FOREACH(pr, &allprison, pr_list) { 693 if (pr->pr_id == prid) { 694 mtx_lock(&pr->pr_mtx); 695 if (pr->pr_ref == 0) { 696 mtx_unlock(&pr->pr_mtx); 697 break; 698 } 699 return (pr); 700 } 701 } 702 return (NULL); 703} 704 705void 706prison_free_locked(struct prison *pr) 707{ 708 709 mtx_assert(&pr->pr_mtx, MA_OWNED); 710 pr->pr_ref--; 711 if (pr->pr_ref == 0) { 712 mtx_unlock(&pr->pr_mtx); 713 TASK_INIT(&pr->pr_task, 0, prison_complete, pr); 714 taskqueue_enqueue(taskqueue_thread, &pr->pr_task); 715 return; 716 } 717 mtx_unlock(&pr->pr_mtx); 718} 719 720void 721prison_free(struct prison *pr) 722{ 723 724 mtx_lock(&pr->pr_mtx); 725 prison_free_locked(pr); 726} 727 728static void 729prison_complete(void *context, int pending) 730{ 731 struct prison *pr; 732 int vfslocked; 733 734 pr = (struct prison *)context; 735 736 sx_xlock(&allprison_lock); 737 LIST_REMOVE(pr, pr_list); 738 prisoncount--; 739 sx_xunlock(&allprison_lock); 740 741 cpuset_rel(pr->pr_cpuset); 742 743 /* Free all OSD associated to this jail. */ 744 osd_jail_exit(pr); 745 746 vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount); 747 vrele(pr->pr_root); 748 VFS_UNLOCK_GIANT(vfslocked); 749 750 mtx_destroy(&pr->pr_mtx); 751 free(pr->pr_linux, M_PRISON); 752#ifdef INET6 753 free(pr->pr_ip6, M_PRISON); 754#endif 755#ifdef INET 756 free(pr->pr_ip4, M_PRISON); 757#endif 758 free(pr, M_PRISON); 759} 760 761void 762prison_hold_locked(struct prison *pr) 763{ 764 765 mtx_assert(&pr->pr_mtx, MA_OWNED); 766 KASSERT(pr->pr_ref > 0, 767 ("Trying to hold dead prison (id=%d).", pr->pr_id)); 768 pr->pr_ref++; 769} 770 771void 772prison_hold(struct prison *pr) 773{ 774 775 mtx_lock(&pr->pr_mtx); 776 prison_hold_locked(pr); 777 mtx_unlock(&pr->pr_mtx); 778} 779 780void 781prison_proc_hold(struct prison *pr) 782{ 783 784 mtx_lock(&pr->pr_mtx); 785 KASSERT(pr->pr_state == PRISON_STATE_ALIVE, 786 ("Cannot add a process to a non-alive prison (id=%d).", pr->pr_id)); 787 pr->pr_nprocs++; 788 mtx_unlock(&pr->pr_mtx); 789} 790 791void 792prison_proc_free(struct prison *pr) 793{ 794 795 mtx_lock(&pr->pr_mtx); 796 KASSERT(pr->pr_state == PRISON_STATE_ALIVE && pr->pr_nprocs > 0, 797 ("Trying to kill a process in a dead prison (id=%d).", pr->pr_id)); 798 pr->pr_nprocs--; 799 if (pr->pr_nprocs == 0) 800 pr->pr_state = PRISON_STATE_DYING; 801 mtx_unlock(&pr->pr_mtx); 802} 803 804 805#ifdef INET 806/* 807 * Pass back primary IPv4 address of this jail. 808 * 809 * If not jailed return success but do not alter the address. Caller has to 810 * make sure to intialize it correctly (INADDR_ANY). 811 * 812 * Returns 0 on success, 1 on error. Address returned in NBO. 813 */ 814int 815prison_get_ip4(struct ucred *cred, struct in_addr *ia) 816{ 817 818 KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 819 KASSERT(ia != NULL, ("%s: ia is NULL", __func__)); 820 821 if (!jailed(cred)) 822 /* Do not change address passed in. */ 823 return (0); 824 825 if (cred->cr_prison->pr_ip4 == NULL) 826 return (1); 827 828 ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr; 829 return (0); 830} 831 832/* 833 * Make sure our (source) address is set to something meaningful to this 834 * jail. 835 * 836 * Returns 0 on success, 1 on error. Address passed in in NBO and returned 837 * in NBO. 838 */ 839int 840prison_local_ip4(struct ucred *cred, struct in_addr *ia) 841{ 842 struct in_addr ia0; 843 844 KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 845 KASSERT(ia != NULL, ("%s: ia is NULL", __func__)); 846 847 if (!jailed(cred)) 848 return (0); 849 if (cred->cr_prison->pr_ip4 == NULL) 850 return (1); 851 852 ia0.s_addr = ntohl(ia->s_addr); 853 if (ia0.s_addr == INADDR_LOOPBACK) { 854 ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr; 855 return (0); 856 } 857 858 /* 859 * In case there is only 1 IPv4 address, bind directly. 860 */ 861 if (ia0.s_addr == INADDR_ANY && cred->cr_prison->pr_ip4s == 1) { 862 ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr; 863 return (0); 864 } 865 866 if (ia0.s_addr == INADDR_ANY || prison_check_ip4(cred, ia)) 867 return (0); 868 869 return (1); 870} 871 872/* 873 * Rewrite destination address in case we will connect to loopback address. 874 * 875 * Returns 0 on success, 1 on error. Address passed in in NBO and returned 876 * in NBO. 877 */ 878int 879prison_remote_ip4(struct ucred *cred, struct in_addr *ia) 880{ 881 882 KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 883 KASSERT(ia != NULL, ("%s: ia is NULL", __func__)); 884 885 if (!jailed(cred)) 886 return (0); 887 if (cred->cr_prison->pr_ip4 == NULL) 888 return (1); 889 if (ntohl(ia->s_addr) == INADDR_LOOPBACK) { 890 ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr; 891 return (0); 892 } 893 894 /* 895 * Return success because nothing had to be changed. 896 */ 897 return (0); 898} 899 900/* 901 * Check if given address belongs to the jail referenced by cred. 902 * 903 * Returns 1 if address belongs to jail, 0 if not. Address passed in in NBO. 904 */ 905static int 906_prison_check_ip4(struct prison *pr, struct in_addr *ia) 907{ 908 int i, a, z, d; 909 910 if (pr->pr_ip4 == NULL) 911 return (0); 912 913 /* 914 * Check the primary IP. 915 */ 916 if (pr->pr_ip4[0].s_addr == ia->s_addr) 917 return (1); 918 919 /* 920 * All the other IPs are sorted so we can do a binary search. 921 */ 922 a = 0; 923 z = pr->pr_ip4s - 2; 924 while (a <= z) { 925 i = (a + z) / 2; 926 d = qcmp_v4(&pr->pr_ip4[i+1], ia); 927 if (d > 0) 928 z = i - 1; 929 else if (d < 0) 930 a = i + 1; 931 else 932 return (1); 933 } 934 return (0); 935} 936 937int 938prison_check_ip4(struct ucred *cred, struct in_addr *ia) 939{ 940 941 KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 942 KASSERT(ia != NULL, ("%s: ia is NULL", __func__)); 943 944 if (!jailed(cred)) 945 return (1); 946 947 return (_prison_check_ip4(cred->cr_prison, ia)); 948} 949#endif 950 951#ifdef INET6 952/* 953 * Pass back primary IPv6 address for this jail. 954 * 955 * If not jailed return success but do not alter the address. Caller has to 956 * make sure to intialize it correctly (IN6ADDR_ANY_INIT). 957 * 958 * Returns 0 on success, 1 on error. 959 */ 960int 961prison_get_ip6(struct ucred *cred, struct in6_addr *ia6) 962{ 963 964 KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 965 KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__)); 966 967 if (!jailed(cred)) 968 return (0); 969 if (cred->cr_prison->pr_ip6 == NULL) 970 return (1); 971 bcopy(&cred->cr_prison->pr_ip6[0], ia6, sizeof(struct in6_addr)); 972 return (0); 973} 974 975/* 976 * Make sure our (source) address is set to something meaningful to this jail. 977 * 978 * v6only should be set based on (inp->inp_flags & IN6P_IPV6_V6ONLY != 0) 979 * when needed while binding. 980 * 981 * Returns 0 on success, 1 on error. 982 */ 983int 984prison_local_ip6(struct ucred *cred, struct in6_addr *ia6, int v6only) 985{ 986 987 KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 988 KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__)); 989 990 if (!jailed(cred)) 991 return (0); 992 if (cred->cr_prison->pr_ip6 == NULL) 993 return (1); 994 if (IN6_IS_ADDR_LOOPBACK(ia6)) { 995 bcopy(&cred->cr_prison->pr_ip6[0], ia6, 996 sizeof(struct in6_addr)); 997 return (0); 998 } 999 1000 /* 1001 * In case there is only 1 IPv6 address, and v6only is true, then 1002 * bind directly. 1003 */ 1004 if (v6only != 0 && IN6_IS_ADDR_UNSPECIFIED(ia6) && 1005 cred->cr_prison->pr_ip6s == 1) { 1006 bcopy(&cred->cr_prison->pr_ip6[0], ia6, 1007 sizeof(struct in6_addr)); 1008 return (0); 1009 } 1010 if (IN6_IS_ADDR_UNSPECIFIED(ia6) || prison_check_ip6(cred, ia6)) 1011 return (0); 1012 return (1); 1013} 1014 1015/* 1016 * Rewrite destination address in case we will connect to loopback address. 1017 * 1018 * Returns 0 on success, 1 on error. 1019 */ 1020int 1021prison_remote_ip6(struct ucred *cred, struct in6_addr *ia6) 1022{ 1023 1024 KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 1025 KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__)); 1026 1027 if (!jailed(cred)) 1028 return (0); 1029 if (cred->cr_prison->pr_ip6 == NULL) 1030 return (1); 1031 if (IN6_IS_ADDR_LOOPBACK(ia6)) { 1032 bcopy(&cred->cr_prison->pr_ip6[0], ia6, 1033 sizeof(struct in6_addr)); 1034 return (0); 1035 } 1036 1037 /* 1038 * Return success because nothing had to be changed. 1039 */ 1040 return (0); 1041} 1042 1043/* 1044 * Check if given address belongs to the jail referenced by cred. 1045 * 1046 * Returns 1 if address belongs to jail, 0 if not. 1047 */ 1048static int 1049_prison_check_ip6(struct prison *pr, struct in6_addr *ia6) 1050{ 1051 int i, a, z, d; 1052 1053 if (pr->pr_ip6 == NULL) 1054 return (0); 1055 1056 /* 1057 * Check the primary IP. 1058 */ 1059 if (IN6_ARE_ADDR_EQUAL(&pr->pr_ip6[0], ia6)) 1060 return (1); 1061 1062 /* 1063 * All the other IPs are sorted so we can do a binary search. 1064 */ 1065 a = 0; 1066 z = pr->pr_ip6s - 2; 1067 while (a <= z) { 1068 i = (a + z) / 2; 1069 d = qcmp_v6(&pr->pr_ip6[i+1], ia6); 1070 if (d > 0) 1071 z = i - 1; 1072 else if (d < 0) 1073 a = i + 1; 1074 else 1075 return (1); 1076 } 1077 return (0); 1078} 1079 1080int 1081prison_check_ip6(struct ucred *cred, struct in6_addr *ia6) 1082{ 1083 1084 KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 1085 KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__)); 1086 1087 if (!jailed(cred)) 1088 return (1); 1089 1090 return (_prison_check_ip6(cred->cr_prison, ia6)); 1091} 1092#endif 1093 1094/* 1095 * Check if given address belongs to the jail referenced by cred (wrapper to 1096 * prison_check_ip[46]). 1097 * 1098 * Returns 1 if address belongs to jail, 0 if not. IPv4 Address passed in in 1099 * NBO. 1100 */ 1101int 1102prison_if(struct ucred *cred, struct sockaddr *sa) 1103{ 1104#ifdef INET 1105 struct sockaddr_in *sai; 1106#endif 1107#ifdef INET6 1108 struct sockaddr_in6 *sai6; 1109#endif 1110 int ok; 1111 1112 KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 1113 KASSERT(sa != NULL, ("%s: sa is NULL", __func__)); 1114 1115 ok = 0; 1116 switch(sa->sa_family) 1117 { 1118#ifdef INET 1119 case AF_INET: 1120 sai = (struct sockaddr_in *)sa; 1121 if (prison_check_ip4(cred, &sai->sin_addr)) 1122 ok = 1; 1123 break; 1124 1125#endif 1126#ifdef INET6 1127 case AF_INET6: 1128 sai6 = (struct sockaddr_in6 *)sa; 1129 if (prison_check_ip6(cred, (struct in6_addr *)&sai6->sin6_addr)) 1130 ok = 1; 1131 break; 1132 1133#endif 1134 default: 1135 if (!jail_socket_unixiproute_only) 1136 ok = 1; 1137 } 1138 return (ok); 1139} 1140 1141/* 1142 * Return 0 if jails permit p1 to frob p2, otherwise ESRCH. 1143 */ 1144int 1145prison_check(struct ucred *cred1, struct ucred *cred2) 1146{ 1147 1148 if (jailed(cred1)) { 1149 if (!jailed(cred2)) 1150 return (ESRCH); 1151 if (cred2->cr_prison != cred1->cr_prison) 1152 return (ESRCH); 1153 } 1154 1155 return (0); 1156} 1157 1158/* 1159 * Return 1 if the passed credential is in a jail, otherwise 0. 1160 */ 1161int 1162jailed(struct ucred *cred) 1163{ 1164 1165 return (cred->cr_prison != NULL); 1166} 1167 1168/* 1169 * Return the correct hostname for the passed credential. 1170 */ 1171void 1172getcredhostname(struct ucred *cred, char *buf, size_t size) 1173{ 1174 INIT_VPROCG(cred->cr_vimage->v_procg); 1175 1176 if (jailed(cred)) { 1177 mtx_lock(&cred->cr_prison->pr_mtx); 1178 strlcpy(buf, cred->cr_prison->pr_host, size); 1179 mtx_unlock(&cred->cr_prison->pr_mtx); 1180 } else { 1181 mtx_lock(&hostname_mtx); 1182 strlcpy(buf, V_hostname, size); 1183 mtx_unlock(&hostname_mtx); 1184 } 1185} 1186 1187/* 1188 * Determine whether the subject represented by cred can "see" 1189 * status of a mount point. 1190 * Returns: 0 for permitted, ENOENT otherwise. 1191 * XXX: This function should be called cr_canseemount() and should be 1192 * placed in kern_prot.c. 1193 */ 1194int 1195prison_canseemount(struct ucred *cred, struct mount *mp) 1196{ 1197 struct prison *pr; 1198 struct statfs *sp; 1199 size_t len; 1200 1201 if (!jailed(cred) || jail_enforce_statfs == 0) 1202 return (0); 1203 pr = cred->cr_prison; 1204 if (pr->pr_root->v_mount == mp) 1205 return (0); 1206 if (jail_enforce_statfs == 2) 1207 return (ENOENT); 1208 /* 1209 * If jail's chroot directory is set to "/" we should be able to see 1210 * all mount-points from inside a jail. 1211 * This is ugly check, but this is the only situation when jail's 1212 * directory ends with '/'. 1213 */ 1214 if (strcmp(pr->pr_path, "/") == 0) 1215 return (0); 1216 len = strlen(pr->pr_path); 1217 sp = &mp->mnt_stat; 1218 if (strncmp(pr->pr_path, sp->f_mntonname, len) != 0) 1219 return (ENOENT); 1220 /* 1221 * Be sure that we don't have situation where jail's root directory 1222 * is "/some/path" and mount point is "/some/pathpath". 1223 */ 1224 if (sp->f_mntonname[len] != '\0' && sp->f_mntonname[len] != '/') 1225 return (ENOENT); 1226 return (0); 1227} 1228 1229void 1230prison_enforce_statfs(struct ucred *cred, struct mount *mp, struct statfs *sp) 1231{ 1232 char jpath[MAXPATHLEN]; 1233 struct prison *pr; 1234 size_t len; 1235 1236 if (!jailed(cred) || jail_enforce_statfs == 0) 1237 return; 1238 pr = cred->cr_prison; 1239 if (prison_canseemount(cred, mp) != 0) { 1240 bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 1241 strlcpy(sp->f_mntonname, "[restricted]", 1242 sizeof(sp->f_mntonname)); 1243 return; 1244 } 1245 if (pr->pr_root->v_mount == mp) { 1246 /* 1247 * Clear current buffer data, so we are sure nothing from 1248 * the valid path left there. 1249 */ 1250 bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 1251 *sp->f_mntonname = '/'; 1252 return; 1253 } 1254 /* 1255 * If jail's chroot directory is set to "/" we should be able to see 1256 * all mount-points from inside a jail. 1257 */ 1258 if (strcmp(pr->pr_path, "/") == 0) 1259 return; 1260 len = strlen(pr->pr_path); 1261 strlcpy(jpath, sp->f_mntonname + len, sizeof(jpath)); 1262 /* 1263 * Clear current buffer data, so we are sure nothing from 1264 * the valid path left there. 1265 */ 1266 bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 1267 if (*jpath == '\0') { 1268 /* Should never happen. */ 1269 *sp->f_mntonname = '/'; 1270 } else { 1271 strlcpy(sp->f_mntonname, jpath, sizeof(sp->f_mntonname)); 1272 } 1273} 1274 1275/* 1276 * Check with permission for a specific privilege is granted within jail. We 1277 * have a specific list of accepted privileges; the rest are denied. 1278 */ 1279int 1280prison_priv_check(struct ucred *cred, int priv) 1281{ 1282 1283 if (!jailed(cred)) 1284 return (0); 1285 1286 switch (priv) { 1287 1288 /* 1289 * Allow ktrace privileges for root in jail. 1290 */ 1291 case PRIV_KTRACE: 1292 1293#if 0 1294 /* 1295 * Allow jailed processes to configure audit identity and 1296 * submit audit records (login, etc). In the future we may 1297 * want to further refine the relationship between audit and 1298 * jail. 1299 */ 1300 case PRIV_AUDIT_GETAUDIT: 1301 case PRIV_AUDIT_SETAUDIT: 1302 case PRIV_AUDIT_SUBMIT: 1303#endif 1304 1305 /* 1306 * Allow jailed processes to manipulate process UNIX 1307 * credentials in any way they see fit. 1308 */ 1309 case PRIV_CRED_SETUID: 1310 case PRIV_CRED_SETEUID: 1311 case PRIV_CRED_SETGID: 1312 case PRIV_CRED_SETEGID: 1313 case PRIV_CRED_SETGROUPS: 1314 case PRIV_CRED_SETREUID: 1315 case PRIV_CRED_SETREGID: 1316 case PRIV_CRED_SETRESUID: 1317 case PRIV_CRED_SETRESGID: 1318 1319 /* 1320 * Jail implements visibility constraints already, so allow 1321 * jailed root to override uid/gid-based constraints. 1322 */ 1323 case PRIV_SEEOTHERGIDS: 1324 case PRIV_SEEOTHERUIDS: 1325 1326 /* 1327 * Jail implements inter-process debugging limits already, so 1328 * allow jailed root various debugging privileges. 1329 */ 1330 case PRIV_DEBUG_DIFFCRED: 1331 case PRIV_DEBUG_SUGID: 1332 case PRIV_DEBUG_UNPRIV: 1333 1334 /* 1335 * Allow jail to set various resource limits and login 1336 * properties, and for now, exceed process resource limits. 1337 */ 1338 case PRIV_PROC_LIMIT: 1339 case PRIV_PROC_SETLOGIN: 1340 case PRIV_PROC_SETRLIMIT: 1341 1342 /* 1343 * System V and POSIX IPC privileges are granted in jail. 1344 */ 1345 case PRIV_IPC_READ: 1346 case PRIV_IPC_WRITE: 1347 case PRIV_IPC_ADMIN: 1348 case PRIV_IPC_MSGSIZE: 1349 case PRIV_MQ_ADMIN: 1350 1351 /* 1352 * Jail implements its own inter-process limits, so allow 1353 * root processes in jail to change scheduling on other 1354 * processes in the same jail. Likewise for signalling. 1355 */ 1356 case PRIV_SCHED_DIFFCRED: 1357 case PRIV_SCHED_CPUSET: 1358 case PRIV_SIGNAL_DIFFCRED: 1359 case PRIV_SIGNAL_SUGID: 1360 1361 /* 1362 * Allow jailed processes to write to sysctls marked as jail 1363 * writable. 1364 */ 1365 case PRIV_SYSCTL_WRITEJAIL: 1366 1367 /* 1368 * Allow root in jail to manage a variety of quota 1369 * properties. These should likely be conditional on a 1370 * configuration option. 1371 */ 1372 case PRIV_VFS_GETQUOTA: 1373 case PRIV_VFS_SETQUOTA: 1374 1375 /* 1376 * Since Jail relies on chroot() to implement file system 1377 * protections, grant many VFS privileges to root in jail. 1378 * Be careful to exclude mount-related and NFS-related 1379 * privileges. 1380 */ 1381 case PRIV_VFS_READ: 1382 case PRIV_VFS_WRITE: 1383 case PRIV_VFS_ADMIN: 1384 case PRIV_VFS_EXEC: 1385 case PRIV_VFS_LOOKUP: 1386 case PRIV_VFS_BLOCKRESERVE: /* XXXRW: Slightly surprising. */ 1387 case PRIV_VFS_CHFLAGS_DEV: 1388 case PRIV_VFS_CHOWN: 1389 case PRIV_VFS_CHROOT: 1390 case PRIV_VFS_RETAINSUGID: 1391 case PRIV_VFS_FCHROOT: 1392 case PRIV_VFS_LINK: 1393 case PRIV_VFS_SETGID: 1394 case PRIV_VFS_STAT: 1395 case PRIV_VFS_STICKYFILE: 1396 return (0); 1397 1398 /* 1399 * Depending on the global setting, allow privilege of 1400 * setting system flags. 1401 */ 1402 case PRIV_VFS_SYSFLAGS: 1403 if (jail_chflags_allowed) 1404 return (0); 1405 else 1406 return (EPERM); 1407 1408 /* 1409 * Depending on the global setting, allow privilege of 1410 * mounting/unmounting file systems. 1411 */ 1412 case PRIV_VFS_MOUNT: 1413 case PRIV_VFS_UNMOUNT: 1414 case PRIV_VFS_MOUNT_NONUSER: 1415 case PRIV_VFS_MOUNT_OWNER: 1416 if (jail_mount_allowed) 1417 return (0); 1418 else 1419 return (EPERM); 1420 1421 /* 1422 * Allow jailed root to bind reserved ports and reuse in-use 1423 * ports. 1424 */ 1425 case PRIV_NETINET_RESERVEDPORT: 1426 case PRIV_NETINET_REUSEPORT: 1427 return (0); 1428 1429 /* 1430 * Allow jailed root to set certian IPv4/6 (option) headers. 1431 */ 1432 case PRIV_NETINET_SETHDROPTS: 1433 return (0); 1434 1435 /* 1436 * Conditionally allow creating raw sockets in jail. 1437 */ 1438 case PRIV_NETINET_RAW: 1439 if (jail_allow_raw_sockets) 1440 return (0); 1441 else 1442 return (EPERM); 1443 1444 /* 1445 * Since jail implements its own visibility limits on netstat 1446 * sysctls, allow getcred. This allows identd to work in 1447 * jail. 1448 */ 1449 case PRIV_NETINET_GETCRED: 1450 return (0); 1451 1452 default: 1453 /* 1454 * In all remaining cases, deny the privilege request. This 1455 * includes almost all network privileges, many system 1456 * configuration privileges. 1457 */ 1458 return (EPERM); 1459 } 1460} 1461 1462static int 1463sysctl_jail_list(SYSCTL_HANDLER_ARGS) 1464{ 1465 struct xprison *xp, *sxp; 1466 struct prison *pr; 1467 char *p; 1468 size_t len; 1469 int count, error; 1470 1471 if (jailed(req->td->td_ucred)) 1472 return (0); 1473 1474 sx_slock(&allprison_lock); 1475 if ((count = prisoncount) == 0) { 1476 sx_sunlock(&allprison_lock); 1477 return (0); 1478 } 1479 1480 len = sizeof(*xp) * count; 1481 LIST_FOREACH(pr, &allprison, pr_list) { 1482#ifdef INET 1483 len += pr->pr_ip4s * sizeof(struct in_addr); 1484#endif 1485#ifdef INET6 1486 len += pr->pr_ip6s * sizeof(struct in6_addr); 1487#endif 1488 } 1489 1490 sxp = xp = malloc(len, M_TEMP, M_WAITOK | M_ZERO); 1491 1492 LIST_FOREACH(pr, &allprison, pr_list) { 1493 xp->pr_version = XPRISON_VERSION; 1494 xp->pr_id = pr->pr_id; 1495 xp->pr_state = pr->pr_state; 1496 xp->pr_cpusetid = pr->pr_cpuset->cs_id; 1497 strlcpy(xp->pr_path, pr->pr_path, sizeof(xp->pr_path)); 1498 mtx_lock(&pr->pr_mtx); 1499 strlcpy(xp->pr_host, pr->pr_host, sizeof(xp->pr_host)); 1500 strlcpy(xp->pr_name, pr->pr_name, sizeof(xp->pr_name)); 1501 mtx_unlock(&pr->pr_mtx); 1502#ifdef INET 1503 xp->pr_ip4s = pr->pr_ip4s; 1504#endif 1505#ifdef INET6 1506 xp->pr_ip6s = pr->pr_ip6s; 1507#endif 1508 p = (char *)(xp + 1); 1509#ifdef INET 1510 if (pr->pr_ip4s > 0) { 1511 bcopy(pr->pr_ip4, (struct in_addr *)p, 1512 pr->pr_ip4s * sizeof(struct in_addr)); 1513 p += (pr->pr_ip4s * sizeof(struct in_addr)); 1514 } 1515#endif 1516#ifdef INET6 1517 if (pr->pr_ip6s > 0) { 1518 bcopy(pr->pr_ip6, (struct in6_addr *)p, 1519 pr->pr_ip6s * sizeof(struct in6_addr)); 1520 p += (pr->pr_ip6s * sizeof(struct in6_addr)); 1521 } 1522#endif 1523 xp = (struct xprison *)p; 1524 } 1525 sx_sunlock(&allprison_lock); 1526 1527 error = SYSCTL_OUT(req, sxp, len); 1528 free(sxp, M_TEMP); 1529 return (error); 1530} 1531
|