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