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