1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2001 Dag-Erling Coïdan Smørgrav 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer 12 * in this position and unchanged. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include "opt_pseudofs.h" 35 36 #include <sys/param.h> 37 #include <sys/kernel.h> 38 #include <sys/systm.h> 39 #include <sys/ctype.h> 40 #include <sys/dirent.h> 41 #include <sys/fcntl.h> 42 #include <sys/limits.h> 43 #include <sys/lock.h> 44 #include <sys/malloc.h> 45 #include <sys/mount.h> 46 #include <sys/mutex.h> 47 #include <sys/namei.h> 48 #include <sys/proc.h> 49 #include <sys/sbuf.h> 50 #include <sys/sx.h> 51 #include <sys/sysctl.h> 52 #include <sys/vnode.h> 53 54 #include <fs/pseudofs/pseudofs.h> 55 #include <fs/pseudofs/pseudofs_internal.h> 56 57 #define KASSERT_PN_IS_DIR(pn) \ 58 KASSERT((pn)->pn_type == pfstype_root || \ 59 (pn)->pn_type == pfstype_dir || \ 60 (pn)->pn_type == pfstype_procdir, \ 61 ("%s(): VDIR vnode refers to non-directory pfs_node", __func__)) 62 63 #define KASSERT_PN_IS_FILE(pn) \ 64 KASSERT((pn)->pn_type == pfstype_file, \ 65 ("%s(): VREG vnode refers to non-file pfs_node", __func__)) 66 67 #define KASSERT_PN_IS_LINK(pn) \ 68 KASSERT((pn)->pn_type == pfstype_symlink, \ 69 ("%s(): VLNK vnode refers to non-link pfs_node", __func__)) 70 71 #define PFS_MAXBUFSIZ 1024 * 1024 72 73 /* 74 * Returns the fileno, adjusted for target pid 75 */ 76 static uint32_t 77 pn_fileno(struct pfs_node *pn, pid_t pid) 78 { 79 80 KASSERT(pn->pn_fileno > 0, 81 ("%s(): no fileno allocated", __func__)); 82 if (pid != NO_PID) 83 return (pn->pn_fileno * NO_PID + pid); 84 return (pn->pn_fileno); 85 } 86 87 /* 88 * Returns non-zero if given file is visible to given thread. 89 */ 90 static int 91 pfs_visible_proc(struct thread *td, struct pfs_node *pn, struct proc *proc) 92 { 93 int visible; 94 95 if (proc == NULL) 96 return (0); 97 98 PROC_LOCK_ASSERT(proc, MA_OWNED); 99 100 visible = ((proc->p_flag & P_WEXIT) == 0); 101 if (visible) 102 visible = (p_cansee(td, proc) == 0); 103 if (visible && pn->pn_vis != NULL) 104 visible = pn_vis(td, proc, pn); 105 if (!visible) 106 return (0); 107 return (1); 108 } 109 110 static int 111 pfs_visible(struct thread *td, struct pfs_node *pn, pid_t pid, 112 struct proc **p) 113 { 114 struct proc *proc; 115 116 PFS_TRACE(("%s (pid: %d, req: %d)", 117 pn->pn_name, pid, td->td_proc->p_pid)); 118 119 if (p) 120 *p = NULL; 121 if (pid == NO_PID) 122 PFS_RETURN (1); 123 proc = pfind(pid); 124 if (proc == NULL) 125 PFS_RETURN (0); 126 if (pfs_visible_proc(td, pn, proc)) { 127 if (p) 128 *p = proc; 129 else 130 PROC_UNLOCK(proc); 131 PFS_RETURN (1); 132 } 133 PROC_UNLOCK(proc); 134 PFS_RETURN (0); 135 } 136 137 static int 138 pfs_lookup_proc(pid_t pid, struct proc **p) 139 { 140 struct proc *proc; 141 142 proc = pfind(pid); 143 if (proc == NULL) 144 return (0); 145 if ((proc->p_flag & P_WEXIT) != 0) { 146 PROC_UNLOCK(proc); 147 return (0); 148 } 149 _PHOLD(proc); 150 PROC_UNLOCK(proc); 151 *p = proc; 152 return (1); 153 } 154 155 /* 156 * Verify permissions 157 */ 158 static int 159 pfs_access(struct vop_access_args *va) 160 { 161 struct vnode *vn = va->a_vp; 162 struct pfs_vdata *pvd = vn->v_data; 163 struct vattr vattr; 164 int error; 165 166 PFS_TRACE(("%s", pvd->pvd_pn->pn_name)); 167 (void)pvd; 168 169 error = VOP_GETATTR(vn, &vattr, va->a_cred); 170 if (error) 171 PFS_RETURN (error); 172 error = vaccess(vn->v_type, vattr.va_mode, vattr.va_uid, vattr.va_gid, 173 va->a_accmode, va->a_cred); 174 PFS_RETURN (error); 175 } 176 177 /* 178 * Close a file or directory 179 */ 180 static int 181 pfs_close(struct vop_close_args *va) 182 { 183 struct vnode *vn = va->a_vp; 184 struct pfs_vdata *pvd = vn->v_data; 185 struct pfs_node *pn = pvd->pvd_pn; 186 struct proc *proc; 187 int error; 188 189 PFS_TRACE(("%s", pn->pn_name)); 190 pfs_assert_not_owned(pn); 191 192 /* 193 * Do nothing unless this is the last close and the node has a 194 * last-close handler. 195 */ 196 if (vrefcnt(vn) > 1 || pn->pn_close == NULL) 197 PFS_RETURN (0); 198 199 if (pvd->pvd_pid != NO_PID) { 200 proc = pfind(pvd->pvd_pid); 201 } else { 202 proc = NULL; 203 } 204 205 error = pn_close(va->a_td, proc, pn); 206 207 if (proc != NULL) 208 PROC_UNLOCK(proc); 209 210 PFS_RETURN (error); 211 } 212 213 /* 214 * Get file attributes 215 */ 216 static int 217 pfs_getattr(struct vop_getattr_args *va) 218 { 219 struct vnode *vn = va->a_vp; 220 struct pfs_vdata *pvd = vn->v_data; 221 struct pfs_node *pn = pvd->pvd_pn; 222 struct vattr *vap = va->a_vap; 223 struct proc *proc; 224 int error = 0; 225 226 PFS_TRACE(("%s", pn->pn_name)); 227 pfs_assert_not_owned(pn); 228 229 if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc)) 230 PFS_RETURN (ENOENT); 231 232 vap->va_type = vn->v_type; 233 vap->va_fileid = pn_fileno(pn, pvd->pvd_pid); 234 vap->va_flags = 0; 235 vap->va_blocksize = PAGE_SIZE; 236 vap->va_bytes = vap->va_size = 0; 237 vap->va_filerev = 0; 238 vap->va_fsid = vn->v_mount->mnt_stat.f_fsid.val[0]; 239 vap->va_nlink = 1; 240 nanotime(&vap->va_ctime); 241 vap->va_atime = vap->va_mtime = vap->va_ctime; 242 243 switch (pn->pn_type) { 244 case pfstype_procdir: 245 case pfstype_root: 246 case pfstype_dir: 247 #if 0 248 pfs_lock(pn); 249 /* compute link count */ 250 pfs_unlock(pn); 251 #endif 252 vap->va_mode = 0555; 253 break; 254 case pfstype_file: 255 case pfstype_symlink: 256 vap->va_mode = 0444; 257 break; 258 default: 259 printf("shouldn't be here!\n"); 260 vap->va_mode = 0; 261 break; 262 } 263 264 if (proc != NULL) { 265 vap->va_uid = proc->p_ucred->cr_ruid; 266 vap->va_gid = proc->p_ucred->cr_rgid; 267 } else { 268 vap->va_uid = 0; 269 vap->va_gid = 0; 270 } 271 272 if (pn->pn_attr != NULL) 273 error = pn_attr(curthread, proc, pn, vap); 274 275 if(proc != NULL) 276 PROC_UNLOCK(proc); 277 278 PFS_RETURN (error); 279 } 280 281 /* 282 * Perform an ioctl 283 */ 284 static int 285 pfs_ioctl(struct vop_ioctl_args *va) 286 { 287 struct vnode *vn; 288 struct pfs_vdata *pvd; 289 struct pfs_node *pn; 290 struct proc *proc; 291 int error; 292 293 vn = va->a_vp; 294 vn_lock(vn, LK_SHARED | LK_RETRY); 295 if (VN_IS_DOOMED(vn)) { 296 VOP_UNLOCK(vn); 297 return (EBADF); 298 } 299 pvd = vn->v_data; 300 pn = pvd->pvd_pn; 301 302 PFS_TRACE(("%s: %lx", pn->pn_name, va->a_command)); 303 pfs_assert_not_owned(pn); 304 305 if (vn->v_type != VREG) { 306 VOP_UNLOCK(vn); 307 PFS_RETURN (EINVAL); 308 } 309 KASSERT_PN_IS_FILE(pn); 310 311 if (pn->pn_ioctl == NULL) { 312 VOP_UNLOCK(vn); 313 PFS_RETURN (ENOTTY); 314 } 315 316 /* 317 * This is necessary because process' privileges may 318 * have changed since the open() call. 319 */ 320 if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc)) { 321 VOP_UNLOCK(vn); 322 PFS_RETURN (EIO); 323 } 324 325 error = pn_ioctl(curthread, proc, pn, va->a_command, va->a_data); 326 327 if (proc != NULL) 328 PROC_UNLOCK(proc); 329 330 VOP_UNLOCK(vn); 331 PFS_RETURN (error); 332 } 333 334 /* 335 * Perform getextattr 336 */ 337 static int 338 pfs_getextattr(struct vop_getextattr_args *va) 339 { 340 struct vnode *vn = va->a_vp; 341 struct pfs_vdata *pvd = vn->v_data; 342 struct pfs_node *pn = pvd->pvd_pn; 343 struct proc *proc; 344 int error; 345 346 PFS_TRACE(("%s", pn->pn_name)); 347 pfs_assert_not_owned(pn); 348 349 /* 350 * This is necessary because either process' privileges may 351 * have changed since the open() call. 352 */ 353 if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc)) 354 PFS_RETURN (EIO); 355 356 if (pn->pn_getextattr == NULL) 357 error = EOPNOTSUPP; 358 else 359 error = pn_getextattr(curthread, proc, pn, 360 va->a_attrnamespace, va->a_name, va->a_uio, 361 va->a_size, va->a_cred); 362 363 if (proc != NULL) 364 PROC_UNLOCK(proc); 365 366 PFS_RETURN (error); 367 } 368 369 /* 370 * Convert a vnode to its component name 371 */ 372 static int 373 pfs_vptocnp(struct vop_vptocnp_args *ap) 374 { 375 struct vnode *vp = ap->a_vp; 376 struct vnode **dvp = ap->a_vpp; 377 struct pfs_vdata *pvd = vp->v_data; 378 struct pfs_node *pd = pvd->pvd_pn; 379 struct pfs_node *pn; 380 struct mount *mp; 381 char *buf = ap->a_buf; 382 size_t *buflen = ap->a_buflen; 383 char pidbuf[PFS_NAMELEN]; 384 pid_t pid = pvd->pvd_pid; 385 int len, i, error, locked; 386 387 i = *buflen; 388 error = 0; 389 390 pfs_lock(pd); 391 392 if (vp->v_type == VDIR && pd->pn_type == pfstype_root) { 393 *dvp = vp; 394 vhold(*dvp); 395 pfs_unlock(pd); 396 PFS_RETURN (0); 397 } else if (vp->v_type == VDIR && pd->pn_type == pfstype_procdir) { 398 len = snprintf(pidbuf, sizeof(pidbuf), "%d", pid); 399 i -= len; 400 if (i < 0) { 401 error = ENOMEM; 402 goto failed; 403 } 404 bcopy(pidbuf, buf + i, len); 405 } else { 406 len = strlen(pd->pn_name); 407 i -= len; 408 if (i < 0) { 409 error = ENOMEM; 410 goto failed; 411 } 412 bcopy(pd->pn_name, buf + i, len); 413 } 414 415 pn = pd->pn_parent; 416 pfs_unlock(pd); 417 418 mp = vp->v_mount; 419 error = vfs_busy(mp, 0); 420 if (error) 421 return (error); 422 423 /* 424 * vp is held by caller. 425 */ 426 locked = VOP_ISLOCKED(vp); 427 VOP_UNLOCK(vp); 428 429 error = pfs_vncache_alloc(mp, dvp, pn, pid); 430 if (error) { 431 vn_lock(vp, locked | LK_RETRY); 432 vfs_unbusy(mp); 433 PFS_RETURN(error); 434 } 435 436 *buflen = i; 437 VOP_UNLOCK(*dvp); 438 vn_lock(vp, locked | LK_RETRY); 439 vfs_unbusy(mp); 440 441 PFS_RETURN (0); 442 failed: 443 pfs_unlock(pd); 444 PFS_RETURN(error); 445 } 446 447 /* 448 * Look up a file or directory 449 */ 450 static int 451 pfs_lookup(struct vop_cachedlookup_args *va) 452 { 453 struct vnode *vn = va->a_dvp; 454 struct vnode **vpp = va->a_vpp; 455 struct componentname *cnp = va->a_cnp; 456 struct pfs_vdata *pvd = vn->v_data; 457 struct pfs_node *pd = pvd->pvd_pn; 458 struct pfs_node *pn, *pdn = NULL; 459 struct mount *mp; 460 pid_t pid = pvd->pvd_pid; 461 char *pname; 462 int error, i, namelen, visible; 463 464 PFS_TRACE(("%.*s", (int)cnp->cn_namelen, cnp->cn_nameptr)); 465 pfs_assert_not_owned(pd); 466 467 if (vn->v_type != VDIR) 468 PFS_RETURN (ENOTDIR); 469 KASSERT_PN_IS_DIR(pd); 470 471 /* 472 * Don't support DELETE or RENAME. CREATE is supported so 473 * that O_CREAT will work, but the lookup will still fail if 474 * the file does not exist. 475 */ 476 if ((cnp->cn_flags & ISLASTCN) && 477 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) 478 PFS_RETURN (EOPNOTSUPP); 479 480 /* shortcut: check if the name is too long */ 481 if (cnp->cn_namelen >= PFS_NAMELEN) 482 PFS_RETURN (ENOENT); 483 484 /* check that parent directory is visible... */ 485 if (!pfs_visible(curthread, pd, pvd->pvd_pid, NULL)) 486 PFS_RETURN (ENOENT); 487 488 /* self */ 489 namelen = cnp->cn_namelen; 490 pname = cnp->cn_nameptr; 491 if (namelen == 1 && pname[0] == '.') { 492 pn = pd; 493 *vpp = vn; 494 VREF(vn); 495 PFS_RETURN (0); 496 } 497 498 mp = vn->v_mount; 499 500 /* parent */ 501 if (cnp->cn_flags & ISDOTDOT) { 502 if (pd->pn_type == pfstype_root) 503 PFS_RETURN (EIO); 504 error = vfs_busy(mp, MBF_NOWAIT); 505 if (error != 0) { 506 vfs_ref(mp); 507 VOP_UNLOCK(vn); 508 error = vfs_busy(mp, 0); 509 vn_lock(vn, LK_EXCLUSIVE | LK_RETRY); 510 vfs_rel(mp); 511 if (error != 0) 512 PFS_RETURN(ENOENT); 513 if (VN_IS_DOOMED(vn)) { 514 vfs_unbusy(mp); 515 PFS_RETURN(ENOENT); 516 } 517 } 518 VOP_UNLOCK(vn); 519 KASSERT(pd->pn_parent != NULL, 520 ("%s(): non-root directory has no parent", __func__)); 521 /* 522 * This one is tricky. Descendents of procdir nodes 523 * inherit their parent's process affinity, but 524 * there's no easy reverse mapping. For simplicity, 525 * we assume that if this node is a procdir, its 526 * parent isn't (which is correct as long as 527 * descendents of procdir nodes are never procdir 528 * nodes themselves) 529 */ 530 if (pd->pn_type == pfstype_procdir) 531 pid = NO_PID; 532 pfs_lock(pd); 533 pn = pd->pn_parent; 534 pfs_unlock(pd); 535 goto got_pnode; 536 } 537 538 pfs_lock(pd); 539 540 /* named node */ 541 for (pn = pd->pn_nodes; pn != NULL; pn = pn->pn_next) 542 if (pn->pn_type == pfstype_procdir) 543 pdn = pn; 544 else if (pn->pn_name[namelen] == '\0' && 545 bcmp(pname, pn->pn_name, namelen) == 0) { 546 pfs_unlock(pd); 547 goto got_pnode; 548 } 549 550 /* process dependent node */ 551 if ((pn = pdn) != NULL) { 552 pid = 0; 553 for (pid = 0, i = 0; i < namelen && isdigit(pname[i]); ++i) 554 if ((pid = pid * 10 + pname[i] - '0') > PID_MAX) 555 break; 556 if (i == cnp->cn_namelen) { 557 pfs_unlock(pd); 558 goto got_pnode; 559 } 560 } 561 562 pfs_unlock(pd); 563 564 PFS_RETURN (ENOENT); 565 566 got_pnode: 567 pfs_assert_not_owned(pd); 568 pfs_assert_not_owned(pn); 569 visible = pfs_visible(curthread, pn, pid, NULL); 570 if (!visible) { 571 error = ENOENT; 572 goto failed; 573 } 574 575 error = pfs_vncache_alloc(mp, vpp, pn, pid); 576 if (error) 577 goto failed; 578 579 if (cnp->cn_flags & ISDOTDOT) { 580 vfs_unbusy(mp); 581 vn_lock(vn, LK_EXCLUSIVE | LK_RETRY); 582 if (VN_IS_DOOMED(vn)) { 583 vput(*vpp); 584 *vpp = NULL; 585 PFS_RETURN(ENOENT); 586 } 587 } 588 if (cnp->cn_flags & MAKEENTRY && !VN_IS_DOOMED(vn)) 589 cache_enter(vn, *vpp, cnp); 590 PFS_RETURN (0); 591 failed: 592 if (cnp->cn_flags & ISDOTDOT) { 593 vfs_unbusy(mp); 594 vn_lock(vn, LK_EXCLUSIVE | LK_RETRY); 595 *vpp = NULL; 596 } 597 PFS_RETURN(error); 598 } 599 600 /* 601 * Open a file or directory. 602 */ 603 static int 604 pfs_open(struct vop_open_args *va) 605 { 606 struct vnode *vn = va->a_vp; 607 struct pfs_vdata *pvd = vn->v_data; 608 struct pfs_node *pn = pvd->pvd_pn; 609 int mode = va->a_mode; 610 611 PFS_TRACE(("%s (mode 0x%x)", pn->pn_name, mode)); 612 pfs_assert_not_owned(pn); 613 614 /* check if the requested mode is permitted */ 615 if (((mode & FREAD) && !(mode & PFS_RD)) || 616 ((mode & FWRITE) && !(mode & PFS_WR))) 617 PFS_RETURN (EPERM); 618 619 /* we don't support locking */ 620 if ((mode & O_SHLOCK) || (mode & O_EXLOCK)) 621 PFS_RETURN (EOPNOTSUPP); 622 623 PFS_RETURN (0); 624 } 625 626 /* 627 * Read from a file 628 */ 629 static int 630 pfs_read(struct vop_read_args *va) 631 { 632 struct vnode *vn = va->a_vp; 633 struct pfs_vdata *pvd = vn->v_data; 634 struct pfs_node *pn = pvd->pvd_pn; 635 struct uio *uio = va->a_uio; 636 struct proc *proc; 637 struct sbuf *sb = NULL; 638 int error, locked; 639 off_t buflen; 640 641 PFS_TRACE(("%s", pn->pn_name)); 642 pfs_assert_not_owned(pn); 643 644 if (vn->v_type != VREG) 645 PFS_RETURN (EINVAL); 646 KASSERT_PN_IS_FILE(pn); 647 648 if (!(pn->pn_flags & PFS_RD)) 649 PFS_RETURN (EBADF); 650 651 if (pn->pn_fill == NULL) 652 PFS_RETURN (EIO); 653 654 /* 655 * This is necessary because either process' privileges may 656 * have changed since the open() call. 657 */ 658 if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc)) 659 PFS_RETURN (EIO); 660 if (proc != NULL) { 661 _PHOLD(proc); 662 PROC_UNLOCK(proc); 663 } 664 665 vhold(vn); 666 locked = VOP_ISLOCKED(vn); 667 VOP_UNLOCK(vn); 668 669 if (pn->pn_flags & PFS_RAWRD) { 670 PFS_TRACE(("%zd resid", uio->uio_resid)); 671 error = pn_fill(curthread, proc, pn, NULL, uio); 672 PFS_TRACE(("%zd resid", uio->uio_resid)); 673 goto ret; 674 } 675 676 if (uio->uio_resid < 0 || uio->uio_offset < 0 || 677 uio->uio_resid > OFF_MAX - uio->uio_offset) { 678 error = EINVAL; 679 goto ret; 680 } 681 buflen = uio->uio_offset + uio->uio_resid; 682 if (buflen > PFS_MAXBUFSIZ) 683 buflen = PFS_MAXBUFSIZ; 684 685 sb = sbuf_new(sb, NULL, buflen + 1, 0); 686 if (sb == NULL) { 687 error = EIO; 688 goto ret; 689 } 690 691 error = pn_fill(curthread, proc, pn, sb, uio); 692 693 if (error) { 694 sbuf_delete(sb); 695 goto ret; 696 } 697 698 /* 699 * XXX: If the buffer overflowed, sbuf_len() will not return 700 * the data length. Then just use the full length because an 701 * overflowed sbuf must be full. 702 */ 703 if (sbuf_finish(sb) == 0) 704 buflen = sbuf_len(sb); 705 error = uiomove_frombuf(sbuf_data(sb), buflen, uio); 706 sbuf_delete(sb); 707 ret: 708 vn_lock(vn, locked | LK_RETRY); 709 vdrop(vn); 710 if (proc != NULL) 711 PRELE(proc); 712 PFS_RETURN (error); 713 } 714 715 /* 716 * Iterate through directory entries 717 */ 718 static int 719 pfs_iterate(struct thread *td, struct proc *proc, struct pfs_node *pd, 720 struct pfs_node **pn, struct proc **p) 721 { 722 int visible; 723 724 sx_assert(&allproc_lock, SX_SLOCKED); 725 pfs_assert_owned(pd); 726 again: 727 if (*pn == NULL) { 728 /* first node */ 729 *pn = pd->pn_nodes; 730 } else if ((*pn)->pn_type != pfstype_procdir) { 731 /* next node */ 732 *pn = (*pn)->pn_next; 733 } 734 if (*pn != NULL && (*pn)->pn_type == pfstype_procdir) { 735 /* next process */ 736 if (*p == NULL) 737 *p = LIST_FIRST(&allproc); 738 else 739 *p = LIST_NEXT(*p, p_list); 740 /* out of processes: next node */ 741 if (*p == NULL) 742 *pn = (*pn)->pn_next; 743 else 744 PROC_LOCK(*p); 745 } 746 747 if ((*pn) == NULL) 748 return (-1); 749 750 if (*p != NULL) { 751 visible = pfs_visible_proc(td, *pn, *p); 752 PROC_UNLOCK(*p); 753 } else if (proc != NULL) { 754 visible = pfs_visible_proc(td, *pn, proc); 755 } else { 756 visible = 1; 757 } 758 if (!visible) 759 goto again; 760 761 return (0); 762 } 763 764 /* Directory entry list */ 765 struct pfsentry { 766 STAILQ_ENTRY(pfsentry) link; 767 struct dirent entry; 768 }; 769 STAILQ_HEAD(pfsdirentlist, pfsentry); 770 771 /* 772 * Return directory entries. 773 */ 774 static int 775 pfs_readdir(struct vop_readdir_args *va) 776 { 777 struct vnode *vn = va->a_vp; 778 struct pfs_vdata *pvd = vn->v_data; 779 struct pfs_node *pd = pvd->pvd_pn; 780 pid_t pid = pvd->pvd_pid; 781 struct proc *p, *proc; 782 struct pfs_node *pn; 783 struct uio *uio; 784 struct pfsentry *pfsent, *pfsent2; 785 struct pfsdirentlist lst; 786 off_t offset; 787 int error, i, resid; 788 789 STAILQ_INIT(&lst); 790 error = 0; 791 KASSERT(pd->pn_info == vn->v_mount->mnt_data, 792 ("%s(): pn_info does not match mountpoint", __func__)); 793 PFS_TRACE(("%s pid %lu", pd->pn_name, (unsigned long)pid)); 794 pfs_assert_not_owned(pd); 795 796 if (vn->v_type != VDIR) 797 PFS_RETURN (ENOTDIR); 798 KASSERT_PN_IS_DIR(pd); 799 uio = va->a_uio; 800 801 /* only allow reading entire entries */ 802 offset = uio->uio_offset; 803 resid = uio->uio_resid; 804 if (offset < 0 || offset % PFS_DELEN != 0 || 805 (resid && resid < PFS_DELEN)) 806 PFS_RETURN (EINVAL); 807 if (resid == 0) 808 PFS_RETURN (0); 809 810 proc = NULL; 811 if (pid != NO_PID && !pfs_lookup_proc(pid, &proc)) 812 PFS_RETURN (ENOENT); 813 814 sx_slock(&allproc_lock); 815 pfs_lock(pd); 816 817 KASSERT(pid == NO_PID || proc != NULL, 818 ("%s(): no process for pid %lu", __func__, (unsigned long)pid)); 819 820 if (pid != NO_PID) { 821 PROC_LOCK(proc); 822 823 /* check if the directory is visible to the caller */ 824 if (!pfs_visible_proc(curthread, pd, proc)) { 825 _PRELE(proc); 826 PROC_UNLOCK(proc); 827 sx_sunlock(&allproc_lock); 828 pfs_unlock(pd); 829 PFS_RETURN (ENOENT); 830 } 831 } 832 833 /* skip unwanted entries */ 834 for (pn = NULL, p = NULL; offset > 0; offset -= PFS_DELEN) { 835 if (pfs_iterate(curthread, proc, pd, &pn, &p) == -1) { 836 /* nothing left... */ 837 if (proc != NULL) { 838 _PRELE(proc); 839 PROC_UNLOCK(proc); 840 } 841 pfs_unlock(pd); 842 sx_sunlock(&allproc_lock); 843 PFS_RETURN (0); 844 } 845 } 846 847 /* fill in entries */ 848 while (pfs_iterate(curthread, proc, pd, &pn, &p) != -1 && 849 resid >= PFS_DELEN) { 850 if ((pfsent = malloc(sizeof(struct pfsentry), M_IOV, 851 M_NOWAIT | M_ZERO)) == NULL) { 852 error = ENOMEM; 853 break; 854 } 855 pfsent->entry.d_reclen = PFS_DELEN; 856 pfsent->entry.d_fileno = pn_fileno(pn, pid); 857 /* PFS_DELEN was picked to fit PFS_NAMLEN */ 858 for (i = 0; i < PFS_NAMELEN - 1 && pn->pn_name[i] != '\0'; ++i) 859 pfsent->entry.d_name[i] = pn->pn_name[i]; 860 pfsent->entry.d_namlen = i; 861 /* NOTE: d_off is the offset of the *next* entry. */ 862 pfsent->entry.d_off = offset + PFS_DELEN; 863 switch (pn->pn_type) { 864 case pfstype_procdir: 865 KASSERT(p != NULL, 866 ("reached procdir node with p == NULL")); 867 pfsent->entry.d_namlen = snprintf(pfsent->entry.d_name, 868 PFS_NAMELEN, "%d", p->p_pid); 869 /* fall through */ 870 case pfstype_root: 871 case pfstype_dir: 872 case pfstype_this: 873 case pfstype_parent: 874 pfsent->entry.d_type = DT_DIR; 875 break; 876 case pfstype_file: 877 pfsent->entry.d_type = DT_REG; 878 break; 879 case pfstype_symlink: 880 pfsent->entry.d_type = DT_LNK; 881 break; 882 default: 883 panic("%s has unexpected node type: %d", pn->pn_name, pn->pn_type); 884 } 885 PFS_TRACE(("%s", pfsent->entry.d_name)); 886 dirent_terminate(&pfsent->entry); 887 STAILQ_INSERT_TAIL(&lst, pfsent, link); 888 offset += PFS_DELEN; 889 resid -= PFS_DELEN; 890 } 891 if (proc != NULL) { 892 _PRELE(proc); 893 PROC_UNLOCK(proc); 894 } 895 pfs_unlock(pd); 896 sx_sunlock(&allproc_lock); 897 i = 0; 898 STAILQ_FOREACH_SAFE(pfsent, &lst, link, pfsent2) { 899 if (error == 0) 900 error = uiomove(&pfsent->entry, PFS_DELEN, uio); 901 free(pfsent, M_IOV); 902 i++; 903 } 904 PFS_TRACE(("%ju bytes", (uintmax_t)(i * PFS_DELEN))); 905 PFS_RETURN (error); 906 } 907 908 /* 909 * Read a symbolic link 910 */ 911 static int 912 pfs_readlink(struct vop_readlink_args *va) 913 { 914 struct vnode *vn = va->a_vp; 915 struct pfs_vdata *pvd = vn->v_data; 916 struct pfs_node *pn = pvd->pvd_pn; 917 struct uio *uio = va->a_uio; 918 struct proc *proc = NULL; 919 char buf[PATH_MAX]; 920 struct sbuf sb; 921 int error, locked; 922 923 PFS_TRACE(("%s", pn->pn_name)); 924 pfs_assert_not_owned(pn); 925 926 if (vn->v_type != VLNK) 927 PFS_RETURN (EINVAL); 928 KASSERT_PN_IS_LINK(pn); 929 930 if (pn->pn_fill == NULL) 931 PFS_RETURN (EIO); 932 933 if (pvd->pvd_pid != NO_PID) { 934 if ((proc = pfind(pvd->pvd_pid)) == NULL) 935 PFS_RETURN (EIO); 936 if (proc->p_flag & P_WEXIT) { 937 PROC_UNLOCK(proc); 938 PFS_RETURN (EIO); 939 } 940 _PHOLD(proc); 941 PROC_UNLOCK(proc); 942 } 943 vhold(vn); 944 locked = VOP_ISLOCKED(vn); 945 VOP_UNLOCK(vn); 946 947 /* sbuf_new() can't fail with a static buffer */ 948 sbuf_new(&sb, buf, sizeof buf, 0); 949 950 error = pn_fill(curthread, proc, pn, &sb, NULL); 951 952 if (proc != NULL) 953 PRELE(proc); 954 vn_lock(vn, locked | LK_RETRY); 955 vdrop(vn); 956 957 if (error) { 958 sbuf_delete(&sb); 959 PFS_RETURN (error); 960 } 961 962 if (sbuf_finish(&sb) != 0) { 963 sbuf_delete(&sb); 964 PFS_RETURN (ENAMETOOLONG); 965 } 966 967 error = uiomove_frombuf(sbuf_data(&sb), sbuf_len(&sb), uio); 968 sbuf_delete(&sb); 969 PFS_RETURN (error); 970 } 971 972 /* 973 * Reclaim a vnode 974 */ 975 static int 976 pfs_reclaim(struct vop_reclaim_args *va) 977 { 978 struct vnode *vn = va->a_vp; 979 struct pfs_vdata *pvd = vn->v_data; 980 struct pfs_node *pn = pvd->pvd_pn; 981 982 PFS_TRACE(("%s", pn->pn_name)); 983 pfs_assert_not_owned(pn); 984 985 return (pfs_vncache_free(va->a_vp)); 986 } 987 988 /* 989 * Set attributes 990 */ 991 static int 992 pfs_setattr(struct vop_setattr_args *va) 993 { 994 struct vnode *vn = va->a_vp; 995 struct pfs_vdata *pvd = vn->v_data; 996 struct pfs_node *pn = pvd->pvd_pn; 997 998 PFS_TRACE(("%s", pn->pn_name)); 999 pfs_assert_not_owned(pn); 1000 1001 /* Silently ignore unchangeable attributes. */ 1002 PFS_RETURN (0); 1003 } 1004 1005 /* 1006 * Write to a file 1007 */ 1008 static int 1009 pfs_write(struct vop_write_args *va) 1010 { 1011 struct vnode *vn = va->a_vp; 1012 struct pfs_vdata *pvd = vn->v_data; 1013 struct pfs_node *pn = pvd->pvd_pn; 1014 struct uio *uio = va->a_uio; 1015 struct proc *proc; 1016 struct sbuf sb; 1017 int error; 1018 1019 PFS_TRACE(("%s", pn->pn_name)); 1020 pfs_assert_not_owned(pn); 1021 1022 if (vn->v_type != VREG) 1023 PFS_RETURN (EINVAL); 1024 KASSERT_PN_IS_FILE(pn); 1025 1026 if (!(pn->pn_flags & PFS_WR)) 1027 PFS_RETURN (EBADF); 1028 1029 if (pn->pn_fill == NULL) 1030 PFS_RETURN (EIO); 1031 1032 /* 1033 * This is necessary because either process' privileges may 1034 * have changed since the open() call. 1035 */ 1036 if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc)) 1037 PFS_RETURN (EIO); 1038 if (proc != NULL) { 1039 _PHOLD(proc); 1040 PROC_UNLOCK(proc); 1041 } 1042 1043 if (pn->pn_flags & PFS_RAWWR) { 1044 error = pn_fill(curthread, proc, pn, NULL, uio); 1045 if (proc != NULL) 1046 PRELE(proc); 1047 PFS_RETURN (error); 1048 } 1049 1050 sbuf_uionew(&sb, uio, &error); 1051 if (error) { 1052 if (proc != NULL) 1053 PRELE(proc); 1054 PFS_RETURN (error); 1055 } 1056 1057 error = pn_fill(curthread, proc, pn, &sb, uio); 1058 1059 sbuf_delete(&sb); 1060 if (proc != NULL) 1061 PRELE(proc); 1062 PFS_RETURN (error); 1063 } 1064 1065 /* 1066 * Vnode operations 1067 */ 1068 struct vop_vector pfs_vnodeops = { 1069 .vop_default = &default_vnodeops, 1070 1071 .vop_access = pfs_access, 1072 .vop_cachedlookup = pfs_lookup, 1073 .vop_close = pfs_close, 1074 .vop_create = VOP_EOPNOTSUPP, 1075 .vop_getattr = pfs_getattr, 1076 .vop_getextattr = pfs_getextattr, 1077 .vop_ioctl = pfs_ioctl, 1078 .vop_link = VOP_EOPNOTSUPP, 1079 .vop_lookup = vfs_cache_lookup, 1080 .vop_mkdir = VOP_EOPNOTSUPP, 1081 .vop_mknod = VOP_EOPNOTSUPP, 1082 .vop_open = pfs_open, 1083 .vop_read = pfs_read, 1084 .vop_readdir = pfs_readdir, 1085 .vop_readlink = pfs_readlink, 1086 .vop_reclaim = pfs_reclaim, 1087 .vop_remove = VOP_EOPNOTSUPP, 1088 .vop_rename = VOP_EOPNOTSUPP, 1089 .vop_rmdir = VOP_EOPNOTSUPP, 1090 .vop_setattr = pfs_setattr, 1091 .vop_symlink = VOP_EOPNOTSUPP, 1092 .vop_vptocnp = pfs_vptocnp, 1093 .vop_write = pfs_write, 1094 /* XXX I've probably forgotten a few that need VOP_EOPNOTSUPP */ 1095 }; 1096 VFS_VOP_VECTOR_REGISTER(pfs_vnodeops); 1097