1 /* $NetBSD: procfs_subr.c,v 1.93 2008/12/17 20:51:36 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.93 2008/12/17 20:51:36 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(mp, vpp, pid, pfs_type, fd, p) 162 struct mount *mp; 163 struct vnode **vpp; 164 pid_t pid; 165 pfstype pfs_type; 166 int fd; 167 struct proc *p; 168 { 169 struct pfsnode *pfs; 170 struct vnode *vp; 171 int error; 172 173 retry: 174 *vpp = procfs_hashget(pid, pfs_type, fd, mp, LK_EXCLUSIVE); 175 if (*vpp != NULL) 176 return (0); 177 178 if ((error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, &vp)) != 0) { 179 *vpp = NULL; 180 return (error); 181 } 182 pfs = malloc(sizeof(struct pfsnode), M_TEMP, M_WAITOK); 183 184 mutex_enter(&pfs_hashlock); 185 if ((*vpp = procfs_hashget(pid, pfs_type, fd, mp, 0)) != NULL) { 186 mutex_exit(&pfs_hashlock); 187 ungetnewvnode(vp); 188 free(pfs, M_TEMP); 189 goto retry; 190 } 191 192 vp->v_data = pfs; 193 pfs->pfs_pid = pid; 194 pfs->pfs_type = pfs_type; 195 pfs->pfs_vnode = vp; 196 pfs->pfs_flags = 0; 197 pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type, fd); 198 pfs->pfs_fd = fd; 199 200 switch (pfs_type) { 201 case PFSroot: /* /proc = dr-xr-xr-x */ 202 vp->v_vflag |= VV_ROOT; 203 /*FALLTHROUGH*/ 204 case PFSproc: /* /proc/N = dr-xr-xr-x */ 205 pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 206 vp->v_type = VDIR; 207 break; 208 209 case PFScurproc: /* /proc/curproc = lr-xr-xr-x */ 210 case PFSself: /* /proc/self = lr-xr-xr-x */ 211 case PFScwd: /* /proc/N/cwd = lr-xr-xr-x */ 212 case PFSchroot: /* /proc/N/chroot = lr-xr-xr-x */ 213 case PFSexe: /* /proc/N/exe = lr-xr-xr-x */ 214 pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 215 vp->v_type = VLNK; 216 break; 217 218 case PFSfd: 219 if (fd == -1) { /* /proc/N/fd = dr-xr-xr-x */ 220 pfs->pfs_mode = S_IRUSR|S_IXUSR; 221 vp->v_type = VDIR; 222 } else { /* /proc/N/fd/M = [ps-]rw------- */ 223 file_t *fp; 224 vnode_t *vxp; 225 226 if ((fp = fd_getfile2(p, pfs->pfs_fd)) == NULL) { 227 error = EBADF; 228 goto bad; 229 } 230 231 pfs->pfs_mode = S_IRUSR|S_IWUSR; 232 switch (fp->f_type) { 233 case DTYPE_VNODE: 234 vxp = fp->f_data; 235 236 /* 237 * We make symlinks for directories 238 * to avoid cycles. 239 */ 240 if (vxp->v_type == VDIR) 241 goto symlink; 242 vp->v_type = vxp->v_type; 243 break; 244 case DTYPE_PIPE: 245 vp->v_type = VFIFO; 246 break; 247 case DTYPE_SOCKET: 248 vp->v_type = VSOCK; 249 break; 250 case DTYPE_KQUEUE: 251 case DTYPE_MISC: 252 symlink: 253 pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP| 254 S_IXGRP|S_IROTH|S_IXOTH; 255 vp->v_type = VLNK; 256 break; 257 default: 258 error = EOPNOTSUPP; 259 closef(fp); 260 goto bad; 261 } 262 closef(fp); 263 } 264 break; 265 266 case PFSfile: /* /proc/N/file = -rw------- */ 267 case PFSmem: /* /proc/N/mem = -rw------- */ 268 case PFSregs: /* /proc/N/regs = -rw------- */ 269 case PFSfpregs: /* /proc/N/fpregs = -rw------- */ 270 pfs->pfs_mode = S_IRUSR|S_IWUSR; 271 vp->v_type = VREG; 272 break; 273 274 case PFSctl: /* /proc/N/ctl = --w------ */ 275 case PFSnote: /* /proc/N/note = --w------ */ 276 case PFSnotepg: /* /proc/N/notepg = --w------ */ 277 pfs->pfs_mode = S_IWUSR; 278 vp->v_type = VREG; 279 break; 280 281 case PFSmap: /* /proc/N/map = -r--r--r-- */ 282 case PFSmaps: /* /proc/N/maps = -r--r--r-- */ 283 case PFSstatus: /* /proc/N/status = -r--r--r-- */ 284 case PFSstat: /* /proc/N/stat = -r--r--r-- */ 285 case PFScmdline: /* /proc/N/cmdline = -r--r--r-- */ 286 case PFSemul: /* /proc/N/emul = -r--r--r-- */ 287 case PFSmeminfo: /* /proc/meminfo = -r--r--r-- */ 288 case PFScpustat: /* /proc/stat = -r--r--r-- */ 289 case PFSdevices: /* /proc/devices = -r--r--r-- */ 290 case PFScpuinfo: /* /proc/cpuinfo = -r--r--r-- */ 291 case PFSuptime: /* /proc/uptime = -r--r--r-- */ 292 case PFSmounts: /* /proc/mounts = -r--r--r-- */ 293 case PFSloadavg: /* /proc/loadavg = -r--r--r-- */ 294 case PFSstatm: /* /proc/N/statm = -r--r--r-- */ 295 pfs->pfs_mode = S_IRUSR|S_IRGRP|S_IROTH; 296 vp->v_type = VREG; 297 break; 298 299 #ifdef __HAVE_PROCFS_MACHDEP 300 PROCFS_MACHDEP_NODETYPE_CASES 301 procfs_machdep_allocvp(vp); 302 break; 303 #endif 304 305 default: 306 panic("procfs_allocvp"); 307 } 308 309 procfs_hashins(pfs); 310 uvm_vnp_setsize(vp, 0); 311 mutex_exit(&pfs_hashlock); 312 313 *vpp = vp; 314 return (0); 315 316 bad: 317 mutex_exit(&pfs_hashlock); 318 free(pfs, M_TEMP); 319 vp->v_data = NULL; 320 ungetnewvnode(vp); 321 return (error); 322 } 323 324 int 325 procfs_freevp(vp) 326 struct vnode *vp; 327 { 328 struct pfsnode *pfs = VTOPFS(vp); 329 330 procfs_hashrem(pfs); 331 332 free(vp->v_data, M_TEMP); 333 vp->v_data = NULL; 334 return (0); 335 } 336 337 int 338 procfs_rw(v) 339 void *v; 340 { 341 struct vop_read_args *ap = v; 342 struct vnode *vp = ap->a_vp; 343 struct uio *uio = ap->a_uio; 344 struct lwp *curl; 345 struct lwp *l; 346 struct pfsnode *pfs = VTOPFS(vp); 347 struct proc *p; 348 int error; 349 350 if (uio->uio_offset < 0) 351 return EINVAL; 352 353 if ((error = procfs_proc_lock(pfs->pfs_pid, &p, ESRCH)) != 0) 354 return error; 355 356 curl = curlwp; 357 358 /* 359 * Do not allow init to be modified while in secure mode; it 360 * could be duped into changing the security level. 361 */ 362 #define M2K(m) ((m) == UIO_READ ? KAUTH_REQ_PROCESS_PROCFS_READ : \ 363 KAUTH_REQ_PROCESS_PROCFS_WRITE) 364 mutex_enter(p->p_lock); 365 error = kauth_authorize_process(curl->l_cred, KAUTH_PROCESS_PROCFS, 366 p, pfs, KAUTH_ARG(M2K(uio->uio_rw)), NULL); 367 mutex_exit(p->p_lock); 368 if (error) { 369 procfs_proc_unlock(p); 370 return (error); 371 } 372 #undef M2K 373 374 mutex_enter(p->p_lock); 375 LIST_FOREACH(l, &p->p_lwps, l_sibling) { 376 if (l->l_stat != LSZOMB) 377 break; 378 } 379 /* Process is exiting if no-LWPS or all LWPs are LSZOMB */ 380 if (l == NULL) { 381 mutex_exit(p->p_lock); 382 procfs_proc_unlock(p); 383 return ESRCH; 384 } 385 386 lwp_addref(l); 387 mutex_exit(p->p_lock); 388 389 switch (pfs->pfs_type) { 390 case PFSnote: 391 case PFSnotepg: 392 error = procfs_donote(curl, p, pfs, uio); 393 break; 394 395 case PFSregs: 396 error = procfs_doregs(curl, l, pfs, uio); 397 break; 398 399 case PFSfpregs: 400 error = procfs_dofpregs(curl, l, pfs, uio); 401 break; 402 403 case PFSctl: 404 error = procfs_doctl(curl, l, pfs, uio); 405 break; 406 407 case PFSstatus: 408 error = procfs_dostatus(curl, l, pfs, uio); 409 break; 410 411 case PFSstat: 412 error = procfs_do_pid_stat(curl, l, pfs, uio); 413 break; 414 415 case PFSmap: 416 error = procfs_domap(curl, p, pfs, uio, 0); 417 break; 418 419 case PFSmaps: 420 error = procfs_domap(curl, p, pfs, uio, 1); 421 break; 422 423 case PFSmem: 424 error = procfs_domem(curl, l, pfs, uio); 425 break; 426 427 case PFScmdline: 428 error = procfs_docmdline(curl, p, pfs, uio); 429 break; 430 431 case PFSmeminfo: 432 error = procfs_domeminfo(curl, p, pfs, uio); 433 break; 434 435 case PFSdevices: 436 error = procfs_dodevices(curl, p, pfs, uio); 437 break; 438 439 case PFScpuinfo: 440 error = procfs_docpuinfo(curl, p, pfs, uio); 441 break; 442 443 case PFScpustat: 444 error = procfs_docpustat(curl, p, pfs, uio); 445 break; 446 447 case PFSloadavg: 448 error = procfs_doloadavg(curl, p, pfs, uio); 449 break; 450 451 case PFSstatm: 452 error = procfs_do_pid_statm(curl, l, pfs, uio); 453 break; 454 455 case PFSfd: 456 error = procfs_dofd(curl, p, pfs, uio); 457 break; 458 459 case PFSuptime: 460 error = procfs_douptime(curl, p, pfs, uio); 461 break; 462 463 case PFSmounts: 464 error = procfs_domounts(curl, p, pfs, uio); 465 break; 466 467 case PFSemul: 468 error = procfs_doemul(curl, p, pfs, uio); 469 break; 470 471 #ifdef __HAVE_PROCFS_MACHDEP 472 PROCFS_MACHDEP_NODETYPE_CASES 473 error = procfs_machdep_rw(curl, l, pfs, uio); 474 break; 475 #endif 476 477 default: 478 error = EOPNOTSUPP; 479 break; 480 } 481 482 /* 483 * Release the references that we acquired earlier. 484 */ 485 lwp_delref(l); 486 procfs_proc_unlock(p); 487 488 return (error); 489 } 490 491 /* 492 * Get a string from userland into (bf). Strip a trailing 493 * nl character (to allow easy access from the shell). 494 * The buffer should be *buflenp + 1 chars long. vfs_getuserstr 495 * will automatically add a nul char at the end. 496 * 497 * Returns 0 on success or the following errors 498 * 499 * EINVAL: file offset is non-zero. 500 * EMSGSIZE: message is longer than kernel buffer 501 * EFAULT: user i/o buffer is not addressable 502 */ 503 int 504 vfs_getuserstr(uio, bf, buflenp) 505 struct uio *uio; 506 char *bf; 507 int *buflenp; 508 { 509 int xlen; 510 int error; 511 512 if (uio->uio_offset != 0) 513 return (EINVAL); 514 515 xlen = *buflenp; 516 517 /* must be able to read the whole string in one go */ 518 if (xlen < uio->uio_resid) 519 return (EMSGSIZE); 520 xlen = uio->uio_resid; 521 522 if ((error = uiomove(bf, xlen, uio)) != 0) 523 return (error); 524 525 /* allow multiple writes without seeks */ 526 uio->uio_offset = 0; 527 528 /* cleanup string and remove trailing newline */ 529 bf[xlen] = '\0'; 530 xlen = strlen(bf); 531 if (xlen > 0 && bf[xlen-1] == '\n') 532 bf[--xlen] = '\0'; 533 *buflenp = xlen; 534 535 return (0); 536 } 537 538 const vfs_namemap_t * 539 vfs_findname(nm, bf, buflen) 540 const vfs_namemap_t *nm; 541 const char *bf; 542 int buflen; 543 { 544 545 for (; nm->nm_name; nm++) 546 if (memcmp(bf, nm->nm_name, buflen+1) == 0) 547 return (nm); 548 549 return (0); 550 } 551 552 /* 553 * Initialize pfsnode hash table. 554 */ 555 void 556 procfs_hashinit() 557 { 558 mutex_init(&pfs_hashlock, MUTEX_DEFAULT, IPL_NONE); 559 mutex_init(&pfs_ihash_lock, MUTEX_DEFAULT, IPL_NONE); 560 pfs_hashtbl = hashinit(desiredvnodes / 4, HASH_LIST, true, &pfs_ihash); 561 } 562 563 void 564 procfs_hashreinit() 565 { 566 struct pfsnode *pp; 567 struct pfs_hashhead *oldhash, *hash; 568 u_long i, oldmask, mask, val; 569 570 hash = hashinit(desiredvnodes / 4, HASH_LIST, true, &mask); 571 572 mutex_enter(&pfs_ihash_lock); 573 oldhash = pfs_hashtbl; 574 oldmask = pfs_ihash; 575 pfs_hashtbl = hash; 576 pfs_ihash = mask; 577 for (i = 0; i <= oldmask; i++) { 578 while ((pp = LIST_FIRST(&oldhash[i])) != NULL) { 579 LIST_REMOVE(pp, pfs_hash); 580 val = PFSPIDHASH(pp->pfs_pid); 581 LIST_INSERT_HEAD(&hash[val], pp, pfs_hash); 582 } 583 } 584 mutex_exit(&pfs_ihash_lock); 585 hashdone(oldhash, HASH_LIST, oldmask); 586 } 587 588 /* 589 * Free pfsnode hash table. 590 */ 591 void 592 procfs_hashdone() 593 { 594 hashdone(pfs_hashtbl, HASH_LIST, pfs_ihash); 595 mutex_destroy(&pfs_hashlock); 596 mutex_destroy(&pfs_ihash_lock); 597 } 598 599 struct vnode * 600 procfs_hashget(pid, type, fd, mp, flags) 601 pid_t pid; 602 pfstype type; 603 int fd; 604 struct mount *mp; 605 int flags; 606 { 607 struct pfs_hashhead *ppp; 608 struct pfsnode *pp; 609 struct vnode *vp; 610 611 loop: 612 mutex_enter(&pfs_ihash_lock); 613 ppp = &pfs_hashtbl[PFSPIDHASH(pid)]; 614 LIST_FOREACH(pp, ppp, pfs_hash) { 615 vp = PFSTOV(pp); 616 if (pid == pp->pfs_pid && pp->pfs_type == type && 617 pp->pfs_fd == fd && vp->v_mount == mp) { 618 if (flags == 0) { 619 mutex_exit(&pfs_ihash_lock); 620 } else { 621 mutex_enter(&vp->v_interlock); 622 mutex_exit(&pfs_ihash_lock); 623 if (vget(vp, flags | LK_INTERLOCK)) 624 goto loop; 625 } 626 return (vp); 627 } 628 } 629 mutex_exit(&pfs_ihash_lock); 630 return (NULL); 631 } 632 633 /* 634 * Insert the pfsnode into the hash table and lock it. 635 */ 636 void 637 procfs_hashins(pp) 638 struct pfsnode *pp; 639 { 640 struct pfs_hashhead *ppp; 641 642 /* lock the pfsnode, then put it on the appropriate hash list */ 643 vlockmgr(&pp->pfs_vnode->v_lock, LK_EXCLUSIVE); 644 645 mutex_enter(&pfs_ihash_lock); 646 ppp = &pfs_hashtbl[PFSPIDHASH(pp->pfs_pid)]; 647 LIST_INSERT_HEAD(ppp, pp, pfs_hash); 648 mutex_exit(&pfs_ihash_lock); 649 } 650 651 /* 652 * Remove the pfsnode from the hash table. 653 */ 654 void 655 procfs_hashrem(pp) 656 struct pfsnode *pp; 657 { 658 mutex_enter(&pfs_ihash_lock); 659 LIST_REMOVE(pp, pfs_hash); 660 mutex_exit(&pfs_ihash_lock); 661 } 662 663 void 664 procfs_revoke_vnodes(p, arg) 665 struct proc *p; 666 void *arg; 667 { 668 struct pfsnode *pfs, *pnext; 669 struct vnode *vp; 670 struct mount *mp = (struct mount *)arg; 671 struct pfs_hashhead *ppp; 672 673 if (!(p->p_flag & PK_SUGID)) 674 return; 675 676 mutex_enter(&pfs_ihash_lock); 677 ppp = &pfs_hashtbl[PFSPIDHASH(p->p_pid)]; 678 for (pfs = LIST_FIRST(ppp); pfs; pfs = pnext) { 679 vp = PFSTOV(pfs); 680 pnext = LIST_NEXT(pfs, pfs_hash); 681 mutex_enter(&vp->v_interlock); 682 if (vp->v_usecount > 0 && pfs->pfs_pid == p->p_pid && 683 vp->v_mount == mp) { 684 vp->v_usecount++; 685 mutex_exit(&vp->v_interlock); 686 mutex_exit(&pfs_ihash_lock); 687 VOP_REVOKE(vp, REVOKEALL); 688 vrele(vp); 689 mutex_enter(&pfs_ihash_lock); 690 } else { 691 mutex_exit(&vp->v_interlock); 692 } 693 } 694 mutex_exit(&pfs_ihash_lock); 695 } 696 697 int 698 procfs_proc_lock(int pid, struct proc **bunghole, int notfound) 699 { 700 struct proc *tp; 701 int error = 0; 702 703 mutex_enter(proc_lock); 704 705 if (pid == 0) 706 tp = &proc0; 707 else if ((tp = p_find(pid, PFIND_LOCKED)) == NULL) 708 error = notfound; 709 if (tp != NULL && !rw_tryenter(&tp->p_reflock, RW_READER)) 710 error = EBUSY; 711 712 mutex_exit(proc_lock); 713 714 *bunghole = tp; 715 return error; 716 } 717 718 void 719 procfs_proc_unlock(struct proc *p) 720 { 721 722 rw_exit(&p->p_reflock); 723 } 724 725 int 726 procfs_doemul(struct lwp *curl, struct proc *p, 727 struct pfsnode *pfs, struct uio *uio) 728 { 729 const char *ename = p->p_emul->e_name; 730 return uiomove_frombuf(__UNCONST(ename), strlen(ename), uio); 731 } 732