1 /* $NetBSD: procfs_subr.c,v 1.95 2009/03/15 17:22:38 cegger Exp $ */ 2 3 /*- 4 * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Doran. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * This code is derived from software contributed to Berkeley by 37 * Jan-Simon Pendry. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. Neither the name of the University nor the names of its contributors 48 * may be used to endorse or promote products derived from this software 49 * without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * SUCH DAMAGE. 62 * 63 * @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95 64 */ 65 66 /* 67 * Copyright (c) 1994 Christopher G. Demetriou. All rights reserved. 68 * Copyright (c) 1993 Jan-Simon Pendry 69 * 70 * This code is derived from software contributed to Berkeley by 71 * Jan-Simon Pendry. 72 * 73 * Redistribution and use in source and binary forms, with or without 74 * modification, are permitted provided that the following conditions 75 * are met: 76 * 1. Redistributions of source code must retain the above copyright 77 * notice, this list of conditions and the following disclaimer. 78 * 2. Redistributions in binary form must reproduce the above copyright 79 * notice, this list of conditions and the following disclaimer in the 80 * documentation and/or other materials provided with the distribution. 81 * 3. All advertising materials mentioning features or use of this software 82 * must display the following acknowledgement: 83 * This product includes software developed by the University of 84 * California, Berkeley and its contributors. 85 * 4. Neither the name of the University nor the names of its contributors 86 * may be used to endorse or promote products derived from this software 87 * without specific prior written permission. 88 * 89 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 90 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 91 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 92 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 93 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 94 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 95 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 96 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 97 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 98 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 99 * SUCH DAMAGE. 100 * 101 * @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95 102 */ 103 104 #include <sys/cdefs.h> 105 __KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.95 2009/03/15 17:22:38 cegger Exp $"); 106 107 #include <sys/param.h> 108 #include <sys/systm.h> 109 #include <sys/time.h> 110 #include <sys/kernel.h> 111 #include <sys/proc.h> 112 #include <sys/vnode.h> 113 #include <sys/malloc.h> 114 #include <sys/stat.h> 115 #include <sys/file.h> 116 #include <sys/filedesc.h> 117 #include <sys/kauth.h> 118 119 #include <miscfs/procfs/procfs.h> 120 121 void procfs_hashins(struct pfsnode *); 122 void procfs_hashrem(struct pfsnode *); 123 struct vnode *procfs_hashget(pid_t, pfstype, int, struct mount *, int); 124 125 LIST_HEAD(pfs_hashhead, pfsnode) *pfs_hashtbl; 126 u_long pfs_ihash; /* size of hash table - 1 */ 127 #define PFSPIDHASH(pid) ((pid) & pfs_ihash) 128 129 kmutex_t pfs_hashlock; 130 kmutex_t pfs_ihash_lock; 131 132 #define ISSET(t, f) ((t) & (f)) 133 134 /* 135 * allocate a pfsnode/vnode pair. the vnode is 136 * referenced, and locked. 137 * 138 * the pid, pfs_type, and mount point uniquely 139 * identify a pfsnode. the mount point is needed 140 * because someone might mount this filesystem 141 * twice. 142 * 143 * all pfsnodes are maintained on a singly-linked 144 * list. new nodes are only allocated when they cannot 145 * be found on this list. entries on the list are 146 * removed when the vfs reclaim entry is called. 147 * 148 * a single lock is kept for the entire list. this is 149 * needed because the getnewvnode() function can block 150 * waiting for a vnode to become free, in which case there 151 * may be more than one process trying to get the same 152 * vnode. this lock is only taken if we are going to 153 * call getnewvnode, since the kernel itself is single-threaded. 154 * 155 * if an entry is found on the list, then call vget() to 156 * take a reference. this is done because there may be 157 * zero references to it and so it needs to removed from 158 * the vnode free list. 159 */ 160 int 161 procfs_allocvp(struct mount *mp, struct vnode **vpp, pid_t pid, pfstype pfs_type, int fd, struct proc *p) 162 { 163 struct pfsnode *pfs; 164 struct vnode *vp; 165 int error; 166 167 retry: 168 *vpp = procfs_hashget(pid, pfs_type, fd, mp, LK_EXCLUSIVE); 169 if (*vpp != NULL) 170 return (0); 171 172 if ((error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, &vp)) != 0) { 173 *vpp = NULL; 174 return (error); 175 } 176 pfs = malloc(sizeof(struct pfsnode), M_TEMP, M_WAITOK); 177 178 mutex_enter(&pfs_hashlock); 179 if ((*vpp = procfs_hashget(pid, pfs_type, fd, mp, 0)) != NULL) { 180 mutex_exit(&pfs_hashlock); 181 ungetnewvnode(vp); 182 free(pfs, M_TEMP); 183 goto retry; 184 } 185 186 vp->v_data = pfs; 187 pfs->pfs_pid = pid; 188 pfs->pfs_type = pfs_type; 189 pfs->pfs_vnode = vp; 190 pfs->pfs_flags = 0; 191 pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type, fd); 192 pfs->pfs_fd = fd; 193 194 switch (pfs_type) { 195 case PFSroot: /* /proc = dr-xr-xr-x */ 196 vp->v_vflag |= VV_ROOT; 197 /*FALLTHROUGH*/ 198 case PFSproc: /* /proc/N = dr-xr-xr-x */ 199 pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 200 vp->v_type = VDIR; 201 break; 202 203 case PFScurproc: /* /proc/curproc = lr-xr-xr-x */ 204 case PFSself: /* /proc/self = lr-xr-xr-x */ 205 case PFScwd: /* /proc/N/cwd = lr-xr-xr-x */ 206 case PFSchroot: /* /proc/N/chroot = lr-xr-xr-x */ 207 case PFSexe: /* /proc/N/exe = lr-xr-xr-x */ 208 pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 209 vp->v_type = VLNK; 210 break; 211 212 case PFSfd: 213 if (fd == -1) { /* /proc/N/fd = dr-xr-xr-x */ 214 pfs->pfs_mode = S_IRUSR|S_IXUSR; 215 vp->v_type = VDIR; 216 } else { /* /proc/N/fd/M = [ps-]rw------- */ 217 file_t *fp; 218 vnode_t *vxp; 219 220 if ((fp = fd_getfile2(p, pfs->pfs_fd)) == NULL) { 221 error = EBADF; 222 goto bad; 223 } 224 225 pfs->pfs_mode = S_IRUSR|S_IWUSR; 226 switch (fp->f_type) { 227 case DTYPE_VNODE: 228 vxp = fp->f_data; 229 230 /* 231 * We make symlinks for directories 232 * to avoid cycles. 233 */ 234 if (vxp->v_type == VDIR) 235 goto symlink; 236 vp->v_type = vxp->v_type; 237 break; 238 case DTYPE_PIPE: 239 vp->v_type = VFIFO; 240 break; 241 case DTYPE_SOCKET: 242 vp->v_type = VSOCK; 243 break; 244 case DTYPE_KQUEUE: 245 case DTYPE_MISC: 246 symlink: 247 pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP| 248 S_IXGRP|S_IROTH|S_IXOTH; 249 vp->v_type = VLNK; 250 break; 251 default: 252 error = EOPNOTSUPP; 253 closef(fp); 254 goto bad; 255 } 256 closef(fp); 257 } 258 break; 259 260 case PFSfile: /* /proc/N/file = -rw------- */ 261 case PFSmem: /* /proc/N/mem = -rw------- */ 262 case PFSregs: /* /proc/N/regs = -rw------- */ 263 case PFSfpregs: /* /proc/N/fpregs = -rw------- */ 264 pfs->pfs_mode = S_IRUSR|S_IWUSR; 265 vp->v_type = VREG; 266 break; 267 268 case PFSctl: /* /proc/N/ctl = --w------ */ 269 case PFSnote: /* /proc/N/note = --w------ */ 270 case PFSnotepg: /* /proc/N/notepg = --w------ */ 271 pfs->pfs_mode = S_IWUSR; 272 vp->v_type = VREG; 273 break; 274 275 case PFSmap: /* /proc/N/map = -r--r--r-- */ 276 case PFSmaps: /* /proc/N/maps = -r--r--r-- */ 277 case PFSstatus: /* /proc/N/status = -r--r--r-- */ 278 case PFSstat: /* /proc/N/stat = -r--r--r-- */ 279 case PFScmdline: /* /proc/N/cmdline = -r--r--r-- */ 280 case PFSemul: /* /proc/N/emul = -r--r--r-- */ 281 case PFSmeminfo: /* /proc/meminfo = -r--r--r-- */ 282 case PFScpustat: /* /proc/stat = -r--r--r-- */ 283 case PFSdevices: /* /proc/devices = -r--r--r-- */ 284 case PFScpuinfo: /* /proc/cpuinfo = -r--r--r-- */ 285 case PFSuptime: /* /proc/uptime = -r--r--r-- */ 286 case PFSmounts: /* /proc/mounts = -r--r--r-- */ 287 case PFSloadavg: /* /proc/loadavg = -r--r--r-- */ 288 case PFSstatm: /* /proc/N/statm = -r--r--r-- */ 289 pfs->pfs_mode = S_IRUSR|S_IRGRP|S_IROTH; 290 vp->v_type = VREG; 291 break; 292 293 #ifdef __HAVE_PROCFS_MACHDEP 294 PROCFS_MACHDEP_NODETYPE_CASES 295 procfs_machdep_allocvp(vp); 296 break; 297 #endif 298 299 default: 300 panic("procfs_allocvp"); 301 } 302 303 procfs_hashins(pfs); 304 uvm_vnp_setsize(vp, 0); 305 mutex_exit(&pfs_hashlock); 306 307 *vpp = vp; 308 return (0); 309 310 bad: 311 mutex_exit(&pfs_hashlock); 312 free(pfs, M_TEMP); 313 vp->v_data = NULL; 314 ungetnewvnode(vp); 315 return (error); 316 } 317 318 int 319 procfs_freevp(struct vnode *vp) 320 { 321 struct pfsnode *pfs = VTOPFS(vp); 322 323 procfs_hashrem(pfs); 324 325 free(vp->v_data, M_TEMP); 326 vp->v_data = NULL; 327 return (0); 328 } 329 330 int 331 procfs_rw(void *v) 332 { 333 struct vop_read_args *ap = v; 334 struct vnode *vp = ap->a_vp; 335 struct uio *uio = ap->a_uio; 336 struct lwp *curl; 337 struct lwp *l; 338 struct pfsnode *pfs = VTOPFS(vp); 339 struct proc *p; 340 int error; 341 342 if (uio->uio_offset < 0) 343 return EINVAL; 344 345 if ((error = procfs_proc_lock(pfs->pfs_pid, &p, ESRCH)) != 0) 346 return error; 347 348 curl = curlwp; 349 350 /* 351 * Do not allow init to be modified while in secure mode; it 352 * could be duped into changing the security level. 353 */ 354 #define M2K(m) ((m) == UIO_READ ? KAUTH_REQ_PROCESS_PROCFS_READ : \ 355 KAUTH_REQ_PROCESS_PROCFS_WRITE) 356 mutex_enter(p->p_lock); 357 error = kauth_authorize_process(curl->l_cred, KAUTH_PROCESS_PROCFS, 358 p, pfs, KAUTH_ARG(M2K(uio->uio_rw)), NULL); 359 mutex_exit(p->p_lock); 360 if (error) { 361 procfs_proc_unlock(p); 362 return (error); 363 } 364 #undef M2K 365 366 mutex_enter(p->p_lock); 367 LIST_FOREACH(l, &p->p_lwps, l_sibling) { 368 if (l->l_stat != LSZOMB) 369 break; 370 } 371 /* Process is exiting if no-LWPS or all LWPs are LSZOMB */ 372 if (l == NULL) { 373 mutex_exit(p->p_lock); 374 procfs_proc_unlock(p); 375 return ESRCH; 376 } 377 378 lwp_addref(l); 379 mutex_exit(p->p_lock); 380 381 switch (pfs->pfs_type) { 382 case PFSnote: 383 case PFSnotepg: 384 error = procfs_donote(curl, p, pfs, uio); 385 break; 386 387 case PFSregs: 388 error = procfs_doregs(curl, l, pfs, uio); 389 break; 390 391 case PFSfpregs: 392 error = procfs_dofpregs(curl, l, pfs, uio); 393 break; 394 395 case PFSctl: 396 error = procfs_doctl(curl, l, pfs, uio); 397 break; 398 399 case PFSstatus: 400 error = procfs_dostatus(curl, l, pfs, uio); 401 break; 402 403 case PFSstat: 404 error = procfs_do_pid_stat(curl, l, pfs, uio); 405 break; 406 407 case PFSmap: 408 error = procfs_domap(curl, p, pfs, uio, 0); 409 break; 410 411 case PFSmaps: 412 error = procfs_domap(curl, p, pfs, uio, 1); 413 break; 414 415 case PFSmem: 416 error = procfs_domem(curl, l, pfs, uio); 417 break; 418 419 case PFScmdline: 420 error = procfs_docmdline(curl, p, pfs, uio); 421 break; 422 423 case PFSmeminfo: 424 error = procfs_domeminfo(curl, p, pfs, uio); 425 break; 426 427 case PFSdevices: 428 error = procfs_dodevices(curl, p, pfs, uio); 429 break; 430 431 case PFScpuinfo: 432 error = procfs_docpuinfo(curl, p, pfs, uio); 433 break; 434 435 case PFScpustat: 436 error = procfs_docpustat(curl, p, pfs, uio); 437 break; 438 439 case PFSloadavg: 440 error = procfs_doloadavg(curl, p, pfs, uio); 441 break; 442 443 case PFSstatm: 444 error = procfs_do_pid_statm(curl, l, pfs, uio); 445 break; 446 447 case PFSfd: 448 error = procfs_dofd(curl, p, pfs, uio); 449 break; 450 451 case PFSuptime: 452 error = procfs_douptime(curl, p, pfs, uio); 453 break; 454 455 case PFSmounts: 456 error = procfs_domounts(curl, p, pfs, uio); 457 break; 458 459 case PFSemul: 460 error = procfs_doemul(curl, p, pfs, uio); 461 break; 462 463 #ifdef __HAVE_PROCFS_MACHDEP 464 PROCFS_MACHDEP_NODETYPE_CASES 465 error = procfs_machdep_rw(curl, l, pfs, uio); 466 break; 467 #endif 468 469 default: 470 error = EOPNOTSUPP; 471 break; 472 } 473 474 /* 475 * Release the references that we acquired earlier. 476 */ 477 lwp_delref(l); 478 procfs_proc_unlock(p); 479 480 return (error); 481 } 482 483 /* 484 * Get a string from userland into (bf). Strip a trailing 485 * nl character (to allow easy access from the shell). 486 * The buffer should be *buflenp + 1 chars long. vfs_getuserstr 487 * will automatically add a nul char at the end. 488 * 489 * Returns 0 on success or the following errors 490 * 491 * EINVAL: file offset is non-zero. 492 * EMSGSIZE: message is longer than kernel buffer 493 * EFAULT: user i/o buffer is not addressable 494 */ 495 int 496 vfs_getuserstr(struct uio *uio, char *bf, int *buflenp) 497 { 498 int xlen; 499 int error; 500 501 if (uio->uio_offset != 0) 502 return (EINVAL); 503 504 xlen = *buflenp; 505 506 /* must be able to read the whole string in one go */ 507 if (xlen < uio->uio_resid) 508 return (EMSGSIZE); 509 xlen = uio->uio_resid; 510 511 if ((error = uiomove(bf, xlen, uio)) != 0) 512 return (error); 513 514 /* allow multiple writes without seeks */ 515 uio->uio_offset = 0; 516 517 /* cleanup string and remove trailing newline */ 518 bf[xlen] = '\0'; 519 xlen = strlen(bf); 520 if (xlen > 0 && bf[xlen-1] == '\n') 521 bf[--xlen] = '\0'; 522 *buflenp = xlen; 523 524 return (0); 525 } 526 527 const vfs_namemap_t * 528 vfs_findname(const vfs_namemap_t *nm, const char *bf, int buflen) 529 { 530 531 for (; nm->nm_name; nm++) 532 if (memcmp(bf, nm->nm_name, buflen+1) == 0) 533 return (nm); 534 535 return (0); 536 } 537 538 /* 539 * Initialize pfsnode hash table. 540 */ 541 void 542 procfs_hashinit(void) 543 { 544 mutex_init(&pfs_hashlock, MUTEX_DEFAULT, IPL_NONE); 545 mutex_init(&pfs_ihash_lock, MUTEX_DEFAULT, IPL_NONE); 546 pfs_hashtbl = hashinit(desiredvnodes / 4, HASH_LIST, true, &pfs_ihash); 547 } 548 549 void 550 procfs_hashreinit(void) 551 { 552 struct pfsnode *pp; 553 struct pfs_hashhead *oldhash, *hash; 554 u_long i, oldmask, mask, val; 555 556 hash = hashinit(desiredvnodes / 4, HASH_LIST, true, &mask); 557 558 mutex_enter(&pfs_ihash_lock); 559 oldhash = pfs_hashtbl; 560 oldmask = pfs_ihash; 561 pfs_hashtbl = hash; 562 pfs_ihash = mask; 563 for (i = 0; i <= oldmask; i++) { 564 while ((pp = LIST_FIRST(&oldhash[i])) != NULL) { 565 LIST_REMOVE(pp, pfs_hash); 566 val = PFSPIDHASH(pp->pfs_pid); 567 LIST_INSERT_HEAD(&hash[val], pp, pfs_hash); 568 } 569 } 570 mutex_exit(&pfs_ihash_lock); 571 hashdone(oldhash, HASH_LIST, oldmask); 572 } 573 574 /* 575 * Free pfsnode hash table. 576 */ 577 void 578 procfs_hashdone(void) 579 { 580 hashdone(pfs_hashtbl, HASH_LIST, pfs_ihash); 581 mutex_destroy(&pfs_hashlock); 582 mutex_destroy(&pfs_ihash_lock); 583 } 584 585 struct vnode * 586 procfs_hashget(pid_t pid, pfstype type, int fd, struct mount *mp, int flags) 587 { 588 struct pfs_hashhead *ppp; 589 struct pfsnode *pp; 590 struct vnode *vp; 591 592 loop: 593 mutex_enter(&pfs_ihash_lock); 594 ppp = &pfs_hashtbl[PFSPIDHASH(pid)]; 595 LIST_FOREACH(pp, ppp, pfs_hash) { 596 vp = PFSTOV(pp); 597 if (pid == pp->pfs_pid && pp->pfs_type == type && 598 pp->pfs_fd == fd && vp->v_mount == mp) { 599 if (flags == 0) { 600 mutex_exit(&pfs_ihash_lock); 601 } else { 602 mutex_enter(&vp->v_interlock); 603 mutex_exit(&pfs_ihash_lock); 604 if (vget(vp, flags | LK_INTERLOCK)) 605 goto loop; 606 } 607 return (vp); 608 } 609 } 610 mutex_exit(&pfs_ihash_lock); 611 return (NULL); 612 } 613 614 /* 615 * Insert the pfsnode into the hash table and lock it. 616 */ 617 void 618 procfs_hashins(struct pfsnode *pp) 619 { 620 struct pfs_hashhead *ppp; 621 622 /* lock the pfsnode, then put it on the appropriate hash list */ 623 vlockmgr(&pp->pfs_vnode->v_lock, LK_EXCLUSIVE); 624 625 mutex_enter(&pfs_ihash_lock); 626 ppp = &pfs_hashtbl[PFSPIDHASH(pp->pfs_pid)]; 627 LIST_INSERT_HEAD(ppp, pp, pfs_hash); 628 mutex_exit(&pfs_ihash_lock); 629 } 630 631 /* 632 * Remove the pfsnode from the hash table. 633 */ 634 void 635 procfs_hashrem(struct pfsnode *pp) 636 { 637 mutex_enter(&pfs_ihash_lock); 638 LIST_REMOVE(pp, pfs_hash); 639 mutex_exit(&pfs_ihash_lock); 640 } 641 642 void 643 procfs_revoke_vnodes(struct proc *p, void *arg) 644 { 645 struct pfsnode *pfs, *pnext; 646 struct vnode *vp; 647 struct mount *mp = (struct mount *)arg; 648 struct pfs_hashhead *ppp; 649 650 if (!(p->p_flag & PK_SUGID)) 651 return; 652 653 mutex_enter(&pfs_ihash_lock); 654 ppp = &pfs_hashtbl[PFSPIDHASH(p->p_pid)]; 655 for (pfs = LIST_FIRST(ppp); pfs; pfs = pnext) { 656 vp = PFSTOV(pfs); 657 pnext = LIST_NEXT(pfs, pfs_hash); 658 mutex_enter(&vp->v_interlock); 659 if (vp->v_usecount > 0 && pfs->pfs_pid == p->p_pid && 660 vp->v_mount == mp) { 661 vp->v_usecount++; 662 mutex_exit(&vp->v_interlock); 663 mutex_exit(&pfs_ihash_lock); 664 VOP_REVOKE(vp, REVOKEALL); 665 vrele(vp); 666 mutex_enter(&pfs_ihash_lock); 667 } else { 668 mutex_exit(&vp->v_interlock); 669 } 670 } 671 mutex_exit(&pfs_ihash_lock); 672 } 673 674 int 675 procfs_proc_lock(int pid, struct proc **bunghole, int notfound) 676 { 677 struct proc *tp; 678 int error = 0; 679 680 mutex_enter(proc_lock); 681 682 if (pid == 0) 683 tp = &proc0; 684 else if ((tp = p_find(pid, PFIND_LOCKED)) == NULL) 685 error = notfound; 686 if (tp != NULL && !rw_tryenter(&tp->p_reflock, RW_READER)) 687 error = EBUSY; 688 689 mutex_exit(proc_lock); 690 691 *bunghole = tp; 692 return error; 693 } 694 695 void 696 procfs_proc_unlock(struct proc *p) 697 { 698 699 rw_exit(&p->p_reflock); 700 } 701 702 int 703 procfs_doemul(struct lwp *curl, struct proc *p, 704 struct pfsnode *pfs, struct uio *uio) 705 { 706 const char *ename = p->p_emul->e_name; 707 return uiomove_frombuf(__UNCONST(ename), strlen(ename), uio); 708 } 709