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