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