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