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