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