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