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