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