1 /* 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you 5 * can do whatever you want with this stuff. If we meet some day, and you think 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7 * ---------------------------------------------------------------------------- 8 * 9 */ 10 /*- 11 * Copyright (c) 2006 Victor Balada Diaz <victor@bsdes.net> 12 * All rights reserved. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 37 /* 38 * $FreeBSD: src/sys/kern/kern_jail.c,v 1.6.2.3 2001/08/17 01:00:26 rwatson Exp $ 39 * $DragonFly: src/sys/kern/kern_jail.c,v 1.19 2008/05/17 18:20:33 dillon Exp $ 40 */ 41 42 #include "opt_inet6.h" 43 44 #include <sys/param.h> 45 #include <sys/types.h> 46 #include <sys/kernel.h> 47 #include <sys/systm.h> 48 #include <sys/errno.h> 49 #include <sys/sysproto.h> 50 #include <sys/malloc.h> 51 #include <sys/nlookup.h> 52 #include <sys/namecache.h> 53 #include <sys/proc.h> 54 #include <sys/priv.h> 55 #include <sys/jail.h> 56 #include <sys/socket.h> 57 #include <sys/sysctl.h> 58 #include <sys/kern_syscall.h> 59 #include <net/if.h> 60 #include <netinet/in.h> 61 #include <netinet6/in6_var.h> 62 63 static struct prison *prison_find(int); 64 static void prison_ipcache_init(struct prison *); 65 66 MALLOC_DEFINE(M_PRISON, "prison", "Prison structures"); 67 68 SYSCTL_NODE(, OID_AUTO, jail, CTLFLAG_RW, 0, 69 "Jail rules"); 70 71 int jail_set_hostname_allowed = 1; 72 SYSCTL_INT(_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW, 73 &jail_set_hostname_allowed, 0, 74 "Processes in jail can set their hostnames"); 75 76 int jail_socket_unixiproute_only = 1; 77 SYSCTL_INT(_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW, 78 &jail_socket_unixiproute_only, 0, 79 "Processes in jail are limited to creating UNIX/IPv[46]/route sockets only"); 80 81 int jail_sysvipc_allowed = 0; 82 SYSCTL_INT(_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW, 83 &jail_sysvipc_allowed, 0, 84 "Processes in jail can use System V IPC primitives"); 85 86 int jail_chflags_allowed = 0; 87 SYSCTL_INT(_jail, OID_AUTO, chflags_allowed, CTLFLAG_RW, 88 &jail_chflags_allowed, 0, 89 "Process in jail can set chflags(1)"); 90 91 int jail_allow_raw_sockets = 0; 92 SYSCTL_INT(_jail, OID_AUTO, allow_raw_sockets, CTLFLAG_RW, 93 &jail_allow_raw_sockets, 0, 94 "Process in jail can create raw sockets"); 95 96 int lastprid = 0; 97 int prisoncount = 0; 98 99 LIST_HEAD(prisonlist, prison); 100 struct prisonlist allprison = LIST_HEAD_INITIALIZER(&allprison); 101 102 static int 103 kern_jail_attach(int jid) 104 { 105 struct proc *p = curthread->td_proc; 106 struct prison *pr; 107 int error; 108 109 pr = prison_find(jid); 110 if (pr == NULL) 111 return(EINVAL); 112 113 error = kern_chroot(&pr->pr_root); 114 if (error) 115 return(error); 116 117 prison_hold(pr); 118 cratom(&p->p_ucred); 119 p->p_ucred->cr_prison = pr; 120 p->p_flag |= P_JAILED; 121 122 return(0); 123 } 124 125 static int 126 assign_prison_id(struct prison *pr) 127 { 128 int tryprid; 129 struct prison *tpr; 130 131 tryprid = lastprid + 1; 132 if (tryprid == JAIL_MAX) 133 tryprid = 1; 134 next: 135 LIST_FOREACH(tpr, &allprison, pr_list) { 136 if (tpr->pr_id != tryprid) 137 continue; 138 tryprid++; 139 if (tryprid == JAIL_MAX) { 140 return (ERANGE); 141 } 142 goto next; 143 } 144 pr->pr_id = lastprid = tryprid; 145 146 return (0); 147 } 148 149 static int 150 kern_jail(struct prison *pr, struct jail *j) 151 { 152 int error; 153 struct nlookupdata nd; 154 155 error = nlookup_init(&nd, j->path, UIO_USERSPACE, NLC_FOLLOW); 156 if (error) { 157 nlookup_done(&nd); 158 return (error); 159 } 160 error = nlookup(&nd); 161 if (error) { 162 nlookup_done(&nd); 163 return (error); 164 } 165 cache_copy(&nd.nl_nch, &pr->pr_root); 166 167 varsymset_init(&pr->pr_varsymset, NULL); 168 prison_ipcache_init(pr); 169 170 error = assign_prison_id(pr); 171 if (error) { 172 varsymset_clean(&pr->pr_varsymset); 173 nlookup_done(&nd); 174 return (error); 175 } 176 177 LIST_INSERT_HEAD(&allprison, pr, pr_list); 178 prisoncount++; 179 180 error = kern_jail_attach(pr->pr_id); 181 if (error) { 182 LIST_REMOVE(pr, pr_list); 183 varsymset_clean(&pr->pr_varsymset); 184 } 185 nlookup_done(&nd); 186 return (error); 187 } 188 189 /* 190 * jail() 191 * 192 * jail_args(syscallarg(struct jail *) jail) 193 * 194 * MPALMOSTSAFE 195 */ 196 int 197 sys_jail(struct jail_args *uap) 198 { 199 struct thread *td = curthread; 200 struct prison *pr; 201 struct jail_ip_storage *jip; 202 struct jail j; 203 int error; 204 uint32_t jversion; 205 206 uap->sysmsg_result = -1; 207 208 error = priv_check(td, PRIV_JAIL_CREATE); 209 if (error) 210 return (error); 211 212 error = copyin(uap->jail, &jversion, sizeof(jversion)); 213 if (error) 214 return (error); 215 216 pr = kmalloc(sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO); 217 SLIST_INIT(&pr->pr_ips); 218 get_mplock(); 219 220 switch (jversion) { 221 case 0: 222 /* Single IPv4 jails. */ 223 { 224 struct jail_v0 jv0; 225 struct sockaddr_in ip4addr; 226 227 error = copyin(uap->jail, &jv0, sizeof(jv0)); 228 if (error) 229 goto out; 230 231 j.path = jv0.path; 232 j.hostname = jv0.hostname; 233 234 jip = kmalloc(sizeof(*jip), M_PRISON, M_WAITOK | M_ZERO); 235 ip4addr.sin_family = AF_INET; 236 ip4addr.sin_addr.s_addr = htonl(jv0.ip_number); 237 memcpy(&jip->ip, &ip4addr, sizeof(ip4addr)); 238 SLIST_INSERT_HEAD(&pr->pr_ips, jip, entries); 239 break; 240 } 241 242 case 1: 243 /* 244 * DragonFly multi noIP/IPv4/IPv6 jails 245 * 246 * NOTE: This version is unsupported by FreeBSD 247 * (which uses version 2 instead). 248 */ 249 250 error = copyin(uap->jail, &j, sizeof(j)); 251 if (error) 252 goto out; 253 254 for (int i = 0; i < j.n_ips; i++) { 255 jip = kmalloc(sizeof(*jip), M_PRISON, 256 M_WAITOK | M_ZERO); 257 SLIST_INSERT_HEAD(&pr->pr_ips, jip, entries); 258 error = copyin(&j.ips[i], &jip->ip, 259 sizeof(struct sockaddr_storage)); 260 if (error) 261 goto out; 262 } 263 break; 264 default: 265 error = EINVAL; 266 goto out; 267 } 268 269 error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0); 270 if (error) 271 goto out; 272 273 error = kern_jail(pr, &j); 274 if (error) 275 goto out; 276 277 uap->sysmsg_result = pr->pr_id; 278 rel_mplock(); 279 return (0); 280 281 out: 282 /* Delete all ips */ 283 while (!SLIST_EMPTY(&pr->pr_ips)) { 284 jip = SLIST_FIRST(&pr->pr_ips); 285 SLIST_REMOVE_HEAD(&pr->pr_ips, entries); 286 kfree(jip, M_PRISON); 287 } 288 rel_mplock(); 289 kfree(pr, M_PRISON); 290 return (error); 291 } 292 293 /* 294 * int jail_attach(int jid); 295 * 296 * MPALMOSTSAFE 297 */ 298 int 299 sys_jail_attach(struct jail_attach_args *uap) 300 { 301 struct thread *td = curthread; 302 int error; 303 304 error = priv_check(td, PRIV_JAIL_ATTACH); 305 if (error) 306 return(error); 307 get_mplock(); 308 error = kern_jail_attach(uap->jid); 309 rel_mplock(); 310 return (error); 311 } 312 313 static void 314 prison_ipcache_init(struct prison *pr) 315 { 316 struct jail_ip_storage *jis; 317 struct sockaddr_in *ip4; 318 struct sockaddr_in6 *ip6; 319 320 SLIST_FOREACH(jis, &pr->pr_ips, entries) { 321 switch (jis->ip.ss_family) { 322 case AF_INET: 323 ip4 = (struct sockaddr_in *)&jis->ip; 324 if ((ntohl(ip4->sin_addr.s_addr) >> IN_CLASSA_NSHIFT) == 325 IN_LOOPBACKNET) { 326 /* loopback address */ 327 if (pr->local_ip4 == NULL) 328 pr->local_ip4 = ip4; 329 } else { 330 /* public address */ 331 if (pr->nonlocal_ip4 == NULL) 332 pr->nonlocal_ip4 = ip4; 333 } 334 break; 335 336 case AF_INET6: 337 ip6 = (struct sockaddr_in6 *)&jis->ip; 338 if (IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr)) { 339 /* loopback address */ 340 if (pr->local_ip6 == NULL) 341 pr->local_ip6 = ip6; 342 } else { 343 /* public address */ 344 if (pr->nonlocal_ip6 == NULL) 345 pr->nonlocal_ip6 = ip6; 346 } 347 break; 348 } 349 } 350 } 351 352 /* 353 * Changes INADDR_LOOPBACK for a valid jail address. 354 * ip is in network byte order. 355 * Returns 1 if the ip is among jail valid ips. 356 * Returns 0 if is not among jail valid ips or 357 * if couldn't replace INADDR_LOOPBACK for a valid 358 * IP. 359 */ 360 int 361 prison_replace_wildcards(struct thread *td, struct sockaddr *ip) 362 { 363 struct sockaddr_in *ip4 = (struct sockaddr_in *)ip; 364 struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip; 365 struct prison *pr; 366 367 if (td->td_proc == NULL) 368 return (1); 369 if ((pr = td->td_ucred->cr_prison) == NULL) 370 return (1); 371 372 if ((ip->sa_family == AF_INET && 373 ip4->sin_addr.s_addr == htonl(INADDR_ANY)) || 374 (ip->sa_family == AF_INET6 && 375 IN6_IS_ADDR_UNSPECIFIED(&ip6->sin6_addr))) 376 return (1); 377 if ((ip->sa_family == AF_INET && 378 ip4->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) || 379 (ip->sa_family == AF_INET6 && 380 IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr))) { 381 if (!prison_get_local(pr, ip->sa_family, ip) && 382 !prison_get_nonlocal(pr, ip->sa_family, ip)) 383 return(0); 384 else 385 return(1); 386 } 387 if (jailed_ip(pr, ip)) 388 return(1); 389 return(0); 390 } 391 392 int 393 prison_remote_ip(struct thread *td, struct sockaddr *ip) 394 { 395 struct sockaddr_in *ip4 = (struct sockaddr_in *)ip; 396 struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip; 397 struct prison *pr; 398 399 if (td == NULL || td->td_proc == NULL) 400 return(1); 401 if ((pr = td->td_ucred->cr_prison) == NULL) 402 return(1); 403 if ((ip->sa_family == AF_INET && 404 ip4->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) || 405 (ip->sa_family == AF_INET6 && 406 IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr))) { 407 if (!prison_get_local(pr, ip->sa_family, ip) && 408 !prison_get_nonlocal(pr, ip->sa_family, ip)) 409 return(0); 410 else 411 return(1); 412 } 413 return(1); 414 } 415 416 /* 417 * Prison get non loopback ip: 418 * - af is the address family of the ip we want (AF_INET|AF_INET6). 419 * - If ip != NULL, put the first IP address that is not a loopback address 420 * into *ip. 421 * 422 * ip is in network by order and we don't touch it unless we find a valid ip. 423 * No matter if ip == NULL or not, we return either a valid struct sockaddr *, 424 * or NULL. This struct may not be modified. 425 */ 426 struct sockaddr * 427 prison_get_nonlocal(struct prison *pr, sa_family_t af, struct sockaddr *ip) 428 { 429 struct sockaddr_in *ip4 = (struct sockaddr_in *)ip; 430 struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip; 431 432 /* Check if it is cached */ 433 switch(af) { 434 case AF_INET: 435 if (ip4 != NULL && pr->nonlocal_ip4 != NULL) 436 ip4->sin_addr.s_addr = pr->nonlocal_ip4->sin_addr.s_addr; 437 return (struct sockaddr *)pr->nonlocal_ip4; 438 439 case AF_INET6: 440 if (ip6 != NULL && pr->nonlocal_ip6 != NULL) 441 ip6->sin6_addr = pr->nonlocal_ip6->sin6_addr; 442 return (struct sockaddr *)pr->nonlocal_ip6; 443 } 444 445 /* NOTREACHED */ 446 return NULL; 447 } 448 449 /* 450 * Prison get loopback ip. 451 * - af is the address family of the ip we want (AF_INET|AF_INET6). 452 * - If ip != NULL, put the first IP address that is not a loopback address 453 * into *ip. 454 * 455 * ip is in network by order and we don't touch it unless we find a valid ip. 456 * No matter if ip == NULL or not, we return either a valid struct sockaddr *, 457 * or NULL. This struct may not be modified. 458 */ 459 struct sockaddr * 460 prison_get_local(struct prison *pr, sa_family_t af, struct sockaddr *ip) 461 { 462 struct sockaddr_in *ip4 = (struct sockaddr_in *)ip; 463 struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip; 464 465 /* Check if it is cached */ 466 switch(af) { 467 case AF_INET: 468 if (ip4 != NULL && pr->local_ip4 != NULL) 469 ip4->sin_addr.s_addr = pr->local_ip4->sin_addr.s_addr; 470 return (struct sockaddr *)pr->local_ip4; 471 472 case AF_INET6: 473 if (ip6 != NULL && pr->local_ip6 != NULL) 474 ip6->sin6_addr = pr->local_ip6->sin6_addr; 475 return (struct sockaddr *)pr->local_ip6; 476 } 477 478 /* NOTREACHED */ 479 return NULL; 480 } 481 482 /* Check if the IP is among ours, if it is return 1, else 0 */ 483 int 484 jailed_ip(struct prison *pr, struct sockaddr *ip) 485 { 486 struct jail_ip_storage *jis; 487 struct sockaddr_in *jip4, *ip4; 488 struct sockaddr_in6 *jip6, *ip6; 489 490 if (pr == NULL) 491 return(0); 492 ip4 = (struct sockaddr_in *)ip; 493 ip6 = (struct sockaddr_in6 *)ip; 494 SLIST_FOREACH(jis, &pr->pr_ips, entries) { 495 switch (ip->sa_family) { 496 case AF_INET: 497 jip4 = (struct sockaddr_in *) &jis->ip; 498 if (jip4->sin_family == AF_INET && 499 ip4->sin_addr.s_addr == jip4->sin_addr.s_addr) 500 return(1); 501 break; 502 case AF_INET6: 503 jip6 = (struct sockaddr_in6 *) &jis->ip; 504 if (jip6->sin6_family == AF_INET6 && 505 IN6_ARE_ADDR_EQUAL(&ip6->sin6_addr, 506 &jip6->sin6_addr)) 507 return(1); 508 break; 509 } 510 } 511 /* Ip not in list */ 512 return(0); 513 } 514 515 int 516 prison_if(struct ucred *cred, struct sockaddr *sa) 517 { 518 struct prison *pr; 519 struct sockaddr_in *sai = (struct sockaddr_in*) sa; 520 521 pr = cred->cr_prison; 522 523 if (((sai->sin_family != AF_INET) && (sai->sin_family != AF_INET6)) 524 && jail_socket_unixiproute_only) 525 return(1); 526 else if ((sai->sin_family != AF_INET) && (sai->sin_family != AF_INET6)) 527 return(0); 528 else if (jailed_ip(pr, sa)) 529 return(0); 530 return(1); 531 } 532 533 /* 534 * Returns a prison instance, or NULL on failure. 535 */ 536 static struct prison * 537 prison_find(int prid) 538 { 539 struct prison *pr; 540 541 LIST_FOREACH(pr, &allprison, pr_list) { 542 if (pr->pr_id == prid) 543 break; 544 } 545 return(pr); 546 } 547 548 static int 549 sysctl_jail_list(SYSCTL_HANDLER_ARGS) 550 { 551 struct thread *td = curthread; 552 struct jail_ip_storage *jip; 553 #ifdef INET6 554 struct sockaddr_in6 *jsin6; 555 #endif 556 struct sockaddr_in *jsin; 557 struct lwp *lp; 558 struct prison *pr; 559 unsigned int jlssize, jlsused; 560 int count, error; 561 char *jls; /* Jail list */ 562 char *oip; /* Output ip */ 563 char *fullpath, *freepath; 564 565 jlsused = 0; 566 567 if (jailed(td->td_ucred)) 568 return (0); 569 lp = td->td_lwp; 570 retry: 571 count = prisoncount; 572 573 if (count == 0) 574 return(0); 575 576 jlssize = (count * 1024); 577 jls = kmalloc(jlssize + 1, M_TEMP, M_WAITOK | M_ZERO); 578 if (count < prisoncount) { 579 kfree(jls, M_TEMP); 580 goto retry; 581 } 582 count = prisoncount; 583 584 LIST_FOREACH(pr, &allprison, pr_list) { 585 error = cache_fullpath(lp->lwp_proc, &pr->pr_root, 586 &fullpath, &freepath); 587 if (error) 588 continue; 589 if (jlsused && jlsused < jlssize) 590 jls[jlsused++] = '\n'; 591 count = ksnprintf(jls + jlsused, (jlssize - jlsused), 592 "%d %s %s", 593 pr->pr_id, pr->pr_host, fullpath); 594 kfree(freepath, M_TEMP); 595 if (count < 0) 596 goto end; 597 jlsused += count; 598 599 /* Copy the IPS */ 600 SLIST_FOREACH(jip, &pr->pr_ips, entries) { 601 jsin = (struct sockaddr_in *)&jip->ip; 602 603 switch(jsin->sin_family) { 604 case AF_INET: 605 oip = inet_ntoa(jsin->sin_addr); 606 break; 607 #ifdef INET6 608 case AF_INET6: 609 jsin6 = (struct sockaddr_in6 *)&jip->ip; 610 oip = ip6_sprintf(&jsin6->sin6_addr); 611 break; 612 #endif 613 default: 614 oip = "?family?"; 615 break; 616 } 617 618 if ((jlssize - jlsused) < (strlen(oip) + 1)) { 619 error = ERANGE; 620 goto end; 621 } 622 count = ksnprintf(jls + jlsused, (jlssize - jlsused), 623 " %s", oip); 624 if (count < 0) 625 goto end; 626 jlsused += count; 627 } 628 } 629 630 /* 631 * The format is: 632 * pr_id <SPC> hostname1 <SPC> PATH1 <SPC> IP1 <SPC> IP2\npr_id... 633 */ 634 error = SYSCTL_OUT(req, jls, jlsused); 635 end: 636 kfree(jls, M_TEMP); 637 return(error); 638 } 639 640 SYSCTL_OID(_jail, OID_AUTO, list, CTLTYPE_STRING | CTLFLAG_RD, NULL, 0, 641 sysctl_jail_list, "A", "List of active jails"); 642 643 void 644 prison_hold(struct prison *pr) 645 { 646 pr->pr_ref++; 647 } 648 649 void 650 prison_free(struct prison *pr) 651 { 652 struct jail_ip_storage *jls; 653 KKASSERT(pr->pr_ref >= 1); 654 655 if (--pr->pr_ref > 0) 656 return; 657 658 /* Delete all ips */ 659 while (!SLIST_EMPTY(&pr->pr_ips)) { 660 jls = SLIST_FIRST(&pr->pr_ips); 661 SLIST_REMOVE_HEAD(&pr->pr_ips, entries); 662 kfree(jls, M_PRISON); 663 } 664 LIST_REMOVE(pr, pr_list); 665 prisoncount--; 666 667 if (pr->pr_linux != NULL) 668 kfree(pr->pr_linux, M_PRISON); 669 varsymset_clean(&pr->pr_varsymset); 670 cache_drop(&pr->pr_root); 671 kfree(pr, M_PRISON); 672 } 673 674 /* 675 * Check if permisson for a specific privilege is granted within jail. 676 * 677 * MPSAFE 678 */ 679 int 680 prison_priv_check(struct ucred *cred, int priv) 681 { 682 if (!jailed(cred)) 683 return (0); 684 685 switch (priv) { 686 case PRIV_CRED_SETUID: 687 case PRIV_CRED_SETEUID: 688 case PRIV_CRED_SETGID: 689 case PRIV_CRED_SETEGID: 690 case PRIV_CRED_SETGROUPS: 691 case PRIV_CRED_SETREUID: 692 case PRIV_CRED_SETREGID: 693 case PRIV_CRED_SETRESUID: 694 case PRIV_CRED_SETRESGID: 695 696 case PRIV_VFS_SYSFLAGS: 697 case PRIV_VFS_CHOWN: 698 case PRIV_VFS_CHMOD: 699 case PRIV_VFS_CHROOT: 700 case PRIV_VFS_LINK: 701 case PRIV_VFS_CHFLAGS_DEV: 702 case PRIV_VFS_REVOKE: 703 case PRIV_VFS_MKNOD_BAD: 704 case PRIV_VFS_MKNOD_WHT: 705 case PRIV_VFS_MKNOD_DIR: 706 case PRIV_VFS_SETATTR: 707 case PRIV_VFS_SETGID: 708 709 case PRIV_PROC_SETRLIMIT: 710 case PRIV_PROC_SETLOGIN: 711 712 case PRIV_SYSCTL_WRITEJAIL: 713 714 case PRIV_VARSYM_SYS: 715 716 case PRIV_SETHOSTNAME: 717 718 case PRIV_PROC_TRESPASS: 719 720 return (0); 721 722 case PRIV_UFS_QUOTAON: 723 case PRIV_UFS_QUOTAOFF: 724 case PRIV_VFS_SETQUOTA: 725 case PRIV_UFS_SETUSE: 726 case PRIV_VFS_GETQUOTA: 727 return (0); 728 729 730 case PRIV_DEBUG_UNPRIV: 731 return (0); 732 733 734 /* 735 * Allow jailed root to bind reserved ports. 736 */ 737 case PRIV_NETINET_RESERVEDPORT: 738 return (0); 739 740 741 /* 742 * Conditionally allow creating raw sockets in jail. 743 */ 744 case PRIV_NETINET_RAW: 745 if (jail_allow_raw_sockets) 746 return (0); 747 else 748 return (EPERM); 749 750 case PRIV_HAMMER_IOCTL: 751 return (0); 752 753 default: 754 755 return (EPERM); 756 } 757 } 758