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