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