1 /* $OpenBSD: kern_unveil.c,v 1.39 2020/03/22 20:23:36 anton Exp $ */ 2 3 /* 4 * Copyright (c) 2017-2019 Bob Beck <beck@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 21 #include <sys/acct.h> 22 #include <sys/mount.h> 23 #include <sys/filedesc.h> 24 #include <sys/proc.h> 25 #include <sys/namei.h> 26 #include <sys/pool.h> 27 #include <sys/vnode.h> 28 #include <sys/ktrace.h> 29 #include <sys/types.h> 30 #include <sys/malloc.h> 31 #include <sys/tree.h> 32 #include <sys/lock.h> 33 34 #include <sys/conf.h> 35 #include <sys/syscall.h> 36 #include <sys/syscallargs.h> 37 #include <sys/systm.h> 38 39 #include <sys/pledge.h> 40 41 struct unvname { 42 char *un_name; 43 size_t un_namesize; 44 u_char un_flags; 45 RBT_ENTRY(unvnmae) un_rbt; 46 }; 47 48 RBT_HEAD(unvname_rbt, unvname); 49 50 struct unveil { 51 struct vnode *uv_vp; 52 ssize_t uv_cover; 53 struct unvname_rbt uv_names; 54 struct rwlock uv_lock; 55 u_char uv_flags; 56 }; 57 58 /* #define DEBUG_UNVEIL */ 59 60 #define UNVEIL_MAX_VNODES 128 61 #define UNVEIL_MAX_NAMES 128 62 63 static inline int 64 unvname_compare(const struct unvname *n1, const struct unvname *n2) 65 { 66 if (n1->un_namesize == n2->un_namesize) 67 return (memcmp(n1->un_name, n2->un_name, n1->un_namesize)); 68 else 69 return (n1->un_namesize - n2->un_namesize); 70 } 71 72 struct unvname * 73 unvname_new(const char *name, size_t size, u_char flags) 74 { 75 struct unvname *ret = malloc(sizeof(struct unvname), M_PROC, M_WAITOK); 76 ret->un_name = malloc(size, M_PROC, M_WAITOK); 77 memcpy(ret->un_name, name, size); 78 ret->un_namesize = size; 79 ret->un_flags = flags; 80 return ret; 81 } 82 83 void 84 unveil_free_traversed_vnodes(struct nameidata *ndp) 85 { 86 if (ndp->ni_tvpsize) { 87 size_t i; 88 89 for (i = 0; i < ndp->ni_tvpend; i++) 90 vrele(ndp->ni_tvp[i]); /* ref for being in list */ 91 free(ndp->ni_tvp, M_PROC, ndp->ni_tvpsize * 92 sizeof(struct vnode *)); 93 ndp->ni_tvpsize = 0; 94 ndp->ni_tvpend = 0; 95 } 96 } 97 98 void 99 unveil_save_traversed_vnode(struct nameidata *ndp, struct vnode *vp) 100 { 101 if (ndp->ni_tvpsize == 0) { 102 ndp->ni_tvp = mallocarray(MAXPATHLEN, sizeof(struct vnode *), 103 M_PROC, M_WAITOK); 104 ndp->ni_tvpsize = MAXPATHLEN; 105 } 106 /* This should be limited by MAXPATHLEN on a single lookup */ 107 KASSERT(ndp->ni_tvpsize > ndp->ni_tvpend); 108 vref(vp); /* ref for being in the list */ 109 ndp->ni_tvp[ndp->ni_tvpend++] = vp; 110 } 111 112 void 113 unvname_delete(struct unvname *name) 114 { 115 free(name->un_name, M_PROC, name->un_namesize); 116 free(name, M_PROC, sizeof(struct unvname)); 117 } 118 119 RBT_PROTOTYPE(unvname_rbt, unvname, un_rbt, unvname_compare); 120 RBT_GENERATE(unvname_rbt, unvname, un_rbt, unvname_compare); 121 122 int 123 unveil_delete_names(struct unveil *uv) 124 { 125 struct unvname *unvn, *next; 126 int ret = 0; 127 128 rw_enter_write(&uv->uv_lock); 129 RBT_FOREACH_SAFE(unvn, unvname_rbt, &uv->uv_names, next) { 130 RBT_REMOVE(unvname_rbt, &uv->uv_names, unvn); 131 unvname_delete(unvn); 132 ret++; 133 } 134 rw_exit_write(&uv->uv_lock); 135 #ifdef DEBUG_UNVEIL 136 printf("deleted %d names\n", ret); 137 #endif 138 return ret; 139 } 140 141 int 142 unveil_add_name_unlocked(struct unveil *uv, char *name, u_char flags) 143 { 144 struct unvname *unvn; 145 146 unvn = unvname_new(name, strlen(name) + 1, flags); 147 if (RBT_INSERT(unvname_rbt, &uv->uv_names, unvn) != NULL) { 148 /* Name already present. */ 149 unvname_delete(unvn); 150 return 0; 151 } 152 #ifdef DEBUG_UNVEIL 153 printf("added name %s underneath vnode %p\n", name, uv->uv_vp); 154 #endif 155 return 1; 156 } 157 158 int 159 unveil_add_name(struct unveil *uv, char *name, u_char flags) 160 { 161 int ret; 162 163 rw_enter_write(&uv->uv_lock); 164 ret = unveil_add_name_unlocked(uv, name, flags); 165 rw_exit_write(&uv->uv_lock); 166 return ret; 167 } 168 169 struct unvname * 170 unveil_namelookup(struct unveil *uv, char *name) 171 { 172 struct unvname n, *ret = NULL; 173 174 rw_enter_read(&uv->uv_lock); 175 176 #ifdef DEBUG_UNVEIL 177 printf("unveil_namelookup: looking up name %s (%p) in vnode %p\n", 178 name, name, uv->uv_vp); 179 #endif 180 181 KASSERT(uv->uv_vp != NULL); 182 183 n.un_name = name; 184 n.un_namesize = strlen(name) + 1; 185 186 ret = RBT_FIND(unvname_rbt, &uv->uv_names, &n); 187 188 rw_exit_read(&uv->uv_lock); 189 190 #ifdef DEBUG_UNVEIL 191 if (ret == NULL) 192 printf("unveil_namelookup: no match for name %s in vnode %p\n", 193 name, uv->uv_vp); 194 else 195 printf("unveil_namelookup: matched name %s in vnode %p\n", 196 name, uv->uv_vp); 197 #endif 198 return ret; 199 } 200 201 void 202 unveil_destroy(struct process *ps) 203 { 204 size_t i; 205 206 for (i = 0; ps->ps_uvpaths != NULL && i < ps->ps_uvvcount; i++) { 207 struct unveil *uv = ps->ps_uvpaths + i; 208 209 struct vnode *vp = uv->uv_vp; 210 /* skip any vnodes zapped by unveil_removevnode */ 211 if (vp != NULL) { 212 vp->v_uvcount--; 213 #ifdef DEBUG_UNVEIL 214 printf("unveil: %s(%d): removing vnode %p uvcount %d " 215 "in position %ld\n", 216 ps->ps_comm, ps->ps_pid, vp, vp->v_uvcount, i); 217 #endif 218 vrele(vp); 219 } 220 ps->ps_uvncount -= unveil_delete_names(uv); 221 uv->uv_vp = NULL; 222 uv->uv_flags = 0; 223 } 224 225 KASSERT(ps->ps_uvncount == 0); 226 free(ps->ps_uvpaths, M_PROC, UNVEIL_MAX_VNODES * 227 sizeof(struct unveil)); 228 ps->ps_uvvcount = 0; 229 ps->ps_uvpaths = NULL; 230 ps->ps_uvpcwd = NULL; 231 } 232 233 void 234 unveil_copy(struct process *parent, struct process *child) 235 { 236 size_t i; 237 238 if (parent->ps_uvvcount == 0) 239 return; 240 241 child->ps_uvpaths = mallocarray(UNVEIL_MAX_VNODES, 242 sizeof(struct unveil), M_PROC, M_WAITOK|M_ZERO); 243 244 child->ps_uvncount = 0; 245 for (i = 0; parent->ps_uvpaths != NULL && i < parent->ps_uvvcount; 246 i++) { 247 struct unveil *from = parent->ps_uvpaths + i; 248 struct unveil *to = child->ps_uvpaths + i; 249 struct unvname *unvn, *next; 250 251 to->uv_vp = from->uv_vp; 252 if (to->uv_vp != NULL) { 253 vref(to->uv_vp); 254 to->uv_vp->v_uvcount++; 255 } 256 rw_init(&to->uv_lock, "unveil"); 257 RBT_INIT(unvname_rbt, &to->uv_names); 258 rw_enter_read(&from->uv_lock); 259 RBT_FOREACH_SAFE(unvn, unvname_rbt, &from->uv_names, next) { 260 if (unveil_add_name_unlocked(&child->ps_uvpaths[i], 261 unvn->un_name, unvn->un_flags)) 262 child->ps_uvncount++; 263 } 264 rw_exit_read(&from->uv_lock); 265 to->uv_flags = from->uv_flags; 266 to->uv_cover = from->uv_cover; 267 } 268 child->ps_uvvcount = parent->ps_uvvcount; 269 if (parent->ps_uvpcwd) 270 child->ps_uvpcwd = child->ps_uvpaths + 271 (parent->ps_uvpcwd - parent->ps_uvpaths); 272 child->ps_uvdone = parent->ps_uvdone; 273 child->ps_uvshrink = parent->ps_uvshrink; 274 } 275 276 /* 277 * Walk up from vnode dp, until we find a matching unveil, or the root vnode 278 * returns -1 if no unveil to be found above dp. 279 */ 280 ssize_t 281 unveil_find_cover(struct vnode *dp, struct proc *p) 282 { 283 struct vnode *vp = NULL, *parent = NULL, *root; 284 ssize_t ret = -1; 285 int error; 286 287 /* use the correct root to stop at, chrooted or not.. */ 288 root = p->p_fd->fd_rdir ? p->p_fd->fd_rdir : rootvnode; 289 vp = dp; 290 291 do { 292 struct componentname cn = { 293 .cn_nameiop = LOOKUP, 294 .cn_flags = ISLASTCN | ISDOTDOT | RDONLY, 295 .cn_proc = p, 296 .cn_cred = p->p_ucred, 297 .cn_pnbuf = NULL, 298 .cn_nameptr = "..", 299 .cn_namelen = 2, 300 .cn_consume = 0 301 }; 302 303 /* 304 * If we are at the root of a filesystem, and we are 305 * still mounted somewhere, take the .. in the above 306 * filesystem. 307 */ 308 if (vp != root && (vp->v_flag & VROOT)) { 309 if (vp->v_mount == NULL) 310 return -1; 311 vp = vp->v_mount->mnt_vnodecovered ? 312 vp->v_mount->mnt_vnodecovered : vp; 313 } 314 315 if (vget(vp, LK_EXCLUSIVE|LK_RETRY) != 0) 316 return -1; 317 /* Get parent vnode of vp using lookup of '..' */ 318 /* This returns with vp unlocked but ref'ed*/ 319 error = VOP_LOOKUP(vp, &parent, &cn); 320 if (error) { 321 if (!(cn.cn_flags & PDIRUNLOCK)) 322 vput(vp); 323 else { 324 /* 325 * This corner case should not happen because 326 * we have not set LOCKPARENT in the flags 327 */ 328 printf("vnode %p PDIRUNLOCK on error\n", vp); 329 vrele(vp); 330 } 331 break; 332 } 333 334 vrele(vp); 335 (void) unveil_lookup(parent, p->p_p, &ret); 336 vput(parent); 337 338 if (ret >= 0) 339 break; 340 341 if (vp == parent) { 342 ret = -1; 343 break; 344 } 345 vp = parent; 346 parent = NULL; 347 } while (vp != root); 348 return ret; 349 } 350 351 352 struct unveil * 353 unveil_lookup(struct vnode *vp, struct process *pr, ssize_t *position) 354 { 355 struct unveil *uv = pr->ps_uvpaths; 356 ssize_t l, r; 357 if (position != NULL) 358 *position = -1; 359 360 if (vp->v_uvcount == 0) 361 return NULL; 362 363 /* 364 * shrink if told to do so to remove dead vnodes. 365 */ 366 if (pr->ps_uvshrink) { 367 size_t i = 0, j; 368 369 while (i < pr->ps_uvvcount) { 370 if (uv[i].uv_vp == NULL) { 371 pr->ps_uvncount -= unveil_delete_names(&uv[i]); 372 for (j = i + 1; j < pr->ps_uvvcount; j++) 373 uv[j - 1] = uv[j]; 374 pr->ps_uvvcount--; 375 for (j = 0; j < pr->ps_uvvcount; j++) { 376 if (uv[j].uv_cover == i) { 377 /* 378 * anything covered by 379 * this one will be nuked 380 * on unmount as well. 381 */ 382 uv[j].uv_cover = -1; 383 } 384 else if (uv[j].uv_cover > i) 385 uv[j].uv_cover--; 386 } 387 } 388 i++; 389 } 390 pr->ps_uvshrink = 0; 391 } 392 393 if (pr->ps_uvvcount == 0) 394 return NULL; 395 396 l = 0; 397 r = pr->ps_uvvcount - 1; 398 while (l <= r) { 399 size_t m = l + (r - l)/2; 400 #ifdef DEBUG_UNVEIL 401 printf("unveil: checking vnode %p vs. unveil vnode %p\n", 402 vp, uv[m].uv_vp); 403 #endif 404 if (vp == uv[m].uv_vp) { 405 KASSERT(uv[m].uv_vp->v_uvcount > 0); 406 KASSERT(uv[m].uv_vp->v_usecount > 0); 407 if (position != NULL) 408 *position = m; 409 return &uv[m]; 410 } 411 if (vp > uv[m].uv_vp) 412 l = m + 1; 413 else 414 r = m - 1; 415 } 416 return NULL; 417 } 418 419 int 420 unveil_parsepermissions(const char *permissions, u_char *perms) 421 { 422 size_t i = 0; 423 char c; 424 425 *perms = 0; 426 while ((c = permissions[i++]) != '\0') { 427 switch (c) { 428 case 'r': 429 *perms |= UNVEIL_READ; 430 break; 431 case 'w': 432 *perms |= UNVEIL_WRITE; 433 break; 434 case 'x': 435 *perms |= UNVEIL_EXEC; 436 break; 437 case 'c': 438 *perms |= UNVEIL_CREATE; 439 break; 440 default: 441 return -1; 442 } 443 } 444 return 0; 445 } 446 447 int 448 unveil_setflags(u_char *flags, u_char nflags) 449 { 450 #if 0 451 if (((~(*flags)) & nflags) != 0) { 452 #ifdef DEBUG_UNVEIL 453 printf("Flags escalation %llX -> %llX\n", *flags, nflags); 454 #endif 455 return 1; 456 } 457 #endif 458 *flags = nflags; 459 return 1; 460 } 461 462 struct unveil * 463 unveil_add_vnode(struct proc *p, struct vnode *vp) 464 { 465 struct process *pr = p->p_p; 466 struct unveil *uv = NULL; 467 ssize_t i, j; 468 469 KASSERT(pr->ps_uvvcount < UNVEIL_MAX_VNODES); 470 471 for (i = pr->ps_uvvcount; 472 i > 0 && pr->ps_uvpaths[i - 1].uv_vp > vp; 473 i--) { 474 pr->ps_uvpaths[i] = pr->ps_uvpaths[i - 1]; 475 } 476 477 /* adjust the covers to account for our addition */ 478 for (j = 0; j < pr->ps_uvvcount; j++) { 479 if (pr->ps_uvpaths[i].uv_cover >= i) 480 pr->ps_uvpaths[i].uv_cover++; 481 } 482 483 uv = &pr->ps_uvpaths[i]; 484 rw_init(&uv->uv_lock, "unveil"); 485 RBT_INIT(unvname_rbt, &uv->uv_names); 486 uv->uv_vp = vp; 487 488 /* 489 * Added vnodes are added with the UNVEIL_INSPECT flag 490 * to allow operations such as access and stat. This lets 491 * TOCTOU fans that call access on all components of 492 * an unveil'ed path before the final operations 493 * work. 494 */ 495 uv->uv_flags = UNVEIL_INSPECT; 496 pr->ps_uvvcount++; 497 498 /* find out what we are covered by */ 499 uv->uv_cover = unveil_find_cover(vp, p); 500 501 /* 502 * Find anyone covered by what we are covered by 503 * and re-check what covers them (we could have 504 * interposed a cover) 505 */ 506 for (j = 0; j < pr->ps_uvvcount; j++) { 507 if (pr->ps_uvpaths[i].uv_cover == uv->uv_cover) 508 pr->ps_uvpaths[j].uv_cover = 509 unveil_find_cover(pr->ps_uvpaths[j].uv_vp, p); 510 } 511 512 return (uv); 513 } 514 515 void 516 unveil_add_traversed_vnodes(struct proc *p, struct nameidata *ndp) 517 { 518 if (ndp->ni_tvpsize) { 519 size_t i; 520 521 for (i = 0; i < ndp->ni_tvpend; i++) { 522 struct vnode *vp = ndp->ni_tvp[i]; 523 if (unveil_lookup(vp, p->p_p, NULL) == NULL) { 524 vref(vp); 525 vp->v_uvcount++; 526 unveil_add_vnode(p, vp); 527 } 528 } 529 } 530 } 531 532 int 533 unveil_add(struct proc *p, struct nameidata *ndp, const char *permissions) 534 { 535 struct process *pr = p->p_p; 536 struct vnode *vp; 537 struct unveil *uv; 538 int directory_add; 539 int ret = EINVAL; 540 u_char flags; 541 542 KASSERT(ISSET(ndp->ni_cnd.cn_flags, HASBUF)); /* must have SAVENAME */ 543 544 if (unveil_parsepermissions(permissions, &flags) == -1) 545 goto done; 546 547 if (pr->ps_uvpaths == NULL) { 548 pr->ps_uvpaths = mallocarray(UNVEIL_MAX_VNODES, 549 sizeof(struct unveil), M_PROC, M_WAITOK|M_ZERO); 550 } 551 552 if ((pr->ps_uvvcount + ndp->ni_tvpend) >= UNVEIL_MAX_VNODES || 553 pr->ps_uvncount >= UNVEIL_MAX_NAMES) { 554 ret = E2BIG; 555 goto done; 556 } 557 558 /* Are we a directory? or something else */ 559 directory_add = ndp->ni_vp != NULL && ndp->ni_vp->v_type == VDIR; 560 561 if (directory_add) 562 vp = ndp->ni_vp; 563 else 564 vp = ndp->ni_dvp; 565 566 KASSERT(vp->v_type == VDIR); 567 vref(vp); 568 vp->v_uvcount++; 569 if ((uv = unveil_lookup(vp, pr, NULL)) != NULL) { 570 /* 571 * We already have unveiled this directory 572 * vnode 573 */ 574 vp->v_uvcount--; 575 vrele(vp); 576 577 /* 578 * If we are adding a directory which was already 579 * unveiled containing only specific terminals, 580 * unrestrict it. 581 */ 582 if (directory_add) { 583 #ifdef DEBUG_UNVEIL 584 printf("unveil: %s(%d): updating directory vnode %p" 585 " to unrestricted uvcount %d\n", 586 pr->ps_comm, pr->ps_pid, vp, vp->v_uvcount); 587 #endif 588 if (!unveil_setflags(&uv->uv_flags, flags)) 589 ret = EPERM; 590 else 591 ret = 0; 592 goto done; 593 } 594 595 /* 596 * If we are adding a terminal that is already unveiled, just 597 * replace the flags and we are done 598 */ 599 if (!directory_add) { 600 struct unvname *tname; 601 if ((tname = unveil_namelookup(uv, 602 ndp->ni_cnd.cn_nameptr)) != NULL) { 603 #ifdef DEBUG_UNVEIL 604 printf("unveil: %s(%d): changing flags for %s" 605 "in vnode %p, uvcount %d\n", 606 pr->ps_comm, pr->ps_pid, tname->un_name, vp, 607 vp->v_uvcount); 608 #endif 609 if (!unveil_setflags(&tname->un_flags, flags)) 610 ret = EPERM; 611 else 612 ret = 0; 613 goto done; 614 } 615 } 616 617 } else { 618 /* 619 * New unveil involving this directory vnode. 620 */ 621 uv = unveil_add_vnode(p, vp); 622 } 623 624 /* 625 * At this stage with have a unveil in uv with a vnode for a 626 * directory. If the component we are adding is a directory, 627 * we are done. Otherwise, we add the component name the name 628 * list in uv. 629 */ 630 631 if (directory_add) { 632 uv->uv_flags = flags; 633 ret = 0; 634 #ifdef DEBUG_UNVEIL 635 printf("unveil: %s(%d): added unrestricted directory vnode %p" 636 ", uvcount %d\n", 637 pr->ps_comm, pr->ps_pid, vp, vp->v_uvcount); 638 #endif 639 goto done; 640 } 641 642 if (unveil_add_name(uv, ndp->ni_cnd.cn_nameptr, flags)) 643 pr->ps_uvncount++; 644 ret = 0; 645 646 #ifdef DEBUG_UNVEIL 647 printf("unveil: %s(%d): added name %s beneath %s vnode %p," 648 " uvcount %d\n", 649 pr->ps_comm, pr->ps_pid, ndp->ni_cnd.cn_nameptr, 650 uv->uv_flags ? "unrestricted" : "restricted", 651 vp, vp->v_uvcount); 652 #endif 653 654 done: 655 if (ret == 0) 656 unveil_add_traversed_vnodes(p, ndp); 657 658 pr->ps_uvpcwd = unveil_lookup(p->p_fd->fd_cdir, pr, NULL); 659 if (pr->ps_uvpcwd == NULL) { 660 ssize_t i; 661 662 i = unveil_find_cover(p->p_fd->fd_cdir, p); 663 if (i >= 0) 664 pr->ps_uvpcwd = &pr->ps_uvpaths[i]; 665 } 666 667 return ret; 668 } 669 670 /* 671 * XXX this will probably change. 672 * XXX collapse down later once debug surely unneded 673 */ 674 int 675 unveil_flagmatch(struct nameidata *ni, u_char flags) 676 { 677 if (flags == 0) { 678 #ifdef DEBUG_UNVEIL 679 printf("All operations forbidden for 0 flags\n"); 680 #endif 681 return 0; 682 } 683 if (ni->ni_unveil & UNVEIL_READ) { 684 if ((flags & UNVEIL_READ) == 0) { 685 #ifdef DEBUG_UNVEIL 686 printf("unveil lacks UNVEIL_READ\n"); 687 #endif 688 if (flags != UNVEIL_INSPECT) 689 ni->ni_unveil_eacces = 1; 690 return 0; 691 } 692 } 693 if (ni->ni_unveil & UNVEIL_WRITE) { 694 if ((flags & UNVEIL_WRITE) == 0) { 695 #ifdef DEBUG_UNVEIL 696 printf("unveil lacks UNVEIL_WRITE\n"); 697 #endif 698 if (flags != UNVEIL_INSPECT) 699 ni->ni_unveil_eacces = 1; 700 return 0; 701 } 702 } 703 if (ni->ni_unveil & UNVEIL_EXEC) { 704 if ((flags & UNVEIL_EXEC) == 0) { 705 #ifdef DEBUG_UNVEIL 706 printf("unveil lacks UNVEIL_EXEC\n"); 707 #endif 708 if (flags != UNVEIL_INSPECT) 709 ni->ni_unveil_eacces = 1; 710 return 0; 711 } 712 } 713 if (ni->ni_unveil & UNVEIL_CREATE) { 714 if ((flags & UNVEIL_CREATE) == 0) { 715 #ifdef DEBUG_UNVEIL 716 printf("unveil lacks UNVEIL_CREATE\n"); 717 #endif 718 if (flags != UNVEIL_INSPECT) 719 ni->ni_unveil_eacces = 1; 720 return 0; 721 } 722 } 723 if (ni->ni_unveil & UNVEIL_INSPECT) { 724 #ifdef DEBUG_UNVEIL 725 printf("any unveil allows UNVEIL_INSPECT\n"); 726 #endif 727 } 728 return 1; 729 } 730 731 732 struct unveil * 733 unveil_covered(struct unveil *uv, struct vnode *dvp, struct process *pr) { 734 if (uv && uv->uv_vp == dvp) { 735 if (uv->uv_cover >=0) { 736 KASSERT(uv->uv_cover < pr->ps_uvvcount); 737 return &pr->ps_uvpaths[uv->uv_cover]; 738 } 739 return NULL; 740 } 741 return uv; 742 } 743 744 745 /* 746 * Start a relative path lookup. Ensure we find whatever unveil covered 747 * where we start from, either by having a saved current working directory 748 * unveil, or by walking up and finding a cover the hard way if we are 749 * doing a non AT_FDCWD relative lookup. Caller passes a NULL dp 750 * if we are using AT_FDCWD. 751 */ 752 void 753 unveil_start_relative(struct proc *p, struct nameidata *ni, struct vnode *dp) 754 { 755 struct process *pr = p->p_p; 756 struct unveil *uv = NULL; 757 758 if (dp != NULL && pr->ps_uvpaths != NULL) { 759 ssize_t uvi; 760 /* 761 * XXX 762 * This is a non AT_FDCWD relative lookup starting 763 * from a file descriptor. As such, we can't use the 764 * saved current working directory unveil. We walk up 765 * and find what we are covered by. 766 */ 767 uv = unveil_lookup(dp, pr, NULL); 768 if (uv == NULL) { 769 uvi = unveil_find_cover(dp, p); 770 if (uvi >= 0) { 771 KASSERT(uvi < pr->ps_uvvcount); 772 uv = &pr->ps_uvpaths[uvi]; 773 } 774 } 775 } else { 776 /* 777 * Check saved cwd unveil match. 778 * 779 * Since ps_uvpcwd is set on chdir (UNVEIL_READ) we 780 * don't need to go up any further as in the above 781 * case. 782 */ 783 uv = pr->ps_uvpcwd; 784 } 785 786 /* 787 * If the flags don't match, we have no match from our 788 * starting point. If we do not find a matching unveil later 789 * on a later component of this lookup, we'll be out of luck 790 */ 791 if (uv && (unveil_flagmatch(ni, uv->uv_flags))) { 792 #ifdef DEBUG_UNVEIL 793 printf("unveil: %s(%d): cwd unveil at %p matches", 794 pr->ps_comm, pr->ps_pid, uv); 795 #endif 796 ni->ni_unveil_match = uv; 797 } 798 799 } 800 801 /* 802 * unveil checking - for component directories in a namei lookup. 803 */ 804 void 805 unveil_check_component(struct proc *p, struct nameidata *ni, struct vnode *dp) 806 { 807 struct process *pr = p->p_p; 808 struct unveil *uv = NULL; 809 810 if (ni->ni_pledge != PLEDGE_UNVEIL) { 811 if ((ni->ni_cnd.cn_flags & BYPASSUNVEIL) == 0) { 812 if (ni->ni_cnd.cn_flags & ISDOTDOT) { 813 /* 814 * adjust unveil match as necessary 815 */ 816 uv = unveil_covered(ni->ni_unveil_match, dp, 817 pr); 818 /* clear the match when we DOTDOT above it */ 819 if (ni->ni_unveil_match && 820 ni->ni_unveil_match->uv_vp == dp) { 821 ni->ni_unveil_match = NULL; 822 ni->ni_unveil_eacces = 0; 823 } 824 } 825 else 826 uv = unveil_lookup(dp, pr, NULL); 827 828 if (uv != NULL) { 829 /* if directory flags match, it's a match */ 830 if (unveil_flagmatch(ni, uv->uv_flags)) { 831 if (uv->uv_flags & UNVEIL_USERSET) { 832 ni->ni_unveil_match = uv; 833 #ifdef DEBUG_UNVEIL 834 printf("unveil: %s(%d): component " 835 "directory match for vnode %p\n", 836 pr->ps_comm, pr->ps_pid, dp); 837 #endif 838 } 839 } 840 } 841 } 842 } else 843 unveil_save_traversed_vnode(ni, dp); 844 } 845 846 /* 847 * unveil checking - only done after namei lookup has succeeded on 848 * the last component of a namei lookup. 849 */ 850 int 851 unveil_check_final(struct proc *p, struct nameidata *ni) 852 { 853 struct process *pr = p->p_p; 854 struct unveil *uv = NULL; 855 struct unvname *tname = NULL; 856 857 if (ni->ni_pledge == PLEDGE_UNVEIL || pr->ps_uvpaths == NULL) 858 return (0); 859 860 if (ni->ni_cnd.cn_flags & BYPASSUNVEIL) { 861 #ifdef DEBUG_UNVEIL 862 printf("unveil: %s(%d): BYPASSUNVEIL.\n", 863 pr->ps_comm, pr->ps_pid); 864 #endif 865 return (0); 866 } 867 if (ni->ni_vp != NULL && ni->ni_vp->v_type == VDIR) { 868 /* We are matching a directory terminal component */ 869 uv = unveil_lookup(ni->ni_vp, pr, NULL); 870 if (uv == NULL) { 871 #ifdef DEBUG_UNVEIL 872 printf("unveil: %s(%d) no match for vnode %p\n", 873 pr->ps_comm, pr->ps_pid, ni->ni_vp); 874 #endif 875 goto done; 876 } 877 if (!unveil_flagmatch(ni, uv->uv_flags)) { 878 #ifdef DEBUG_UNVEIL 879 printf("unveil: %s(%d) flag mismatch for directory" 880 " vnode %p\n", 881 pr->ps_comm, pr->ps_pid, ni->ni_vp); 882 #endif 883 pr->ps_acflag |= AUNVEIL; 884 if (uv->uv_flags & UNVEIL_USERSET) 885 return EACCES; 886 else 887 return ENOENT; 888 889 } 890 /* directry and flags match, update match */ 891 ni->ni_unveil_match = uv; 892 goto done; 893 } 894 /* Otherwise, we are matching a non-terminal component */ 895 uv = unveil_lookup(ni->ni_dvp, pr, NULL); 896 if (uv == NULL) { 897 #ifdef DEBUG_UNVEIL 898 printf("unveil: %s(%d) no match for directory" 899 " vnode %p\n", 900 pr->ps_comm, pr->ps_pid, ni->ni_dvp); 901 #endif 902 goto done; 903 } 904 if ((tname = unveil_namelookup(uv, ni->ni_cnd.cn_nameptr)) 905 == NULL) { 906 #ifdef DEBUG_UNVEIL 907 printf("unveil: %s(%d) no match for terminal '%s' in " 908 "directory vnode %p\n", 909 pr->ps_comm, pr->ps_pid, 910 ni->ni_cnd.cn_nameptr, ni->ni_dvp); 911 #endif 912 /* no specific name, so check unveil directory flags */ 913 if (!unveil_flagmatch(ni, uv->uv_flags)) { 914 #ifdef DEBUG_UNVEIL 915 printf("unveil: %s(%d) terminal " 916 "'%s' flags mismatch in directory " 917 "vnode %p\n", 918 pr->ps_comm, pr->ps_pid, 919 ni->ni_cnd.cn_nameptr, ni->ni_dvp); 920 #endif 921 /* 922 * If dir has user set restrictions fail with 923 * EACCES. Otherwise, use any covering match 924 * that we found above this dir. 925 */ 926 if (uv->uv_flags & UNVEIL_USERSET) { 927 pr->ps_acflag |= AUNVEIL; 928 return EACCES; 929 } 930 goto done; 931 } 932 /* directory flags match, update match */ 933 if (uv->uv_flags & UNVEIL_USERSET) 934 ni->ni_unveil_match = uv; 935 goto done; 936 } 937 if (!unveil_flagmatch(ni, tname->un_flags)) { 938 /* do flags match for matched name */ 939 #ifdef DEBUG_UNVEIL 940 printf("unveil: %s(%d) flag mismatch for terminal '%s'\n", 941 pr->ps_comm, pr->ps_pid, tname->un_name); 942 #endif 943 pr->ps_acflag |= AUNVEIL; 944 return EACCES; 945 } 946 /* name and flags match in this dir. update match*/ 947 ni->ni_unveil_match = uv; 948 949 done: 950 if (ni->ni_unveil_match) { 951 #ifdef DEBUG_UNVEIL 952 printf("unveil: %s(%d): matched \"%s\" underneath/at " 953 "vnode %p\n", 954 pr->ps_comm, pr->ps_pid, ni->ni_cnd.cn_nameptr, 955 ni->ni_unveil_match->uv_vp); 956 #endif 957 return (0); 958 } 959 if (ni->ni_unveil_eacces) { 960 #ifdef DEBUG_UNVEIL 961 printf("unveil: %s(%d): \"%s\" flag mismatch above/at " 962 "vnode %p\n", 963 pr->ps_comm, pr->ps_pid, ni->ni_cnd.cn_nameptr, 964 ni->ni_unveil_match->uv_vp); 965 #endif 966 pr->ps_acflag |= AUNVEIL; 967 return EACCES; 968 } 969 pr->ps_acflag |= AUNVEIL; 970 return ENOENT; 971 } 972 973 /* 974 * Scan all active processes to see if any of them have a unveil 975 * to this vnode. If so, NULL the vnode in their unveil list, 976 * vrele, drop the reference, and mark their unveil list 977 * as needing to have the hole shrunk the next time the process 978 * uses it for lookup. 979 */ 980 void 981 unveil_removevnode(struct vnode *vp) 982 { 983 struct process *pr; 984 985 if (vp->v_uvcount == 0) 986 return; 987 988 #ifdef DEBUG_UNVEIL 989 printf("unveil_removevnode found vnode %p with count %d\n", 990 vp, vp->v_uvcount); 991 #endif 992 vref(vp); /* make sure it is held till we are done */ 993 994 LIST_FOREACH(pr, &allprocess, ps_list) { 995 struct unveil * uv; 996 997 if ((uv = unveil_lookup(vp, pr, NULL)) != NULL && 998 uv->uv_vp != NULL) { 999 uv->uv_vp = NULL; 1000 uv->uv_flags = 0; 1001 #ifdef DEBUG_UNVEIL 1002 printf("unveil_removevnode vnode %p now count %d\n", 1003 vp, vp->v_uvcount); 1004 #endif 1005 pr->ps_uvshrink = 1; 1006 if (vp->v_uvcount > 0) { 1007 vrele(vp); 1008 vp->v_uvcount--; 1009 } else 1010 panic("vp %p, v_uvcount of %d should be 0", 1011 vp, vp->v_uvcount); 1012 } 1013 } 1014 KASSERT(vp->v_uvcount == 0); 1015 1016 vrele(vp); /* release our ref */ 1017 } 1018