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