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