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