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