1 /* $OpenBSD: kern_pledge.c,v 1.220 2017/09/08 05:36:53 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org> 5 * Copyright (c) 2015 Theo de Raadt <deraadt@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/param.h> 21 22 #include <sys/mount.h> 23 #include <sys/proc.h> 24 #include <sys/fcntl.h> 25 #include <sys/file.h> 26 #include <sys/filedesc.h> 27 #include <sys/namei.h> 28 #include <sys/socketvar.h> 29 #include <sys/vnode.h> 30 #include <sys/mbuf.h> 31 #include <sys/mman.h> 32 #include <sys/sysctl.h> 33 #include <sys/syslog.h> 34 #include <sys/ktrace.h> 35 #include <sys/acct.h> 36 37 #include <sys/ioctl.h> 38 #include <sys/termios.h> 39 #include <sys/tty.h> 40 #include <sys/device.h> 41 #include <sys/disklabel.h> 42 #include <sys/dkio.h> 43 #include <sys/mtio.h> 44 #include <sys/audioio.h> 45 #include <net/bpf.h> 46 #include <net/route.h> 47 #include <net/if.h> 48 #include <net/if_var.h> 49 #include <netinet/in.h> 50 #include <netinet6/in6_var.h> 51 #include <netinet6/nd6.h> 52 #include <netinet/tcp.h> 53 #include <net/pfvar.h> 54 55 #include <sys/conf.h> 56 #include <sys/specdev.h> 57 #include <sys/signal.h> 58 #include <sys/signalvar.h> 59 #include <sys/syscall.h> 60 #include <sys/syscallargs.h> 61 #include <sys/systm.h> 62 63 #include <dev/biovar.h> 64 65 #define PLEDGENAMES 66 #include <sys/pledge.h> 67 68 #include "audio.h" 69 #include "bpfilter.h" 70 #include "pf.h" 71 #include "pty.h" 72 73 #if defined(__amd64__) || defined(__i386__) 74 #include "vmm.h" 75 #if NVMM > 0 76 #include <machine/conf.h> 77 #endif 78 #endif 79 80 #if defined(__amd64__) || defined(__i386__) || \ 81 defined(__loongson__) || defined(__macppc__) || \ 82 defined(__sparc64__) 83 #include "drm.h" 84 #endif 85 86 uint64_t pledgereq_flags(const char *req); 87 int canonpath(const char *input, char *buf, size_t bufsize); 88 89 /* #define DEBUG_PLEDGE */ 90 #ifdef DEBUG_PLEDGE 91 int debug_pledge = 1; 92 #define DPRINTF(x...) do { if (debug_pledge) printf(x); } while (0) 93 #define DNPRINTF(n,x...) do { if (debug_pledge >= (n)) printf(x); } while (0) 94 #else 95 #define DPRINTF(x...) 96 #define DNPRINTF(n,x...) 97 #endif 98 99 /* 100 * Ordered in blocks starting with least risky and most required. 101 */ 102 const uint64_t pledge_syscalls[SYS_MAXSYSCALL] = { 103 /* 104 * Minimum required 105 */ 106 [SYS_exit] = PLEDGE_ALWAYS, 107 [SYS_kbind] = PLEDGE_ALWAYS, 108 [SYS___get_tcb] = PLEDGE_ALWAYS, 109 [SYS_pledge] = PLEDGE_ALWAYS, 110 [SYS_sendsyslog] = PLEDGE_ALWAYS, /* stack protector reporting */ 111 [SYS_thrkill] = PLEDGE_ALWAYS, /* raise, abort, stack pro */ 112 [SYS_utrace] = PLEDGE_ALWAYS, /* ltrace(1) from ld.so */ 113 114 /* "getting" information about self is considered safe */ 115 [SYS_getuid] = PLEDGE_STDIO, 116 [SYS_geteuid] = PLEDGE_STDIO, 117 [SYS_getresuid] = PLEDGE_STDIO, 118 [SYS_getgid] = PLEDGE_STDIO, 119 [SYS_getegid] = PLEDGE_STDIO, 120 [SYS_getresgid] = PLEDGE_STDIO, 121 [SYS_getgroups] = PLEDGE_STDIO, 122 [SYS_getlogin_r] = PLEDGE_STDIO, 123 [SYS_getpgrp] = PLEDGE_STDIO, 124 [SYS_getpgid] = PLEDGE_STDIO, 125 [SYS_getppid] = PLEDGE_STDIO, 126 [SYS_getsid] = PLEDGE_STDIO, 127 [SYS_getthrid] = PLEDGE_STDIO, 128 [SYS_getrlimit] = PLEDGE_STDIO, 129 [SYS_getrtable] = PLEDGE_STDIO, 130 [SYS_gettimeofday] = PLEDGE_STDIO, 131 [SYS_getdtablecount] = PLEDGE_STDIO, 132 [SYS_getrusage] = PLEDGE_STDIO, 133 [SYS_issetugid] = PLEDGE_STDIO, 134 [SYS_clock_getres] = PLEDGE_STDIO, 135 [SYS_clock_gettime] = PLEDGE_STDIO, 136 [SYS_getpid] = PLEDGE_STDIO, 137 138 /* 139 * Almost exclusively read-only, Very narrow subset. 140 * Use of "route", "inet", "dns", "ps", or "vminfo" 141 * expands access. 142 */ 143 [SYS_sysctl] = PLEDGE_STDIO, 144 145 /* Support for malloc(3) family of operations */ 146 [SYS_getentropy] = PLEDGE_STDIO, 147 [SYS_madvise] = PLEDGE_STDIO, 148 [SYS_minherit] = PLEDGE_STDIO, 149 [SYS_mmap] = PLEDGE_STDIO, 150 [SYS_mprotect] = PLEDGE_STDIO, 151 [SYS_mquery] = PLEDGE_STDIO, 152 [SYS_munmap] = PLEDGE_STDIO, 153 [SYS_msync] = PLEDGE_STDIO, 154 [SYS_break] = PLEDGE_STDIO, 155 156 [SYS_umask] = PLEDGE_STDIO, 157 158 /* read/write operations */ 159 [SYS_read] = PLEDGE_STDIO, 160 [SYS_readv] = PLEDGE_STDIO, 161 [SYS_pread] = PLEDGE_STDIO, 162 [SYS_preadv] = PLEDGE_STDIO, 163 [SYS_write] = PLEDGE_STDIO, 164 [SYS_writev] = PLEDGE_STDIO, 165 [SYS_pwrite] = PLEDGE_STDIO, 166 [SYS_pwritev] = PLEDGE_STDIO, 167 [SYS_recvmsg] = PLEDGE_STDIO, 168 [SYS_recvfrom] = PLEDGE_STDIO | PLEDGE_YPACTIVE, 169 [SYS_ftruncate] = PLEDGE_STDIO, 170 [SYS_lseek] = PLEDGE_STDIO, 171 [SYS_fpathconf] = PLEDGE_STDIO, 172 173 /* 174 * Address selection required a network pledge ("inet", 175 * "unix", "dns". 176 */ 177 [SYS_sendto] = PLEDGE_STDIO | PLEDGE_YPACTIVE, 178 179 /* 180 * Address specification required a network pledge ("inet", 181 * "unix", "dns". SCM_RIGHTS requires "sendfd" or "recvfd". 182 */ 183 [SYS_sendmsg] = PLEDGE_STDIO, 184 185 /* Common signal operations */ 186 [SYS_nanosleep] = PLEDGE_STDIO, 187 [SYS_sigaltstack] = PLEDGE_STDIO, 188 [SYS_sigprocmask] = PLEDGE_STDIO, 189 [SYS_sigsuspend] = PLEDGE_STDIO, 190 [SYS_sigaction] = PLEDGE_STDIO, 191 [SYS_sigreturn] = PLEDGE_STDIO, 192 [SYS_sigpending] = PLEDGE_STDIO, 193 [SYS_getitimer] = PLEDGE_STDIO, 194 [SYS_setitimer] = PLEDGE_STDIO, 195 196 /* 197 * To support event driven programming. 198 */ 199 [SYS_poll] = PLEDGE_STDIO, 200 [SYS_ppoll] = PLEDGE_STDIO, 201 [SYS_kevent] = PLEDGE_STDIO, 202 [SYS_kqueue] = PLEDGE_STDIO, 203 [SYS_select] = PLEDGE_STDIO, 204 [SYS_pselect] = PLEDGE_STDIO, 205 206 [SYS_fstat] = PLEDGE_STDIO, 207 [SYS_fsync] = PLEDGE_STDIO, 208 209 [SYS_setsockopt] = PLEDGE_STDIO, /* narrow whitelist */ 210 [SYS_getsockopt] = PLEDGE_STDIO, /* narrow whitelist */ 211 212 /* F_SETOWN requires PLEDGE_PROC */ 213 [SYS_fcntl] = PLEDGE_STDIO, 214 215 [SYS_close] = PLEDGE_STDIO, 216 [SYS_dup] = PLEDGE_STDIO, 217 [SYS_dup2] = PLEDGE_STDIO, 218 [SYS_dup3] = PLEDGE_STDIO, 219 [SYS_closefrom] = PLEDGE_STDIO, 220 [SYS_shutdown] = PLEDGE_STDIO, 221 [SYS_fchdir] = PLEDGE_STDIO, /* XXX consider tightening */ 222 223 [SYS_pipe] = PLEDGE_STDIO, 224 [SYS_pipe2] = PLEDGE_STDIO, 225 [SYS_socketpair] = PLEDGE_STDIO, 226 227 [SYS_wait4] = PLEDGE_STDIO, 228 229 /* 230 * Can kill self with "stdio". Killing another pid 231 * requires "proc" 232 */ 233 [SYS_kill] = PLEDGE_STDIO, 234 235 /* 236 * FIONREAD/FIONBIO for "stdio" 237 * Other ioctl are selectively allowed based upon other pledges. 238 */ 239 [SYS_ioctl] = PLEDGE_STDIO, 240 241 /* 242 * Path access/creation calls encounter many extensive 243 * checks are done during namei() 244 */ 245 [SYS_open] = PLEDGE_STDIO, 246 [SYS_stat] = PLEDGE_STDIO, 247 [SYS_access] = PLEDGE_STDIO, 248 [SYS_readlink] = PLEDGE_STDIO, 249 250 [SYS_adjtime] = PLEDGE_STDIO, /* setting requires "settime" */ 251 [SYS_adjfreq] = PLEDGE_SETTIME, 252 [SYS_settimeofday] = PLEDGE_SETTIME, 253 254 /* 255 * Needed by threaded programs 256 * XXX should we have a new "threads"? 257 */ 258 [SYS___tfork] = PLEDGE_STDIO, 259 [SYS_sched_yield] = PLEDGE_STDIO, 260 [SYS_futex] = PLEDGE_STDIO, 261 [SYS___thrsleep] = PLEDGE_STDIO, 262 [SYS___thrwakeup] = PLEDGE_STDIO, 263 [SYS___threxit] = PLEDGE_STDIO, 264 [SYS___thrsigdivert] = PLEDGE_STDIO, 265 266 [SYS_fork] = PLEDGE_PROC, 267 [SYS_vfork] = PLEDGE_PROC, 268 [SYS_setpgid] = PLEDGE_PROC, 269 [SYS_setsid] = PLEDGE_PROC, 270 271 [SYS_setrlimit] = PLEDGE_PROC | PLEDGE_ID, 272 [SYS_getpriority] = PLEDGE_PROC | PLEDGE_ID, 273 274 [SYS_setpriority] = PLEDGE_PROC | PLEDGE_ID, 275 276 [SYS_setuid] = PLEDGE_ID, 277 [SYS_seteuid] = PLEDGE_ID, 278 [SYS_setreuid] = PLEDGE_ID, 279 [SYS_setresuid] = PLEDGE_ID, 280 [SYS_setgid] = PLEDGE_ID, 281 [SYS_setegid] = PLEDGE_ID, 282 [SYS_setregid] = PLEDGE_ID, 283 [SYS_setresgid] = PLEDGE_ID, 284 [SYS_setgroups] = PLEDGE_ID, 285 [SYS_setlogin] = PLEDGE_ID, 286 287 [SYS_execve] = PLEDGE_EXEC, 288 289 [SYS_chdir] = PLEDGE_RPATH, 290 [SYS_openat] = PLEDGE_RPATH | PLEDGE_WPATH, 291 [SYS_fstatat] = PLEDGE_RPATH | PLEDGE_WPATH, 292 [SYS_faccessat] = PLEDGE_RPATH | PLEDGE_WPATH, 293 [SYS_readlinkat] = PLEDGE_RPATH | PLEDGE_WPATH, 294 [SYS_lstat] = PLEDGE_RPATH | PLEDGE_WPATH | PLEDGE_TMPPATH, 295 [SYS_truncate] = PLEDGE_WPATH, 296 [SYS_rename] = PLEDGE_RPATH | PLEDGE_CPATH, 297 [SYS_rmdir] = PLEDGE_CPATH, 298 [SYS_renameat] = PLEDGE_CPATH, 299 [SYS_link] = PLEDGE_CPATH, 300 [SYS_linkat] = PLEDGE_CPATH, 301 [SYS_symlink] = PLEDGE_CPATH, 302 [SYS_symlinkat] = PLEDGE_CPATH, 303 [SYS_unlink] = PLEDGE_CPATH | PLEDGE_TMPPATH, 304 [SYS_unlinkat] = PLEDGE_CPATH, 305 [SYS_mkdir] = PLEDGE_CPATH, 306 [SYS_mkdirat] = PLEDGE_CPATH, 307 308 [SYS_mkfifo] = PLEDGE_DPATH, 309 [SYS_mknod] = PLEDGE_DPATH, 310 311 [SYS_revoke] = PLEDGE_TTY, /* also requires PLEDGE_RPATH */ 312 313 /* 314 * Classify as RPATH|WPATH, because of path information leakage. 315 * WPATH due to unknown use of mk*temp(3) on non-/tmp paths.. 316 */ 317 [SYS___getcwd] = PLEDGE_RPATH | PLEDGE_WPATH, 318 319 /* Classify as RPATH, because these leak path information */ 320 [SYS_getdents] = PLEDGE_RPATH, 321 [SYS_getfsstat] = PLEDGE_RPATH, 322 [SYS_statfs] = PLEDGE_RPATH, 323 [SYS_fstatfs] = PLEDGE_RPATH, 324 [SYS_pathconf] = PLEDGE_RPATH, 325 326 [SYS_utimes] = PLEDGE_FATTR, 327 [SYS_futimes] = PLEDGE_FATTR, 328 [SYS_utimensat] = PLEDGE_FATTR, 329 [SYS_futimens] = PLEDGE_FATTR, 330 [SYS_chmod] = PLEDGE_FATTR, 331 [SYS_fchmod] = PLEDGE_FATTR, 332 [SYS_fchmodat] = PLEDGE_FATTR, 333 [SYS_chflags] = PLEDGE_FATTR, 334 [SYS_chflagsat] = PLEDGE_FATTR, 335 [SYS_fchflags] = PLEDGE_FATTR, 336 337 [SYS_chown] = PLEDGE_CHOWN, 338 [SYS_fchownat] = PLEDGE_CHOWN, 339 [SYS_lchown] = PLEDGE_CHOWN, 340 [SYS_fchown] = PLEDGE_CHOWN, 341 342 [SYS_socket] = PLEDGE_INET | PLEDGE_UNIX | PLEDGE_DNS | PLEDGE_YPACTIVE, 343 [SYS_connect] = PLEDGE_INET | PLEDGE_UNIX | PLEDGE_DNS | PLEDGE_YPACTIVE, 344 [SYS_bind] = PLEDGE_INET | PLEDGE_UNIX | PLEDGE_DNS | PLEDGE_YPACTIVE, 345 [SYS_getsockname] = PLEDGE_INET | PLEDGE_UNIX | PLEDGE_DNS | PLEDGE_YPACTIVE, 346 347 [SYS_listen] = PLEDGE_INET | PLEDGE_UNIX, 348 [SYS_accept4] = PLEDGE_INET | PLEDGE_UNIX, 349 [SYS_accept] = PLEDGE_INET | PLEDGE_UNIX, 350 [SYS_getpeername] = PLEDGE_INET | PLEDGE_UNIX, 351 352 [SYS_flock] = PLEDGE_FLOCK | PLEDGE_YPACTIVE, 353 354 [SYS_swapctl] = PLEDGE_VMINFO, /* XXX should limit to "get" operations */ 355 }; 356 357 static const struct { 358 char *name; 359 uint64_t flags; 360 } pledgereq[] = { 361 { "audio", PLEDGE_AUDIO }, 362 { "bpf", PLEDGE_BPF }, 363 { "chown", PLEDGE_CHOWN | PLEDGE_CHOWNUID }, 364 { "cpath", PLEDGE_CPATH }, 365 { "disklabel", PLEDGE_DISKLABEL }, 366 { "dns", PLEDGE_DNS }, 367 { "dpath", PLEDGE_DPATH }, 368 { "drm", PLEDGE_DRM }, 369 { "exec", PLEDGE_EXEC }, 370 { "fattr", PLEDGE_FATTR | PLEDGE_CHOWN }, 371 { "flock", PLEDGE_FLOCK }, 372 { "getpw", PLEDGE_GETPW }, 373 { "id", PLEDGE_ID }, 374 { "inet", PLEDGE_INET }, 375 { "mcast", PLEDGE_MCAST }, 376 { "pf", PLEDGE_PF }, 377 { "proc", PLEDGE_PROC }, 378 { "prot_exec", PLEDGE_PROTEXEC }, 379 { "ps", PLEDGE_PS }, 380 { "recvfd", PLEDGE_RECVFD }, 381 { "route", PLEDGE_ROUTE }, 382 { "rpath", PLEDGE_RPATH }, 383 { "sendfd", PLEDGE_SENDFD }, 384 { "settime", PLEDGE_SETTIME }, 385 { "stdio", PLEDGE_STDIO }, 386 { "tape", PLEDGE_TAPE }, 387 { "tmppath", PLEDGE_TMPPATH }, 388 { "tty", PLEDGE_TTY }, 389 { "unix", PLEDGE_UNIX }, 390 { "vminfo", PLEDGE_VMINFO }, 391 { "vmm", PLEDGE_VMM }, 392 { "wpath", PLEDGE_WPATH }, 393 }; 394 395 int 396 sys_pledge(struct proc *p, void *v, register_t *retval) 397 { 398 struct sys_pledge_args /* { 399 syscallarg(const char *)request; 400 syscallarg(const char **)paths; 401 } */ *uap = v; 402 struct process *pr = p->p_p; 403 uint64_t flags = 0; 404 int error; 405 406 if (SCARG(uap, request)) { 407 size_t rbuflen; 408 char *rbuf, *rp, *pn; 409 uint64_t f; 410 411 rbuf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 412 error = copyinstr(SCARG(uap, request), rbuf, MAXPATHLEN, 413 &rbuflen); 414 if (error) { 415 free(rbuf, M_TEMP, MAXPATHLEN); 416 return (error); 417 } 418 #ifdef KTRACE 419 if (KTRPOINT(p, KTR_STRUCT)) 420 ktrstruct(p, "pledgereq", rbuf, rbuflen-1); 421 #endif 422 423 for (rp = rbuf; rp && *rp && error == 0; rp = pn) { 424 pn = strchr(rp, ' '); /* find terminator */ 425 if (pn) { 426 while (*pn == ' ') 427 *pn++ = '\0'; 428 } 429 430 if ((f = pledgereq_flags(rp)) == 0) { 431 free(rbuf, M_TEMP, MAXPATHLEN); 432 return (EINVAL); 433 } 434 flags |= f; 435 } 436 free(rbuf, M_TEMP, MAXPATHLEN); 437 438 /* 439 * if we are already pledged, allow only promises reductions. 440 * flags doesn't contain flags outside _USERSET: they will be 441 * relearned. 442 */ 443 if (ISSET(pr->ps_flags, PS_PLEDGE) && 444 (((flags | pr->ps_pledge) != pr->ps_pledge))) 445 return (EPERM); 446 } 447 448 if (SCARG(uap, paths)) 449 return (EINVAL); 450 451 if (SCARG(uap, request)) { 452 pr->ps_pledge = flags; 453 pr->ps_flags |= PS_PLEDGE; 454 } 455 456 return (0); 457 } 458 459 int 460 pledge_syscall(struct proc *p, int code, uint64_t *tval) 461 { 462 p->p_pledge_syscall = code; 463 *tval = 0; 464 465 if (code < 0 || code > SYS_MAXSYSCALL - 1) 466 return (EINVAL); 467 468 if (pledge_syscalls[code] == PLEDGE_ALWAYS) 469 return (0); 470 471 if (p->p_p->ps_pledge & pledge_syscalls[code]) 472 return (0); 473 474 *tval = pledge_syscalls[code]; 475 return (EPERM); 476 } 477 478 int 479 pledge_fail(struct proc *p, int error, uint64_t code) 480 { 481 char *codes = ""; 482 int i; 483 struct sigaction sa; 484 485 /* Print first matching pledge */ 486 for (i = 0; code && pledgenames[i].bits != 0; i++) 487 if (pledgenames[i].bits & code) { 488 codes = pledgenames[i].name; 489 break; 490 } 491 log(LOG_ERR, "%s(%d): syscall %d \"%s\"\n", 492 p->p_p->ps_comm, p->p_p->ps_pid, p->p_pledge_syscall, codes); 493 p->p_p->ps_acflag |= APLEDGE; 494 #ifdef KTRACE 495 if (KTRPOINT(p, KTR_PLEDGE)) 496 ktrpledge(p, error, code, p->p_pledge_syscall); 497 #endif 498 /* Send uncatchable SIGABRT for coredump */ 499 memset(&sa, 0, sizeof sa); 500 sa.sa_handler = SIG_DFL; 501 setsigvec(p, SIGABRT, &sa); 502 psignal(p, SIGABRT); 503 504 p->p_p->ps_pledge = 0; /* Disable all PLEDGE_ flags */ 505 return (error); 506 } 507 508 /* 509 * Need to make it more obvious that one cannot get through here 510 * without the right flags set 511 */ 512 int 513 pledge_namei(struct proc *p, struct nameidata *ni, char *origpath) 514 { 515 char path[PATH_MAX]; 516 int error; 517 518 if ((p->p_p->ps_flags & PS_PLEDGE) == 0 || 519 (p->p_p->ps_flags & PS_COREDUMP)) 520 return (0); 521 522 if (!ni || (ni->ni_pledge == 0)) 523 panic("ni_pledge"); 524 525 /* Doing a permitted execve() */ 526 if ((ni->ni_pledge & PLEDGE_EXEC) && 527 (p->p_p->ps_pledge & PLEDGE_EXEC)) 528 return (0); 529 530 error = canonpath(origpath, path, sizeof(path)); 531 if (error) 532 return (error); 533 534 /* Detect what looks like a mkstemp(3) family operation */ 535 if ((p->p_p->ps_pledge & PLEDGE_TMPPATH) && 536 (p->p_pledge_syscall == SYS_open) && 537 (ni->ni_pledge & PLEDGE_CPATH) && 538 strncmp(path, "/tmp/", sizeof("/tmp/") - 1) == 0) { 539 return (0); 540 } 541 542 /* Allow unlinking of a mkstemp(3) file... 543 * Good opportunity for strict checks here. 544 */ 545 if ((p->p_p->ps_pledge & PLEDGE_TMPPATH) && 546 (p->p_pledge_syscall == SYS_unlink) && 547 strncmp(path, "/tmp/", sizeof("/tmp/") - 1) == 0) { 548 return (0); 549 } 550 551 /* Whitelisted paths */ 552 switch (p->p_pledge_syscall) { 553 case SYS_access: 554 /* tzset() needs this. */ 555 if ((ni->ni_pledge == PLEDGE_RPATH) && 556 strcmp(path, "/etc/localtime") == 0) 557 return (0); 558 559 /* when avoiding YP mode, getpw* functions touch this */ 560 if (ni->ni_pledge == PLEDGE_RPATH && 561 strcmp(path, "/var/run/ypbind.lock") == 0) { 562 if (p->p_p->ps_pledge & PLEDGE_GETPW) 563 return (0); 564 else 565 return (pledge_fail(p, error, PLEDGE_GETPW)); 566 } 567 break; 568 case SYS_open: 569 /* daemon(3) or other such functions */ 570 if ((ni->ni_pledge & ~(PLEDGE_RPATH | PLEDGE_WPATH)) == 0 && 571 strcmp(path, "/dev/null") == 0) { 572 return (0); 573 } 574 575 /* readpassphrase(3), getpass(3) */ 576 if ((p->p_p->ps_pledge & PLEDGE_TTY) && 577 (ni->ni_pledge & ~(PLEDGE_RPATH | PLEDGE_WPATH)) == 0 && 578 strcmp(path, "/dev/tty") == 0) { 579 return (0); 580 } 581 582 /* getpw* and friends need a few files */ 583 if ((ni->ni_pledge == PLEDGE_RPATH) && 584 (p->p_p->ps_pledge & PLEDGE_GETPW)) { 585 if (strcmp(path, "/etc/spwd.db") == 0) 586 return (EPERM); /* don't call pledge_fail */ 587 if (strcmp(path, "/etc/pwd.db") == 0) 588 return (0); 589 if (strcmp(path, "/etc/group") == 0) 590 return (0); 591 if (strcmp(path, "/etc/netid") == 0) 592 return (0); 593 } 594 595 /* DNS needs /etc/{resolv.conf,hosts,services}. */ 596 if ((ni->ni_pledge == PLEDGE_RPATH) && 597 (p->p_p->ps_pledge & PLEDGE_DNS)) { 598 if (strcmp(path, "/etc/resolv.conf") == 0) 599 return (0); 600 if (strcmp(path, "/etc/hosts") == 0) 601 return (0); 602 if (strcmp(path, "/etc/services") == 0) 603 return (0); 604 } 605 606 if ((ni->ni_pledge == PLEDGE_RPATH) && 607 (p->p_p->ps_pledge & PLEDGE_GETPW)) { 608 if (strcmp(path, "/var/run/ypbind.lock") == 0) { 609 /* 610 * XXX 611 * The current hack for YP support in "getpw" 612 * is to enable some "inet" features until 613 * next pledge call. This is not considered 614 * worse than pre-pledge, but is a work in 615 * progress, needing a clever design. 616 */ 617 p->p_p->ps_pledge |= PLEDGE_YPACTIVE; 618 return (0); 619 } 620 if (strncmp(path, "/var/yp/binding/", 621 sizeof("/var/yp/binding/") - 1) == 0) 622 return (0); 623 } 624 625 /* tzset() needs these. */ 626 if ((ni->ni_pledge == PLEDGE_RPATH) && 627 strncmp(path, "/usr/share/zoneinfo/", 628 sizeof("/usr/share/zoneinfo/") - 1) == 0) 629 return (0); 630 if ((ni->ni_pledge == PLEDGE_RPATH) && 631 strcmp(path, "/etc/localtime") == 0) 632 return (0); 633 634 break; 635 case SYS_readlink: 636 /* Allow /etc/malloc.conf for malloc(3). */ 637 if ((ni->ni_pledge == PLEDGE_RPATH) && 638 strcmp(path, "/etc/malloc.conf") == 0) 639 return (0); 640 break; 641 case SYS_stat: 642 /* DNS needs /etc/resolv.conf. */ 643 if ((ni->ni_pledge == PLEDGE_RPATH) && 644 (p->p_p->ps_pledge & PLEDGE_DNS) && 645 strcmp(path, "/etc/resolv.conf") == 0) 646 return (0); 647 break; 648 } 649 650 /* 651 * Ensure each flag of p_pledgenote has counterpart allowing it in 652 * ps_pledge 653 */ 654 if (ni->ni_pledge & ~p->p_p->ps_pledge) 655 return (pledge_fail(p, EPERM, (ni->ni_pledge & ~p->p_p->ps_pledge))); 656 657 return (0); 658 } 659 660 /* 661 * Only allow reception of safe file descriptors. 662 */ 663 int 664 pledge_recvfd(struct proc *p, struct file *fp) 665 { 666 struct vnode *vp; 667 668 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 669 return (0); 670 if ((p->p_p->ps_pledge & PLEDGE_RECVFD) == 0) 671 return pledge_fail(p, EPERM, PLEDGE_RECVFD); 672 673 switch (fp->f_type) { 674 case DTYPE_SOCKET: 675 case DTYPE_PIPE: 676 return (0); 677 case DTYPE_VNODE: 678 vp = fp->f_data; 679 680 if (vp->v_type != VDIR) 681 return (0); 682 break; 683 } 684 return pledge_fail(p, EINVAL, PLEDGE_RECVFD); 685 } 686 687 /* 688 * Only allow sending of safe file descriptors. 689 */ 690 int 691 pledge_sendfd(struct proc *p, struct file *fp) 692 { 693 struct vnode *vp; 694 695 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 696 return (0); 697 if ((p->p_p->ps_pledge & PLEDGE_SENDFD) == 0) 698 return pledge_fail(p, EPERM, PLEDGE_SENDFD); 699 700 switch (fp->f_type) { 701 case DTYPE_SOCKET: 702 case DTYPE_PIPE: 703 return (0); 704 case DTYPE_VNODE: 705 vp = fp->f_data; 706 707 if (vp->v_type != VDIR) 708 return (0); 709 break; 710 } 711 return pledge_fail(p, EINVAL, PLEDGE_SENDFD); 712 } 713 714 int 715 pledge_sysctl(struct proc *p, int miblen, int *mib, void *new) 716 { 717 char buf[80]; 718 int i; 719 720 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 721 return (0); 722 723 if (new) 724 return pledge_fail(p, EFAULT, 0); 725 726 /* routing table observation */ 727 if ((p->p_p->ps_pledge & PLEDGE_ROUTE)) { 728 if ((miblen == 6 || miblen == 7) && 729 mib[0] == CTL_NET && mib[1] == PF_ROUTE && 730 mib[2] == 0 && 731 mib[4] == NET_RT_DUMP) 732 return (0); 733 734 if (miblen == 6 && 735 mib[0] == CTL_NET && mib[1] == PF_ROUTE && 736 mib[2] == 0 && 737 (mib[3] == 0 || mib[3] == AF_INET6 || mib[3] == AF_INET) && 738 mib[4] == NET_RT_TABLE) 739 return (0); 740 741 if (miblen == 7 && /* exposes MACs */ 742 mib[0] == CTL_NET && mib[1] == PF_ROUTE && 743 mib[2] == 0 && 744 (mib[3] == 0 || mib[3] == AF_INET6 || mib[3] == AF_INET) && 745 mib[4] == NET_RT_FLAGS && mib[5] == RTF_LLINFO) 746 return (0); 747 } 748 749 if (p->p_p->ps_pledge & (PLEDGE_PS | PLEDGE_VMINFO)) { 750 if (miblen == 2 && /* kern.fscale */ 751 mib[0] == CTL_KERN && mib[1] == KERN_FSCALE) 752 return (0); 753 if (miblen == 2 && /* kern.boottime */ 754 mib[0] == CTL_KERN && mib[1] == KERN_BOOTTIME) 755 return (0); 756 if (miblen == 2 && /* kern.consdev */ 757 mib[0] == CTL_KERN && mib[1] == KERN_CONSDEV) 758 return (0); 759 if (miblen == 2 && /* kern.cptime */ 760 mib[0] == CTL_KERN && mib[1] == KERN_CPTIME) 761 return (0); 762 if (miblen == 3 && /* kern.cptime2 */ 763 mib[0] == CTL_KERN && mib[1] == KERN_CPTIME2) 764 return (0); 765 } 766 767 if ((p->p_p->ps_pledge & PLEDGE_PS)) { 768 if (miblen == 4 && /* kern.procargs.* */ 769 mib[0] == CTL_KERN && mib[1] == KERN_PROC_ARGS && 770 (mib[3] == KERN_PROC_ARGV || mib[3] == KERN_PROC_ENV)) 771 return (0); 772 if (miblen == 6 && /* kern.proc.* */ 773 mib[0] == CTL_KERN && mib[1] == KERN_PROC) 774 return (0); 775 if (miblen == 3 && /* kern.proc_cwd.* */ 776 mib[0] == CTL_KERN && mib[1] == KERN_PROC_CWD) 777 return (0); 778 if (miblen == 2 && /* hw.physmem */ 779 mib[0] == CTL_HW && mib[1] == HW_PHYSMEM64) 780 return (0); 781 if (miblen == 2 && /* kern.ccpu */ 782 mib[0] == CTL_KERN && mib[1] == KERN_CCPU) 783 return (0); 784 if (miblen == 2 && /* vm.maxslp */ 785 mib[0] == CTL_VM && mib[1] == VM_MAXSLP) 786 return (0); 787 } 788 789 if ((p->p_p->ps_pledge & PLEDGE_VMINFO)) { 790 if (miblen == 2 && /* vm.uvmexp */ 791 mib[0] == CTL_VM && mib[1] == VM_UVMEXP) 792 return (0); 793 if (miblen == 3 && /* vfs.generic.bcachestat */ 794 mib[0] == CTL_VFS && mib[1] == VFS_GENERIC && 795 mib[2] == VFS_BCACHESTAT) 796 return (0); 797 } 798 799 if ((p->p_p->ps_pledge & (PLEDGE_ROUTE | PLEDGE_INET | PLEDGE_DNS))) { 800 if (miblen == 6 && /* getifaddrs() */ 801 mib[0] == CTL_NET && mib[1] == PF_ROUTE && 802 mib[2] == 0 && 803 (mib[3] == 0 || mib[3] == AF_INET6 || mib[3] == AF_INET) && 804 mib[4] == NET_RT_IFLIST) 805 return (0); 806 } 807 808 if ((p->p_p->ps_pledge & PLEDGE_DISKLABEL)) { 809 if (miblen == 2 && /* kern.rawpartition */ 810 mib[0] == CTL_KERN && 811 mib[1] == KERN_RAWPARTITION) 812 return (0); 813 if (miblen == 2 && /* kern.maxpartitions */ 814 mib[0] == CTL_KERN && 815 mib[1] == KERN_MAXPARTITIONS) 816 return (0); 817 #ifdef CPU_CHR2BLK 818 if (miblen == 3 && /* machdep.chr2blk */ 819 mib[0] == CTL_MACHDEP && 820 mib[1] == CPU_CHR2BLK) 821 return (0); 822 #endif /* CPU_CHR2BLK */ 823 } 824 825 if (miblen >= 3 && /* ntpd(8) to read sensors */ 826 mib[0] == CTL_HW && mib[1] == HW_SENSORS) 827 return (0); 828 829 if (miblen == 2 && /* getdomainname() */ 830 mib[0] == CTL_KERN && mib[1] == KERN_DOMAINNAME) 831 return (0); 832 if (miblen == 2 && /* gethostname() */ 833 mib[0] == CTL_KERN && mib[1] == KERN_HOSTNAME) 834 return (0); 835 if (miblen == 6 && /* if_nameindex() */ 836 mib[0] == CTL_NET && mib[1] == PF_ROUTE && 837 mib[2] == 0 && mib[3] == 0 && mib[4] == NET_RT_IFNAMES) 838 return (0); 839 if (miblen == 2 && /* uname() */ 840 mib[0] == CTL_KERN && mib[1] == KERN_OSTYPE) 841 return (0); 842 if (miblen == 2 && /* uname() */ 843 mib[0] == CTL_KERN && mib[1] == KERN_OSRELEASE) 844 return (0); 845 if (miblen == 2 && /* uname() */ 846 mib[0] == CTL_KERN && mib[1] == KERN_OSVERSION) 847 return (0); 848 if (miblen == 2 && /* uname() */ 849 mib[0] == CTL_KERN && mib[1] == KERN_VERSION) 850 return (0); 851 if (miblen == 2 && /* kern.clockrate */ 852 mib[0] == CTL_KERN && mib[1] == KERN_CLOCKRATE) 853 return (0); 854 if (miblen == 2 && /* kern.argmax */ 855 mib[0] == CTL_KERN && mib[1] == KERN_ARGMAX) 856 return (0); 857 if (miblen == 2 && /* kern.ngroups */ 858 mib[0] == CTL_KERN && mib[1] == KERN_NGROUPS) 859 return (0); 860 if (miblen == 2 && /* kern.sysvshm */ 861 mib[0] == CTL_KERN && mib[1] == KERN_SYSVSHM) 862 return (0); 863 if (miblen == 2 && /* kern.posix1version */ 864 mib[0] == CTL_KERN && mib[1] == KERN_POSIX1) 865 return (0); 866 if (miblen == 2 && /* uname() */ 867 mib[0] == CTL_HW && mib[1] == HW_MACHINE) 868 return (0); 869 if (miblen == 2 && /* getpagesize() */ 870 mib[0] == CTL_HW && mib[1] == HW_PAGESIZE) 871 return (0); 872 if (miblen == 2 && /* setproctitle() */ 873 mib[0] == CTL_VM && mib[1] == VM_PSSTRINGS) 874 return (0); 875 if (miblen == 2 && /* hw.ncpu */ 876 mib[0] == CTL_HW && mib[1] == HW_NCPU) 877 return (0); 878 if (miblen == 2 && /* vm.loadavg / getloadavg(3) */ 879 mib[0] == CTL_VM && mib[1] == VM_LOADAVG) 880 return (0); 881 882 snprintf(buf, sizeof(buf), "%s(%d): sysctl %d:", 883 p->p_p->ps_comm, p->p_p->ps_pid, miblen); 884 for (i = 0; i < miblen; i++) { 885 char *p = buf + strlen(buf); 886 snprintf(p, sizeof(buf) - (p - buf), " %d", mib[i]); 887 } 888 log(LOG_ERR, "%s\n", buf); 889 890 return pledge_fail(p, EINVAL, 0); 891 } 892 893 int 894 pledge_chown(struct proc *p, uid_t uid, gid_t gid) 895 { 896 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 897 return (0); 898 899 if (p->p_p->ps_pledge & PLEDGE_CHOWNUID) 900 return (0); 901 902 if (uid != -1 && uid != p->p_ucred->cr_uid) 903 return (EPERM); 904 if (gid != -1 && !groupmember(gid, p->p_ucred)) 905 return (EPERM); 906 return (0); 907 } 908 909 int 910 pledge_adjtime(struct proc *p, const void *v) 911 { 912 const struct timeval *delta = v; 913 914 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 915 return (0); 916 917 if ((p->p_p->ps_pledge & PLEDGE_SETTIME)) 918 return (0); 919 if (delta) 920 return (EPERM); 921 return (0); 922 } 923 924 int 925 pledge_sendit(struct proc *p, const void *to) 926 { 927 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 928 return (0); 929 930 if ((p->p_p->ps_pledge & (PLEDGE_INET | PLEDGE_UNIX | PLEDGE_DNS | PLEDGE_YPACTIVE))) 931 return (0); /* may use address */ 932 if (to == NULL) 933 return (0); /* behaves just like write */ 934 return pledge_fail(p, EPERM, PLEDGE_INET); 935 } 936 937 int 938 pledge_ioctl(struct proc *p, long com, struct file *fp) 939 { 940 struct vnode *vp = NULL; 941 int error = EPERM; 942 943 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 944 return (0); 945 946 /* 947 * The ioctl's which are always allowed. 948 */ 949 switch (com) { 950 case FIONREAD: 951 case FIONBIO: 952 case FIOCLEX: 953 case FIONCLEX: 954 return (0); 955 } 956 957 /* fp != NULL was already checked */ 958 if (fp->f_type == DTYPE_VNODE) { 959 vp = fp->f_data; 960 if (vp->v_type == VBAD) 961 return (ENOTTY); 962 } 963 964 if ((p->p_p->ps_pledge & PLEDGE_INET)) { 965 switch (com) { 966 case SIOCATMARK: 967 case SIOCGIFGROUP: 968 if (fp->f_type == DTYPE_SOCKET) 969 return (0); 970 break; 971 } 972 } 973 974 #if NBPFILTER > 0 975 if ((p->p_p->ps_pledge & PLEDGE_BPF)) { 976 switch (com) { 977 case BIOCGSTATS: /* bpf: tcpdump privsep on ^C */ 978 if (fp->f_type == DTYPE_VNODE && 979 fp->f_ops->fo_ioctl == vn_ioctl && 980 vp->v_type == VCHR && 981 cdevsw[major(vp->v_rdev)].d_open == bpfopen) 982 return (0); 983 break; 984 } 985 } 986 #endif /* NBPFILTER > 0 */ 987 988 if ((p->p_p->ps_pledge & PLEDGE_TAPE)) { 989 switch (com) { 990 case MTIOCGET: 991 case MTIOCTOP: 992 /* for pax(1) and such, checking tapes... */ 993 if (fp->f_type == DTYPE_VNODE && 994 vp->v_type == VCHR) { 995 if (vp->v_flag & VISTTY) 996 return (ENOTTY); 997 else 998 return (0); 999 } 1000 break; 1001 } 1002 } 1003 1004 #if NDRM > 0 1005 if ((p->p_p->ps_pledge & PLEDGE_DRM)) { 1006 if ((fp->f_type == DTYPE_VNODE) && 1007 (vp->v_type == VCHR) && 1008 (cdevsw[major(vp->v_rdev)].d_open == drmopen)) { 1009 error = pledge_ioctl_drm(p, com, vp->v_rdev); 1010 if (error == 0) 1011 return 0; 1012 } 1013 } 1014 #endif /* NDRM > 0 */ 1015 1016 #if NAUDIO > 0 1017 if ((p->p_p->ps_pledge & PLEDGE_AUDIO)) { 1018 switch (com) { 1019 case AUDIO_GETPOS: 1020 case AUDIO_GETPAR: 1021 case AUDIO_SETPAR: 1022 case AUDIO_START: 1023 case AUDIO_STOP: 1024 if (fp->f_type == DTYPE_VNODE && 1025 vp->v_type == VCHR && 1026 cdevsw[major(vp->v_rdev)].d_open == audioopen) 1027 return (0); 1028 } 1029 } 1030 #endif /* NAUDIO > 0 */ 1031 1032 if ((p->p_p->ps_pledge & PLEDGE_DISKLABEL)) { 1033 switch (com) { 1034 case DIOCGDINFO: 1035 case DIOCGPDINFO: 1036 case DIOCRLDINFO: 1037 case DIOCWDINFO: 1038 case BIOCDISK: 1039 case BIOCINQ: 1040 case BIOCINSTALLBOOT: 1041 case BIOCVOL: 1042 if (fp->f_type == DTYPE_VNODE && 1043 ((vp->v_type == VCHR && 1044 cdevsw[major(vp->v_rdev)].d_type == D_DISK) || 1045 (vp->v_type == VBLK && 1046 bdevsw[major(vp->v_rdev)].d_type == D_DISK))) 1047 return (0); 1048 break; 1049 case DIOCMAP: 1050 if (fp->f_type == DTYPE_VNODE && 1051 vp->v_type == VCHR && 1052 cdevsw[major(vp->v_rdev)].d_ioctl == diskmapioctl) 1053 return (0); 1054 break; 1055 } 1056 } 1057 1058 #if NPF > 0 1059 if ((p->p_p->ps_pledge & PLEDGE_PF)) { 1060 switch (com) { 1061 case DIOCADDRULE: 1062 case DIOCGETSTATUS: 1063 case DIOCNATLOOK: 1064 case DIOCRADDTABLES: 1065 case DIOCRCLRADDRS: 1066 case DIOCRCLRTABLES: 1067 case DIOCRCLRTSTATS: 1068 case DIOCRGETTSTATS: 1069 case DIOCRSETADDRS: 1070 case DIOCXBEGIN: 1071 case DIOCXCOMMIT: 1072 case DIOCKILLSRCNODES: 1073 if ((fp->f_type == DTYPE_VNODE) && 1074 (vp->v_type == VCHR) && 1075 (cdevsw[major(vp->v_rdev)].d_open == pfopen)) 1076 return (0); 1077 break; 1078 } 1079 } 1080 #endif 1081 1082 if ((p->p_p->ps_pledge & PLEDGE_TTY)) { 1083 switch (com) { 1084 #if NPTY > 0 1085 case PTMGET: 1086 if ((p->p_p->ps_pledge & PLEDGE_RPATH) == 0) 1087 break; 1088 if ((p->p_p->ps_pledge & PLEDGE_WPATH) == 0) 1089 break; 1090 if (fp->f_type != DTYPE_VNODE || vp->v_type != VCHR) 1091 break; 1092 if (cdevsw[major(vp->v_rdev)].d_open != ptmopen) 1093 break; 1094 return (0); 1095 #endif /* NPTY > 0 */ 1096 case TIOCSPGRP: 1097 if ((p->p_p->ps_pledge & PLEDGE_PROC) == 0) 1098 break; 1099 /* FALLTHROUGH */ 1100 case TIOCFLUSH: /* getty, telnet */ 1101 case TIOCGPGRP: 1102 case TIOCGETA: 1103 case TIOCGWINSZ: /* ENOTTY return for non-tty */ 1104 case TIOCSTAT: /* csh */ 1105 if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY)) 1106 return (0); 1107 return (ENOTTY); 1108 case TIOCSWINSZ: 1109 case TIOCEXT: /* mail, libedit .. */ 1110 case TIOCCBRK: /* cu */ 1111 case TIOCSBRK: /* cu */ 1112 case TIOCCDTR: /* cu */ 1113 case TIOCSDTR: /* cu */ 1114 case TIOCEXCL: /* cu */ 1115 case TIOCSETA: /* cu, ... */ 1116 case TIOCSETAW: /* cu, ... */ 1117 case TIOCSETAF: /* tcsetattr TCSAFLUSH, script */ 1118 case TIOCSCTTY: /* forkpty(3), login_tty(3), ... */ 1119 if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY)) 1120 return (0); 1121 break; 1122 } 1123 } 1124 1125 if ((p->p_p->ps_pledge & PLEDGE_ROUTE)) { 1126 switch (com) { 1127 case SIOCGIFADDR: 1128 case SIOCGIFAFLAG_IN6: 1129 case SIOCGIFALIFETIME_IN6: 1130 case SIOCGIFDESCR: 1131 case SIOCGIFFLAGS: 1132 case SIOCGIFMETRIC: 1133 case SIOCGIFGMEMB: 1134 case SIOCGIFRDOMAIN: 1135 case SIOCGIFDSTADDR_IN6: 1136 case SIOCGIFNETMASK_IN6: 1137 case SIOCGIFXFLAGS: 1138 case SIOCGNBRINFO_IN6: 1139 case SIOCGIFINFO_IN6: 1140 case SIOCGIFMEDIA: 1141 if (fp->f_type == DTYPE_SOCKET) 1142 return (0); 1143 break; 1144 } 1145 } 1146 1147 #if NVMM > 0 1148 if ((p->p_p->ps_pledge & PLEDGE_VMM)) { 1149 if ((fp->f_type == DTYPE_VNODE) && 1150 (vp->v_type == VCHR) && 1151 (cdevsw[major(vp->v_rdev)].d_open == vmmopen)) { 1152 error = pledge_ioctl_vmm(p, com); 1153 if (error == 0) 1154 return 0; 1155 } 1156 } 1157 #endif 1158 1159 return pledge_fail(p, error, PLEDGE_TTY); 1160 } 1161 1162 int 1163 pledge_sockopt(struct proc *p, int set, int level, int optname) 1164 { 1165 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 1166 return (0); 1167 1168 /* Always allow these, which are too common to reject */ 1169 switch (level) { 1170 case SOL_SOCKET: 1171 switch (optname) { 1172 case SO_RCVBUF: 1173 case SO_ERROR: 1174 return 0; 1175 } 1176 break; 1177 } 1178 1179 if ((p->p_p->ps_pledge & (PLEDGE_INET|PLEDGE_UNIX|PLEDGE_DNS|PLEDGE_YPACTIVE)) == 0) 1180 return pledge_fail(p, EPERM, PLEDGE_INET); 1181 /* In use by some service libraries */ 1182 switch (level) { 1183 case SOL_SOCKET: 1184 switch (optname) { 1185 case SO_TIMESTAMP: 1186 return 0; 1187 } 1188 break; 1189 } 1190 1191 /* DNS resolver may do these requests */ 1192 if ((p->p_p->ps_pledge & PLEDGE_DNS)) { 1193 switch (level) { 1194 case IPPROTO_IPV6: 1195 switch (optname) { 1196 case IPV6_RECVPKTINFO: 1197 case IPV6_USE_MIN_MTU: 1198 return (0); 1199 } 1200 } 1201 } 1202 1203 /* YP may do these requests */ 1204 if (p->p_p->ps_pledge & PLEDGE_YPACTIVE) { 1205 switch (level) { 1206 case IPPROTO_IP: 1207 switch (optname) { 1208 case IP_PORTRANGE: 1209 return (0); 1210 } 1211 break; 1212 1213 case IPPROTO_IPV6: 1214 switch (optname) { 1215 case IPV6_PORTRANGE: 1216 return (0); 1217 } 1218 break; 1219 } 1220 } 1221 1222 if ((p->p_p->ps_pledge & (PLEDGE_INET|PLEDGE_UNIX)) == 0) 1223 return pledge_fail(p, EPERM, PLEDGE_INET); 1224 switch (level) { 1225 case SOL_SOCKET: 1226 switch (optname) { 1227 case SO_RTABLE: 1228 return pledge_fail(p, EINVAL, PLEDGE_INET); 1229 } 1230 return (0); 1231 } 1232 1233 if ((p->p_p->ps_pledge & PLEDGE_INET) == 0) 1234 return pledge_fail(p, EPERM, PLEDGE_INET); 1235 switch (level) { 1236 case IPPROTO_TCP: 1237 switch (optname) { 1238 case TCP_NODELAY: 1239 case TCP_MD5SIG: 1240 case TCP_SACK_ENABLE: 1241 case TCP_MAXSEG: 1242 case TCP_NOPUSH: 1243 return (0); 1244 } 1245 break; 1246 case IPPROTO_IP: 1247 switch (optname) { 1248 case IP_OPTIONS: 1249 if (!set) 1250 return (0); 1251 break; 1252 case IP_TOS: 1253 case IP_TTL: 1254 case IP_MINTTL: 1255 case IP_IPDEFTTL: 1256 case IP_PORTRANGE: 1257 case IP_RECVDSTADDR: 1258 case IP_RECVDSTPORT: 1259 return (0); 1260 case IP_MULTICAST_IF: 1261 case IP_MULTICAST_TTL: 1262 case IP_MULTICAST_LOOP: 1263 case IP_ADD_MEMBERSHIP: 1264 case IP_DROP_MEMBERSHIP: 1265 if (p->p_p->ps_pledge & PLEDGE_MCAST) 1266 return (0); 1267 break; 1268 } 1269 break; 1270 case IPPROTO_ICMP: 1271 break; 1272 case IPPROTO_IPV6: 1273 switch (optname) { 1274 case IPV6_TCLASS: 1275 case IPV6_UNICAST_HOPS: 1276 case IPV6_MINHOPCOUNT: 1277 case IPV6_RECVHOPLIMIT: 1278 case IPV6_PORTRANGE: 1279 case IPV6_RECVPKTINFO: 1280 case IPV6_RECVDSTPORT: 1281 #ifdef notyet 1282 case IPV6_V6ONLY: 1283 #endif 1284 return (0); 1285 case IPV6_MULTICAST_IF: 1286 case IPV6_MULTICAST_HOPS: 1287 case IPV6_MULTICAST_LOOP: 1288 case IPV6_JOIN_GROUP: 1289 case IPV6_LEAVE_GROUP: 1290 if (p->p_p->ps_pledge & PLEDGE_MCAST) 1291 return (0); 1292 break; 1293 } 1294 break; 1295 case IPPROTO_ICMPV6: 1296 break; 1297 } 1298 return pledge_fail(p, EPERM, PLEDGE_INET); 1299 } 1300 1301 int 1302 pledge_socket(struct proc *p, int domain, int state) 1303 { 1304 if (! ISSET(p->p_p->ps_flags, PS_PLEDGE)) 1305 return 0; 1306 1307 if (ISSET(state, SS_DNS)) { 1308 if (ISSET(p->p_p->ps_pledge, PLEDGE_DNS)) 1309 return 0; 1310 return pledge_fail(p, EPERM, PLEDGE_DNS); 1311 } 1312 1313 switch (domain) { 1314 case -1: /* accept on any domain */ 1315 return (0); 1316 case AF_INET: 1317 case AF_INET6: 1318 if (ISSET(p->p_p->ps_pledge, PLEDGE_INET) || 1319 ISSET(p->p_p->ps_pledge, PLEDGE_YPACTIVE)) 1320 return 0; 1321 return pledge_fail(p, EPERM, PLEDGE_INET); 1322 1323 case AF_UNIX: 1324 if (ISSET(p->p_p->ps_pledge, PLEDGE_UNIX)) 1325 return 0; 1326 return pledge_fail(p, EPERM, PLEDGE_UNIX); 1327 } 1328 1329 return pledge_fail(p, EINVAL, PLEDGE_INET); 1330 } 1331 1332 int 1333 pledge_flock(struct proc *p) 1334 { 1335 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 1336 return (0); 1337 1338 if ((p->p_p->ps_pledge & PLEDGE_FLOCK)) 1339 return (0); 1340 return (pledge_fail(p, EPERM, PLEDGE_FLOCK)); 1341 } 1342 1343 int 1344 pledge_swapctl(struct proc *p) 1345 { 1346 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 1347 return (0); 1348 return (EPERM); 1349 } 1350 1351 /* bsearch over pledgereq. return flags value if found, 0 else */ 1352 uint64_t 1353 pledgereq_flags(const char *req_name) 1354 { 1355 int base = 0, cmp, i, lim; 1356 1357 for (lim = nitems(pledgereq); lim != 0; lim >>= 1) { 1358 i = base + (lim >> 1); 1359 cmp = strcmp(req_name, pledgereq[i].name); 1360 if (cmp == 0) 1361 return (pledgereq[i].flags); 1362 if (cmp > 0) { /* not found before, move right */ 1363 base = i + 1; 1364 lim--; 1365 } /* else move left */ 1366 } 1367 return (0); 1368 } 1369 1370 int 1371 pledge_fcntl(struct proc *p, int cmd) 1372 { 1373 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 1374 return (0); 1375 if ((p->p_p->ps_pledge & PLEDGE_PROC) == 0 && cmd == F_SETOWN) 1376 return pledge_fail(p, EPERM, PLEDGE_PROC); 1377 return (0); 1378 } 1379 1380 int 1381 pledge_kill(struct proc *p, pid_t pid) 1382 { 1383 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 1384 return 0; 1385 if (p->p_p->ps_pledge & PLEDGE_PROC) 1386 return 0; 1387 if (pid == 0 || pid == p->p_p->ps_pid) 1388 return 0; 1389 return pledge_fail(p, EPERM, PLEDGE_PROC); 1390 } 1391 1392 int 1393 pledge_protexec(struct proc *p, int prot) 1394 { 1395 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 1396 return 0; 1397 if (!(p->p_p->ps_pledge & PLEDGE_PROTEXEC) && (prot & PROT_EXEC)) 1398 return pledge_fail(p, EPERM, PLEDGE_PROTEXEC); 1399 return 0; 1400 } 1401 1402 int 1403 canonpath(const char *input, char *buf, size_t bufsize) 1404 { 1405 const char *p; 1406 char *q; 1407 1408 /* can't canon relative paths, don't bother */ 1409 if (input[0] != '/') { 1410 if (strlcpy(buf, input, bufsize) >= bufsize) 1411 return ENAMETOOLONG; 1412 return 0; 1413 } 1414 1415 p = input; 1416 q = buf; 1417 while (*p && (q - buf < bufsize)) { 1418 if (p[0] == '/' && (p[1] == '/' || p[1] == '\0')) { 1419 p += 1; 1420 1421 } else if (p[0] == '/' && p[1] == '.' && 1422 (p[2] == '/' || p[2] == '\0')) { 1423 p += 2; 1424 1425 } else if (p[0] == '/' && p[1] == '.' && p[2] == '.' && 1426 (p[3] == '/' || p[3] == '\0')) { 1427 p += 3; 1428 if (q != buf) /* "/../" at start of buf */ 1429 while (*--q != '/') 1430 continue; 1431 1432 } else { 1433 *q++ = *p++; 1434 } 1435 } 1436 if ((*p == '\0') && (q - buf < bufsize)) { 1437 *q = 0; 1438 return 0; 1439 } else 1440 return ENAMETOOLONG; 1441 } 1442