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