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