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