1 /* $OpenBSD: kern_pledge.c,v 1.183 2016/09/17 00:42:35 tedu 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__) 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 * 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 if (fp->f_type == DTYPE_VNODE && 1181 vp->v_type == VCHR && 1182 cdevsw[major(vp->v_rdev)].d_open == audioopen) 1183 return (0); 1184 } 1185 #endif /* NAUDIO > 0 */ 1186 } 1187 1188 if ((p->p_p->ps_pledge & PLEDGE_DISKLABEL)) { 1189 switch (com) { 1190 case DIOCGDINFO: 1191 case DIOCGPDINFO: 1192 case DIOCRLDINFO: 1193 case DIOCWDINFO: 1194 case BIOCDISK: 1195 case BIOCINQ: 1196 case BIOCINSTALLBOOT: 1197 case BIOCVOL: 1198 if (fp->f_type == DTYPE_VNODE && 1199 ((vp->v_type == VCHR && 1200 cdevsw[major(vp->v_rdev)].d_type == D_DISK) || 1201 (vp->v_type == VBLK && 1202 bdevsw[major(vp->v_rdev)].d_type == D_DISK))) 1203 return (0); 1204 break; 1205 case DIOCMAP: 1206 if (fp->f_type == DTYPE_VNODE && 1207 vp->v_type == VCHR && 1208 cdevsw[major(vp->v_rdev)].d_ioctl == diskmapioctl) 1209 return (0); 1210 break; 1211 } 1212 } 1213 1214 if ((p->p_p->ps_pledge & PLEDGE_PF)) { 1215 #if NPF > 0 1216 switch (com) { 1217 case DIOCADDRULE: 1218 case DIOCGETSTATUS: 1219 case DIOCNATLOOK: 1220 case DIOCRADDTABLES: 1221 case DIOCRCLRADDRS: 1222 case DIOCRCLRTABLES: 1223 case DIOCRCLRTSTATS: 1224 case DIOCRGETTSTATS: 1225 case DIOCRSETADDRS: 1226 case DIOCXBEGIN: 1227 case DIOCXCOMMIT: 1228 case DIOCKILLSRCNODES: 1229 if ((fp->f_type == DTYPE_VNODE) && 1230 (vp->v_type == VCHR) && 1231 (cdevsw[major(vp->v_rdev)].d_open == pfopen)) 1232 return (0); 1233 break; 1234 } 1235 #endif 1236 } 1237 1238 if ((p->p_p->ps_pledge & PLEDGE_TTY)) { 1239 switch (com) { 1240 #if NPTY > 0 1241 case PTMGET: 1242 if ((p->p_p->ps_pledge & PLEDGE_RPATH) == 0) 1243 break; 1244 if ((p->p_p->ps_pledge & PLEDGE_WPATH) == 0) 1245 break; 1246 if (fp->f_type != DTYPE_VNODE || vp->v_type != VCHR) 1247 break; 1248 if (cdevsw[major(vp->v_rdev)].d_open != ptmopen) 1249 break; 1250 return (0); 1251 #endif /* NPTY > 0 */ 1252 case TIOCSTI: /* ksh? csh? */ 1253 if ((p->p_p->ps_pledge & PLEDGE_PROC) && 1254 fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY)) 1255 return (0); 1256 break; 1257 case TIOCSPGRP: 1258 if ((p->p_p->ps_pledge & PLEDGE_PROC) == 0) 1259 break; 1260 /* FALLTHROUGH */ 1261 case TIOCFLUSH: /* getty, telnet */ 1262 case TIOCGPGRP: 1263 case TIOCGETA: 1264 case TIOCGWINSZ: /* ENOTTY return for non-tty */ 1265 if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY)) 1266 return (0); 1267 return (ENOTTY); 1268 case TIOCSWINSZ: 1269 case TIOCEXT: /* mail, libedit .. */ 1270 case TIOCCBRK: /* cu */ 1271 case TIOCSBRK: /* cu */ 1272 case TIOCCDTR: /* cu */ 1273 case TIOCSDTR: /* cu */ 1274 case TIOCEXCL: /* cu */ 1275 case TIOCSETA: /* cu, ... */ 1276 case TIOCSETAW: /* cu, ... */ 1277 case TIOCSETAF: /* tcsetattr TCSAFLUSH, script */ 1278 case TIOCSCTTY: /* forkpty(3), login_tty(3), ... */ 1279 if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY)) 1280 return (0); 1281 break; 1282 } 1283 } 1284 1285 if ((p->p_p->ps_pledge & PLEDGE_ROUTE)) { 1286 switch (com) { 1287 case SIOCGIFADDR: 1288 case SIOCGIFFLAGS: 1289 case SIOCGIFMETRIC: 1290 case SIOCGIFGMEMB: 1291 case SIOCGIFRDOMAIN: 1292 case SIOCGIFDSTADDR_IN6: 1293 case SIOCGIFNETMASK_IN6: 1294 case SIOCGNBRINFO_IN6: 1295 case SIOCGIFINFO_IN6: 1296 case SIOCGIFMEDIA: 1297 if (fp->f_type == DTYPE_SOCKET) 1298 return (0); 1299 break; 1300 } 1301 } 1302 1303 if ((p->p_p->ps_pledge & PLEDGE_VMM)) { 1304 #if NVMM > 0 1305 if ((fp->f_type == DTYPE_VNODE) && 1306 (vp->v_type == VCHR) && 1307 (cdevsw[major(vp->v_rdev)].d_open == vmmopen)) { 1308 error = pledge_ioctl_vmm(p, com); 1309 if (error == 0) 1310 return 0; 1311 } 1312 #endif 1313 } 1314 1315 return pledge_fail(p, error, PLEDGE_IOCTL); 1316 } 1317 1318 int 1319 pledge_sockopt(struct proc *p, int set, int level, int optname) 1320 { 1321 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 1322 return (0); 1323 1324 /* Always allow these, which are too common to reject */ 1325 switch (level) { 1326 case SOL_SOCKET: 1327 switch (optname) { 1328 case SO_RCVBUF: 1329 case SO_ERROR: 1330 return 0; 1331 } 1332 break; 1333 } 1334 1335 if ((p->p_p->ps_pledge & (PLEDGE_INET|PLEDGE_UNIX|PLEDGE_DNS|PLEDGE_YPACTIVE)) == 0) 1336 return pledge_fail(p, EPERM, PLEDGE_INET); 1337 /* In use by some service libraries */ 1338 switch (level) { 1339 case SOL_SOCKET: 1340 switch (optname) { 1341 case SO_TIMESTAMP: 1342 return 0; 1343 } 1344 break; 1345 } 1346 1347 /* DNS resolver may do these requests */ 1348 if ((p->p_p->ps_pledge & PLEDGE_DNS)) { 1349 switch (level) { 1350 case IPPROTO_IPV6: 1351 switch (optname) { 1352 case IPV6_RECVPKTINFO: 1353 case IPV6_USE_MIN_MTU: 1354 return (0); 1355 } 1356 } 1357 } 1358 1359 /* YP may do these requests */ 1360 if (p->p_p->ps_pledge & PLEDGE_YPACTIVE) { 1361 switch (level) { 1362 case IPPROTO_IP: 1363 switch (optname) { 1364 case IP_PORTRANGE: 1365 return (0); 1366 } 1367 break; 1368 1369 case IPPROTO_IPV6: 1370 switch (optname) { 1371 case IPV6_PORTRANGE: 1372 return (0); 1373 } 1374 break; 1375 } 1376 } 1377 1378 if ((p->p_p->ps_pledge & (PLEDGE_INET|PLEDGE_UNIX)) == 0) 1379 return pledge_fail(p, EPERM, PLEDGE_INET); 1380 switch (level) { 1381 case SOL_SOCKET: 1382 switch (optname) { 1383 case SO_RTABLE: 1384 return pledge_fail(p, EINVAL, PLEDGE_INET); 1385 } 1386 return (0); 1387 } 1388 1389 if ((p->p_p->ps_pledge & PLEDGE_INET) == 0) 1390 return pledge_fail(p, EPERM, PLEDGE_INET); 1391 switch (level) { 1392 case IPPROTO_TCP: 1393 switch (optname) { 1394 case TCP_NODELAY: 1395 case TCP_MD5SIG: 1396 case TCP_SACK_ENABLE: 1397 case TCP_MAXSEG: 1398 case TCP_NOPUSH: 1399 return (0); 1400 } 1401 break; 1402 case IPPROTO_IP: 1403 switch (optname) { 1404 case IP_OPTIONS: 1405 if (!set) 1406 return (0); 1407 break; 1408 case IP_TOS: 1409 case IP_TTL: 1410 case IP_MINTTL: 1411 case IP_IPDEFTTL: 1412 case IP_PORTRANGE: 1413 case IP_RECVDSTADDR: 1414 case IP_RECVDSTPORT: 1415 return (0); 1416 case IP_MULTICAST_IF: 1417 case IP_ADD_MEMBERSHIP: 1418 case IP_DROP_MEMBERSHIP: 1419 if (p->p_p->ps_pledge & PLEDGE_MCAST) 1420 return (0); 1421 break; 1422 } 1423 break; 1424 case IPPROTO_ICMP: 1425 break; 1426 case IPPROTO_IPV6: 1427 switch (optname) { 1428 case IPV6_TCLASS: 1429 case IPV6_UNICAST_HOPS: 1430 case IPV6_MINHOPCOUNT: 1431 case IPV6_RECVHOPLIMIT: 1432 case IPV6_PORTRANGE: 1433 case IPV6_RECVPKTINFO: 1434 case IPV6_RECVDSTPORT: 1435 #ifdef notyet 1436 case IPV6_V6ONLY: 1437 #endif 1438 return (0); 1439 case IPV6_MULTICAST_IF: 1440 case IPV6_JOIN_GROUP: 1441 case IPV6_LEAVE_GROUP: 1442 if (p->p_p->ps_pledge & PLEDGE_MCAST) 1443 return (0); 1444 break; 1445 } 1446 break; 1447 case IPPROTO_ICMPV6: 1448 break; 1449 } 1450 return pledge_fail(p, EPERM, PLEDGE_INET); 1451 } 1452 1453 int 1454 pledge_socket(struct proc *p, int domain, int state) 1455 { 1456 if (! ISSET(p->p_p->ps_flags, PS_PLEDGE)) 1457 return 0; 1458 1459 if (ISSET(state, SS_DNS)) { 1460 if (ISSET(p->p_p->ps_pledge, PLEDGE_DNS)) 1461 return 0; 1462 return pledge_fail(p, EPERM, PLEDGE_DNS); 1463 } 1464 1465 switch (domain) { 1466 case -1: /* accept on any domain */ 1467 return (0); 1468 case AF_INET: 1469 case AF_INET6: 1470 if (ISSET(p->p_p->ps_pledge, PLEDGE_INET) || 1471 ISSET(p->p_p->ps_pledge, PLEDGE_YPACTIVE)) 1472 return 0; 1473 return pledge_fail(p, EPERM, PLEDGE_INET); 1474 1475 case AF_UNIX: 1476 if (ISSET(p->p_p->ps_pledge, PLEDGE_UNIX)) 1477 return 0; 1478 return pledge_fail(p, EPERM, PLEDGE_UNIX); 1479 } 1480 1481 return pledge_fail(p, EINVAL, PLEDGE_INET); 1482 } 1483 1484 int 1485 pledge_flock(struct proc *p) 1486 { 1487 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 1488 return (0); 1489 1490 if ((p->p_p->ps_pledge & PLEDGE_FLOCK)) 1491 return (0); 1492 return (pledge_fail(p, EPERM, PLEDGE_FLOCK)); 1493 } 1494 1495 int 1496 pledge_swapctl(struct proc *p) 1497 { 1498 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 1499 return (0); 1500 return (EPERM); 1501 } 1502 1503 /* bsearch over pledgereq. return flags value if found, 0 else */ 1504 uint64_t 1505 pledgereq_flags(const char *req_name) 1506 { 1507 int base = 0, cmp, i, lim; 1508 1509 for (lim = nitems(pledgereq); lim != 0; lim >>= 1) { 1510 i = base + (lim >> 1); 1511 cmp = strcmp(req_name, pledgereq[i].name); 1512 if (cmp == 0) 1513 return (pledgereq[i].flags); 1514 if (cmp > 0) { /* not found before, move right */ 1515 base = i + 1; 1516 lim--; 1517 } /* else move left */ 1518 } 1519 return (0); 1520 } 1521 1522 int 1523 pledge_fcntl(struct proc *p, int cmd) 1524 { 1525 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 1526 return (0); 1527 if ((p->p_p->ps_pledge & PLEDGE_PROC) == 0 && cmd == F_SETOWN) 1528 return pledge_fail(p, EPERM, PLEDGE_PROC); 1529 return (0); 1530 } 1531 1532 int 1533 pledge_kill(struct proc *p, pid_t pid) 1534 { 1535 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 1536 return 0; 1537 if (p->p_p->ps_pledge & PLEDGE_PROC) 1538 return 0; 1539 if (pid == 0 || pid == p->p_p->ps_pid) 1540 return 0; 1541 return pledge_fail(p, EPERM, PLEDGE_PROC); 1542 } 1543 1544 int 1545 pledge_protexec(struct proc *p, int prot) 1546 { 1547 if ((p->p_p->ps_flags & PS_PLEDGE) == 0) 1548 return 0; 1549 if (!(p->p_p->ps_pledge & PLEDGE_PROTEXEC) && (prot & PROT_EXEC)) 1550 return pledge_fail(p, EPERM, PLEDGE_PROTEXEC); 1551 return 0; 1552 } 1553 1554 void 1555 pledge_dropwpaths(struct process *pr) 1556 { 1557 if (pr->ps_pledgepaths && --pr->ps_pledgepaths->wl_ref == 0) { 1558 struct whitepaths *wl = pr->ps_pledgepaths; 1559 int i; 1560 1561 for (i = 0; i < wl->wl_count; i++) 1562 free(wl->wl_paths[i].name, M_TEMP, wl->wl_paths[i].len); 1563 free(wl, M_TEMP, wl->wl_size); 1564 } 1565 pr->ps_pledgepaths = NULL; 1566 } 1567 1568 int 1569 canonpath(const char *input, char *buf, size_t bufsize) 1570 { 1571 const char *p; 1572 char *q; 1573 1574 /* can't canon relative paths, don't bother */ 1575 if (input[0] != '/') { 1576 if (strlcpy(buf, input, bufsize) >= bufsize) 1577 return ENAMETOOLONG; 1578 return 0; 1579 } 1580 1581 p = input; 1582 q = buf; 1583 while (*p && (q - buf < bufsize)) { 1584 if (p[0] == '/' && (p[1] == '/' || p[1] == '\0')) { 1585 p += 1; 1586 1587 } else if (p[0] == '/' && p[1] == '.' && 1588 (p[2] == '/' || p[2] == '\0')) { 1589 p += 2; 1590 1591 } else if (p[0] == '/' && p[1] == '.' && p[2] == '.' && 1592 (p[3] == '/' || p[3] == '\0')) { 1593 p += 3; 1594 if (q != buf) /* "/../" at start of buf */ 1595 while (*--q != '/') 1596 continue; 1597 1598 } else { 1599 *q++ = *p++; 1600 } 1601 } 1602 if ((*p == '\0') && (q - buf < bufsize)) { 1603 *q = 0; 1604 return 0; 1605 } else 1606 return ENAMETOOLONG; 1607 } 1608 1609 int 1610 substrcmp(const char *p1, size_t s1, const char *p2, size_t s2) 1611 { 1612 size_t i; 1613 for (i = 0; i < s1 || i < s2; i++) { 1614 if (p1[i] != p2[i]) 1615 break; 1616 } 1617 if (i == s1) { 1618 return (1); /* string1 is a subpath of string2 */ 1619 } else if (i == s2) 1620 return (2); /* string2 is a subpath of string1 */ 1621 else 1622 return (0); /* no subpath */ 1623 } 1624 1625 int 1626 resolvpath(struct proc *p, 1627 char **rdir, size_t *rdirlen, 1628 char **cwd, size_t *cwdlen, 1629 char *path, size_t pathlen, 1630 char **resolved, size_t *resolvedlen) 1631 { 1632 int error; 1633 char *abspath = NULL, *canopath = NULL, *fullpath = NULL; 1634 size_t abspathlen, canopathlen = 0, fullpathlen = 0, canopathlen_exact; 1635 1636 /* 1. get an absolute path (inside any chroot) : path -> abspath */ 1637 if (path[0] != '/') { 1638 /* path is relative: prepend cwd */ 1639 1640 /* get cwd first (if needed) */ 1641 if (*cwd == NULL) { 1642 char *rawcwd, *bp, *bpend; 1643 size_t rawcwdlen = MAXPATHLEN * 4; 1644 1645 rawcwd = malloc(rawcwdlen, M_TEMP, M_WAITOK); 1646 bp = &rawcwd[rawcwdlen]; 1647 bpend = bp; 1648 *(--bp) = '\0'; 1649 1650 error = vfs_getcwd_common(p->p_fd->fd_cdir, 1651 NULL, &bp, rawcwd, rawcwdlen/2, 1652 GETCWD_CHECK_ACCESS, p); 1653 if (error) { 1654 free(rawcwd, M_TEMP, rawcwdlen); 1655 goto out; 1656 } 1657 1658 /* NUL is included */ 1659 *cwdlen = (bpend - bp); 1660 *cwd = malloc(*cwdlen, M_TEMP, M_WAITOK); 1661 memcpy(*cwd, bp, *cwdlen); 1662 1663 free(rawcwd, M_TEMP, rawcwdlen); 1664 } 1665 1666 /* NUL included in *cwdlen and pathlen */ 1667 abspathlen = *cwdlen + pathlen; 1668 abspath = malloc(abspathlen, M_TEMP, M_WAITOK); 1669 snprintf(abspath, abspathlen, "%s/%s", *cwd, path); 1670 1671 } else { 1672 /* path is absolute */ 1673 abspathlen = pathlen; 1674 abspath = malloc(abspathlen, M_TEMP, M_WAITOK); 1675 memcpy(abspath, path, pathlen); 1676 } 1677 1678 /* 2. canonization: abspath -> canopath */ 1679 canopathlen = abspathlen; 1680 canopath = malloc(canopathlen, M_TEMP, M_WAITOK); 1681 error = canonpath(abspath, canopath, canopathlen); 1682 1683 /* free abspath now as we don't need it after */ 1684 free(abspath, M_TEMP, abspathlen); 1685 1686 /* error in canonpath() call (should not happen, but keep safe) */ 1687 if (error != 0) 1688 goto out; 1689 1690 /* check the canopath size */ 1691 canopathlen_exact = strlen(canopath) + 1; 1692 if (canopathlen_exact > MAXPATHLEN) { 1693 error = ENAMETOOLONG; 1694 goto out; 1695 } 1696 1697 /* 3. preprend *rdir if chrooted : canonpath -> fullpath */ 1698 if (p->p_fd->fd_rdir != NULL) { 1699 if (*rdir == NULL) { 1700 char *rawrdir, *bp, *bpend; 1701 size_t rawrdirlen = MAXPATHLEN * 4; 1702 1703 rawrdir = malloc(rawrdirlen, M_TEMP, M_WAITOK); 1704 bp = &rawrdir[rawrdirlen]; 1705 bpend = bp; 1706 *(--bp) = '\0'; 1707 1708 error = vfs_getcwd_common(p->p_fd->fd_rdir, 1709 rootvnode, &bp, rawrdir, rawrdirlen/2, 1710 GETCWD_CHECK_ACCESS, p); 1711 if (error) { 1712 free(rawrdir, M_TEMP, rawrdirlen); 1713 goto out; 1714 } 1715 1716 /* NUL is included */ 1717 *rdirlen = (bpend - bp); 1718 *rdir = malloc(*rdirlen, M_TEMP, M_WAITOK); 1719 memcpy(*rdir, bp, *rdirlen); 1720 1721 free(rawrdir, M_TEMP, rawrdirlen); 1722 } 1723 1724 /* 1725 * NUL is included in *rdirlen and canopathlen_exact. 1726 * doesn't add "/" between them, as canopath is absolute. 1727 */ 1728 fullpathlen = *rdirlen + canopathlen_exact - 1; 1729 fullpath = malloc(fullpathlen, M_TEMP, M_WAITOK); 1730 snprintf(fullpath, fullpathlen, "%s%s", *rdir, canopath); 1731 1732 } else { 1733 /* not chrooted: only reduce canopath to exact length */ 1734 fullpathlen = canopathlen_exact; 1735 fullpath = malloc(fullpathlen, M_TEMP, M_WAITOK); 1736 memcpy(fullpath, canopath, fullpathlen); 1737 } 1738 1739 *resolvedlen = fullpathlen; 1740 *resolved = fullpath; 1741 1742 out: 1743 free(canopath, M_TEMP, canopathlen); 1744 if (error != 0) 1745 free(fullpath, M_TEMP, fullpathlen); 1746 return error; 1747 } 1748