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