Annotation of src/sys/miscfs/procfs/procfs_subr.c, Revision 1.102.2.1
1.102.2.1! rmind 1: /* $NetBSD: procfs_subr.c,v 1.102 2012/11/25 01:03:05 christos Exp $ */
1.75 ad 2:
3: /*-
1.86 ad 4: * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
1.75 ad 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: */
1.57 agc 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: */
1.13 cgd 65:
1.1 pk 66: /*
1.20 thorpej 67: * Copyright (c) 1994 Christopher G. Demetriou. All rights reserved.
1.5 cgd 68: * Copyright (c) 1993 Jan-Simon Pendry
1.2 pk 69: *
1.5 cgd 70: * This code is derived from software contributed to Berkeley by
71: * Jan-Simon Pendry.
72: *
1.2 pk 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:
1.5 cgd 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.
1.2 pk 100: *
1.23 fvdl 101: * @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95
1.1 pk 102: */
1.39 lukem 103:
104: #include <sys/cdefs.h>
1.102.2.1! rmind 105: __KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.102 2012/11/25 01:03:05 christos Exp $");
1.5 cgd 106:
1.4 mycroft 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>
1.11 mycroft 113: #include <sys/malloc.h>
1.18 mycroft 114: #include <sys/stat.h>
1.42 christos 115: #include <sys/file.h>
116: #include <sys/filedesc.h>
1.73 elad 117: #include <sys/kauth.h>
1.18 mycroft 118:
1.5 cgd 119: #include <miscfs/procfs/procfs.h>
1.1 pk 120:
1.65 xtraeme 121: void procfs_hashins(struct pfsnode *);
122: void procfs_hashrem(struct pfsnode *);
1.102.2.1! rmind 123: struct vnode *procfs_hashget(pid_t, pfstype, int, struct mount *);
1.29 fvdl 124:
125: LIST_HEAD(pfs_hashhead, pfsnode) *pfs_hashtbl;
1.30 fvdl 126: u_long pfs_ihash; /* size of hash table - 1 */
1.38 chs 127: #define PFSPIDHASH(pid) ((pid) & pfs_ihash)
1.29 fvdl 128:
1.76 ad 129: kmutex_t pfs_hashlock;
130: kmutex_t pfs_ihash_lock;
1.1 pk 131:
1.20 thorpej 132: #define ISSET(t, f) ((t) & (f))
133:
1.1 pk 134: /*
1.5 cgd 135: * allocate a pfsnode/vnode pair. the vnode is
1.27 wrstuden 136: * referenced, and locked.
1.5 cgd 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.
1.1 pk 159: */
1.11 mycroft 160: int
1.99 rmind 161: procfs_allocvp(struct mount *mp, struct vnode **vpp, pid_t pid,
162: pfstype pfs_type, int fd, struct proc *p)
1.1 pk 163: {
1.12 mycroft 164: struct pfsnode *pfs;
165: struct vnode *vp;
1.5 cgd 166: int error;
167:
1.102.2.1! rmind 168: *vpp = procfs_hashget(pid, pfs_type, fd, mp);
1.82 ad 169: if (*vpp != NULL)
1.76 ad 170: return (0);
1.1 pk 171:
1.99 rmind 172: error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, NULL, &vp);
173: if (error) {
1.29 fvdl 174: *vpp = NULL;
175: return (error);
1.5 cgd 176: }
1.93 cegger 177: pfs = malloc(sizeof(struct pfsnode), M_TEMP, M_WAITOK);
1.76 ad 178:
179: mutex_enter(&pfs_hashlock);
1.102.2.1! rmind 180: if ((*vpp = procfs_hashget(pid, pfs_type, fd, mp)) != NULL) {
1.76 ad 181: mutex_exit(&pfs_hashlock);
182: ungetnewvnode(vp);
1.93 cegger 183: free(pfs, M_TEMP);
1.102.2.1! rmind 184: return 0;
1.76 ad 185: }
1.5 cgd 186:
1.11 mycroft 187: vp->v_data = pfs;
1.42 christos 188: pfs->pfs_pid = pid;
1.5 cgd 189: pfs->pfs_type = pfs_type;
1.11 mycroft 190: pfs->pfs_vnode = vp;
1.5 cgd 191: pfs->pfs_flags = 0;
1.42 christos 192: pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type, fd);
193: pfs->pfs_fd = fd;
1.5 cgd 194:
195: switch (pfs_type) {
1.58 darcy 196: case PFSroot: /* /proc = dr-xr-xr-x */
1.82 ad 197: vp->v_vflag |= VV_ROOT;
1.74 christos 198: /*FALLTHROUGH*/
199: case PFSproc: /* /proc/N = dr-xr-xr-x */
1.17 mycroft 200: pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
1.11 mycroft 201: vp->v_type = VDIR;
202: break;
203:
1.101 christos 204: case PFStask: /* /proc/N/task = dr-xr-xr-x */
205: if (fd == -1) {
206: pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|
207: S_IROTH|S_IXOTH;
208: vp->v_type = VDIR;
209: break;
210: }
211: /*FALLTHROUGH*/
1.58 darcy 212: case PFScurproc: /* /proc/curproc = lr-xr-xr-x */
213: case PFSself: /* /proc/self = lr-xr-xr-x */
1.66 atatat 214: case PFScwd: /* /proc/N/cwd = lr-xr-xr-x */
215: case PFSchroot: /* /proc/N/chroot = lr-xr-xr-x */
1.70 christos 216: case PFSexe: /* /proc/N/exe = lr-xr-xr-x */
1.22 mycroft 217: pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
1.11 mycroft 218: vp->v_type = VLNK;
1.5 cgd 219: break;
220:
1.58 darcy 221: case PFSfd:
1.101 christos 222: if (fd == -1) { /* /proc/N/fd = dr-x------ */
1.52 christos 223: pfs->pfs_mode = S_IRUSR|S_IXUSR;
1.42 christos 224: vp->v_type = VDIR;
225: } else { /* /proc/N/fd/M = [ps-]rw------- */
1.86 ad 226: file_t *fp;
227: vnode_t *vxp;
1.44 jdolecek 228:
1.86 ad 229: if ((fp = fd_getfile2(p, pfs->pfs_fd)) == NULL) {
1.75 ad 230: error = EBADF;
1.44 jdolecek 231: goto bad;
1.75 ad 232: }
1.44 jdolecek 233:
1.42 christos 234: pfs->pfs_mode = S_IRUSR|S_IWUSR;
235: switch (fp->f_type) {
236: case DTYPE_VNODE:
1.86 ad 237: vxp = fp->f_data;
1.50 jdolecek 238:
1.51 christos 239: /*
1.63 perry 240: * We make symlinks for directories
1.51 christos 241: * to avoid cycles.
242: */
243: if (vxp->v_type == VDIR)
244: goto symlink;
1.42 christos 245: vp->v_type = vxp->v_type;
246: break;
247: case DTYPE_PIPE:
248: vp->v_type = VFIFO;
249: break;
250: case DTYPE_SOCKET:
251: vp->v_type = VSOCK;
1.51 christos 252: break;
253: case DTYPE_KQUEUE:
254: case DTYPE_MISC:
1.102 christos 255: case DTYPE_SEM:
1.51 christos 256: symlink:
257: pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|
258: S_IXGRP|S_IROTH|S_IXOTH;
259: vp->v_type = VLNK;
1.42 christos 260: break;
1.45 jdolecek 261: default:
1.44 jdolecek 262: error = EOPNOTSUPP;
1.86 ad 263: closef(fp);
1.44 jdolecek 264: goto bad;
1.42 christos 265: }
1.86 ad 266: closef(fp);
1.42 christos 267: }
1.5 cgd 268: break;
269:
1.58 darcy 270: case PFSfile: /* /proc/N/file = -rw------- */
271: case PFSmem: /* /proc/N/mem = -rw------- */
272: case PFSregs: /* /proc/N/regs = -rw------- */
273: case PFSfpregs: /* /proc/N/fpregs = -rw------- */
1.17 mycroft 274: pfs->pfs_mode = S_IRUSR|S_IWUSR;
1.9 cgd 275: vp->v_type = VREG;
276: break;
277:
1.58 darcy 278: case PFSctl: /* /proc/N/ctl = --w------ */
279: case PFSnote: /* /proc/N/note = --w------ */
280: case PFSnotepg: /* /proc/N/notepg = --w------ */
1.17 mycroft 281: pfs->pfs_mode = S_IWUSR;
1.6 ws 282: vp->v_type = VREG;
1.5 cgd 283: break;
284:
1.58 darcy 285: case PFSmap: /* /proc/N/map = -r--r--r-- */
286: case PFSmaps: /* /proc/N/maps = -r--r--r-- */
287: case PFSstatus: /* /proc/N/status = -r--r--r-- */
288: case PFSstat: /* /proc/N/stat = -r--r--r-- */
289: case PFScmdline: /* /proc/N/cmdline = -r--r--r-- */
1.71 christos 290: case PFSemul: /* /proc/N/emul = -r--r--r-- */
1.58 darcy 291: case PFSmeminfo: /* /proc/meminfo = -r--r--r-- */
1.80 agc 292: case PFScpustat: /* /proc/stat = -r--r--r-- */
1.69 manu 293: case PFSdevices: /* /proc/devices = -r--r--r-- */
1.58 darcy 294: case PFScpuinfo: /* /proc/cpuinfo = -r--r--r-- */
295: case PFSuptime: /* /proc/uptime = -r--r--r-- */
1.62 jdolecek 296: case PFSmounts: /* /proc/mounts = -r--r--r-- */
1.80 agc 297: case PFSloadavg: /* /proc/loadavg = -r--r--r-- */
298: case PFSstatm: /* /proc/N/statm = -r--r--r-- */
1.100 jmcneill 299: case PFSversion: /* /proc/version = -r--r--r-- */
1.17 mycroft 300: pfs->pfs_mode = S_IRUSR|S_IRGRP|S_IROTH;
1.6 ws 301: vp->v_type = VREG;
1.5 cgd 302: break;
303:
1.40 thorpej 304: #ifdef __HAVE_PROCFS_MACHDEP
305: PROCFS_MACHDEP_NODETYPE_CASES
306: procfs_machdep_allocvp(vp);
307: break;
308: #endif
309:
1.5 cgd 310: default:
1.11 mycroft 311: panic("procfs_allocvp");
1.5 cgd 312: }
1.27 wrstuden 313:
1.29 fvdl 314: procfs_hashins(pfs);
1.34 chs 315: uvm_vnp_setsize(vp, 0);
1.76 ad 316: mutex_exit(&pfs_hashlock);
1.1 pk 317:
1.44 jdolecek 318: *vpp = vp;
319: return (0);
320:
321: bad:
1.76 ad 322: mutex_exit(&pfs_hashlock);
1.93 cegger 323: free(pfs, M_TEMP);
1.82 ad 324: vp->v_data = NULL;
1.44 jdolecek 325: ungetnewvnode(vp);
1.5 cgd 326: return (error);
1.1 pk 327: }
328:
1.11 mycroft 329: int
1.94 dsl 330: procfs_freevp(struct vnode *vp)
1.1 pk 331: {
1.5 cgd 332: struct pfsnode *pfs = VTOPFS(vp);
333:
1.29 fvdl 334: procfs_hashrem(pfs);
1.1 pk 335:
1.93 cegger 336: free(vp->v_data, M_TEMP);
337: vp->v_data = NULL;
1.5 cgd 338: return (0);
1.1 pk 339: }
340:
1.11 mycroft 341: int
1.94 dsl 342: procfs_rw(void *v)
1.1 pk 343: {
1.15 christos 344: struct vop_read_args *ap = v;
1.11 mycroft 345: struct vnode *vp = ap->a_vp;
346: struct uio *uio = ap->a_uio;
1.67 christos 347: struct lwp *curl;
348: struct lwp *l;
1.56 fvdl 349: struct pfsnode *pfs = VTOPFS(vp);
1.5 cgd 350: struct proc *p;
1.73 elad 351: int error;
1.5 cgd 352:
1.59 christos 353: if (uio->uio_offset < 0)
354: return EINVAL;
1.73 elad 355:
1.75 ad 356: if ((error = procfs_proc_lock(pfs->pfs_pid, &p, ESRCH)) != 0)
357: return error;
1.73 elad 358:
359: curl = curlwp;
360:
1.59 christos 361: /*
362: * Do not allow init to be modified while in secure mode; it
363: * could be duped into changing the security level.
364: */
1.84 elad 365: #define M2K(m) ((m) == UIO_READ ? KAUTH_REQ_PROCESS_PROCFS_READ : \
366: KAUTH_REQ_PROCESS_PROCFS_WRITE)
1.88 ad 367: mutex_enter(p->p_lock);
1.84 elad 368: error = kauth_authorize_process(curl->l_cred, KAUTH_PROCESS_PROCFS,
1.73 elad 369: p, pfs, KAUTH_ARG(M2K(uio->uio_rw)), NULL);
1.88 ad 370: mutex_exit(p->p_lock);
1.75 ad 371: if (error) {
372: procfs_proc_unlock(p);
1.73 elad 373: return (error);
1.75 ad 374: }
1.73 elad 375: #undef M2K
1.67 christos 376:
1.88 ad 377: mutex_enter(p->p_lock);
1.92 skrll 378: LIST_FOREACH(l, &p->p_lwps, l_sibling) {
379: if (l->l_stat != LSZOMB)
380: break;
381: }
382: /* Process is exiting if no-LWPS or all LWPs are LSZOMB */
383: if (l == NULL) {
384: mutex_exit(p->p_lock);
385: procfs_proc_unlock(p);
386: return ESRCH;
387: }
388:
1.75 ad 389: lwp_addref(l);
1.88 ad 390: mutex_exit(p->p_lock);
1.63 perry 391:
1.19 mycroft 392: switch (pfs->pfs_type) {
1.58 darcy 393: case PFSnote:
394: case PFSnotepg:
1.75 ad 395: error = procfs_donote(curl, p, pfs, uio);
396: break;
1.5 cgd 397:
1.58 darcy 398: case PFSregs:
1.75 ad 399: error = procfs_doregs(curl, l, pfs, uio);
400: break;
1.9 cgd 401:
1.58 darcy 402: case PFSfpregs:
1.75 ad 403: error = procfs_dofpregs(curl, l, pfs, uio);
404: break;
1.5 cgd 405:
1.58 darcy 406: case PFSctl:
1.75 ad 407: error = procfs_doctl(curl, l, pfs, uio);
408: break;
1.5 cgd 409:
1.58 darcy 410: case PFSstatus:
1.75 ad 411: error = procfs_dostatus(curl, l, pfs, uio);
412: break;
1.53 christos 413:
1.58 darcy 414: case PFSstat:
1.75 ad 415: error = procfs_do_pid_stat(curl, l, pfs, uio);
416: break;
1.25 msaitoh 417:
1.58 darcy 418: case PFSmap:
1.75 ad 419: error = procfs_domap(curl, p, pfs, uio, 0);
420: break;
1.37 fvdl 421:
1.58 darcy 422: case PFSmaps:
1.75 ad 423: error = procfs_domap(curl, p, pfs, uio, 1);
424: break;
1.1 pk 425:
1.58 darcy 426: case PFSmem:
1.75 ad 427: error = procfs_domem(curl, l, pfs, uio);
428: break;
1.26 christos 429:
1.58 darcy 430: case PFScmdline:
1.75 ad 431: error = procfs_docmdline(curl, p, pfs, uio);
432: break;
1.35 fvdl 433:
1.58 darcy 434: case PFSmeminfo:
1.75 ad 435: error = procfs_domeminfo(curl, p, pfs, uio);
436: break;
1.40 thorpej 437:
1.69 manu 438: case PFSdevices:
1.75 ad 439: error = procfs_dodevices(curl, p, pfs, uio);
440: break;
1.69 manu 441:
1.58 darcy 442: case PFScpuinfo:
1.75 ad 443: error = procfs_docpuinfo(curl, p, pfs, uio);
444: break;
1.40 thorpej 445:
1.80 agc 446: case PFScpustat:
447: error = procfs_docpustat(curl, p, pfs, uio);
448: break;
449:
450: case PFSloadavg:
451: error = procfs_doloadavg(curl, p, pfs, uio);
452: break;
453:
454: case PFSstatm:
455: error = procfs_do_pid_statm(curl, l, pfs, uio);
456: break;
457:
1.58 darcy 458: case PFSfd:
1.75 ad 459: error = procfs_dofd(curl, p, pfs, uio);
460: break;
1.46 jrf 461:
1.58 darcy 462: case PFSuptime:
1.75 ad 463: error = procfs_douptime(curl, p, pfs, uio);
464: break;
1.42 christos 465:
1.62 jdolecek 466: case PFSmounts:
1.75 ad 467: error = procfs_domounts(curl, p, pfs, uio);
468: break;
1.62 jdolecek 469:
1.71 christos 470: case PFSemul:
1.75 ad 471: error = procfs_doemul(curl, p, pfs, uio);
472: break;
1.71 christos 473:
1.100 jmcneill 474: case PFSversion:
475: error = procfs_doversion(curl, p, pfs, uio);
476: break;
477:
1.40 thorpej 478: #ifdef __HAVE_PROCFS_MACHDEP
479: PROCFS_MACHDEP_NODETYPE_CASES
1.75 ad 480: error = procfs_machdep_rw(curl, l, pfs, uio);
481: break;
1.40 thorpej 482: #endif
1.1 pk 483:
1.5 cgd 484: default:
1.75 ad 485: error = EOPNOTSUPP;
486: break;
1.5 cgd 487: }
1.75 ad 488:
489: /*
490: * Release the references that we acquired earlier.
491: */
492: lwp_delref(l);
493: procfs_proc_unlock(p);
494:
495: return (error);
1.1 pk 496: }
497:
1.5 cgd 498: /*
1.64 christos 499: * Get a string from userland into (bf). Strip a trailing
1.5 cgd 500: * nl character (to allow easy access from the shell).
1.11 mycroft 501: * The buffer should be *buflenp + 1 chars long. vfs_getuserstr
1.5 cgd 502: * will automatically add a nul char at the end.
503: *
504: * Returns 0 on success or the following errors
505: *
506: * EINVAL: file offset is non-zero.
507: * EMSGSIZE: message is longer than kernel buffer
508: * EFAULT: user i/o buffer is not addressable
509: */
1.11 mycroft 510: int
1.94 dsl 511: vfs_getuserstr(struct uio *uio, char *bf, int *buflenp)
1.1 pk 512: {
1.5 cgd 513: int xlen;
514: int error;
515:
1.11 mycroft 516: if (uio->uio_offset != 0)
517: return (EINVAL);
518:
1.5 cgd 519: xlen = *buflenp;
1.1 pk 520:
1.5 cgd 521: /* must be able to read the whole string in one go */
522: if (xlen < uio->uio_resid)
523: return (EMSGSIZE);
524: xlen = uio->uio_resid;
525:
1.64 christos 526: if ((error = uiomove(bf, xlen, uio)) != 0)
1.5 cgd 527: return (error);
528:
1.11 mycroft 529: /* allow multiple writes without seeks */
530: uio->uio_offset = 0;
531:
1.5 cgd 532: /* cleanup string and remove trailing newline */
1.64 christos 533: bf[xlen] = '\0';
534: xlen = strlen(bf);
535: if (xlen > 0 && bf[xlen-1] == '\n')
536: bf[--xlen] = '\0';
1.5 cgd 537: *buflenp = xlen;
1.1 pk 538:
1.5 cgd 539: return (0);
1.1 pk 540: }
541:
1.36 jdolecek 542: const vfs_namemap_t *
1.94 dsl 543: vfs_findname(const vfs_namemap_t *nm, const char *bf, int buflen)
1.1 pk 544: {
1.11 mycroft 545:
1.5 cgd 546: for (; nm->nm_name; nm++)
1.64 christos 547: if (memcmp(bf, nm->nm_name, buflen+1) == 0)
1.5 cgd 548: return (nm);
549:
550: return (0);
1.29 fvdl 551: }
552:
553: /*
554: * Initialize pfsnode hash table.
555: */
556: void
1.95 cegger 557: procfs_hashinit(void)
1.29 fvdl 558: {
1.76 ad 559: mutex_init(&pfs_hashlock, MUTEX_DEFAULT, IPL_NONE);
560: mutex_init(&pfs_ihash_lock, MUTEX_DEFAULT, IPL_NONE);
1.90 ad 561: pfs_hashtbl = hashinit(desiredvnodes / 4, HASH_LIST, true, &pfs_ihash);
1.31 jdolecek 562: }
563:
1.38 chs 564: void
1.95 cegger 565: procfs_hashreinit(void)
1.38 chs 566: {
567: struct pfsnode *pp;
568: struct pfs_hashhead *oldhash, *hash;
1.41 thorpej 569: u_long i, oldmask, mask, val;
1.38 chs 570:
1.90 ad 571: hash = hashinit(desiredvnodes / 4, HASH_LIST, true, &mask);
1.38 chs 572:
1.76 ad 573: mutex_enter(&pfs_ihash_lock);
1.38 chs 574: oldhash = pfs_hashtbl;
575: oldmask = pfs_ihash;
576: pfs_hashtbl = hash;
577: pfs_ihash = mask;
578: for (i = 0; i <= oldmask; i++) {
579: while ((pp = LIST_FIRST(&oldhash[i])) != NULL) {
580: LIST_REMOVE(pp, pfs_hash);
581: val = PFSPIDHASH(pp->pfs_pid);
582: LIST_INSERT_HEAD(&hash[val], pp, pfs_hash);
583: }
584: }
1.76 ad 585: mutex_exit(&pfs_ihash_lock);
1.90 ad 586: hashdone(oldhash, HASH_LIST, oldmask);
1.38 chs 587: }
588:
1.31 jdolecek 589: /*
590: * Free pfsnode hash table.
591: */
592: void
1.95 cegger 593: procfs_hashdone(void)
1.31 jdolecek 594: {
1.90 ad 595: hashdone(pfs_hashtbl, HASH_LIST, pfs_ihash);
1.78 ad 596: mutex_destroy(&pfs_hashlock);
597: mutex_destroy(&pfs_ihash_lock);
1.29 fvdl 598: }
599:
600: struct vnode *
1.102.2.1! rmind 601: procfs_hashget(pid_t pid, pfstype type, int fd, struct mount *mp)
1.29 fvdl 602: {
1.38 chs 603: struct pfs_hashhead *ppp;
1.29 fvdl 604: struct pfsnode *pp;
605: struct vnode *vp;
606:
607: loop:
1.76 ad 608: mutex_enter(&pfs_ihash_lock);
1.38 chs 609: ppp = &pfs_hashtbl[PFSPIDHASH(pid)];
610: LIST_FOREACH(pp, ppp, pfs_hash) {
1.29 fvdl 611: vp = PFSTOV(pp);
612: if (pid == pp->pfs_pid && pp->pfs_type == type &&
1.42 christos 613: pp->pfs_fd == fd && vp->v_mount == mp) {
1.102.2.1! rmind 614: mutex_enter(vp->v_interlock);
! 615: mutex_exit(&pfs_ihash_lock);
! 616: if (vget(vp, 0))
! 617: goto loop;
1.29 fvdl 618: return (vp);
619: }
620: }
1.76 ad 621: mutex_exit(&pfs_ihash_lock);
1.29 fvdl 622: return (NULL);
623: }
624:
625: /*
626: * Insert the pfsnode into the hash table and lock it.
627: */
628: void
1.94 dsl 629: procfs_hashins(struct pfsnode *pp)
1.29 fvdl 630: {
631: struct pfs_hashhead *ppp;
632:
1.76 ad 633: mutex_enter(&pfs_ihash_lock);
1.38 chs 634: ppp = &pfs_hashtbl[PFSPIDHASH(pp->pfs_pid)];
1.29 fvdl 635: LIST_INSERT_HEAD(ppp, pp, pfs_hash);
1.76 ad 636: mutex_exit(&pfs_ihash_lock);
1.29 fvdl 637: }
638:
639: /*
640: * Remove the pfsnode from the hash table.
641: */
642: void
1.94 dsl 643: procfs_hashrem(struct pfsnode *pp)
1.29 fvdl 644: {
1.76 ad 645: mutex_enter(&pfs_ihash_lock);
1.29 fvdl 646: LIST_REMOVE(pp, pfs_hash);
1.76 ad 647: mutex_exit(&pfs_ihash_lock);
1.29 fvdl 648: }
649:
650: void
1.94 dsl 651: procfs_revoke_vnodes(struct proc *p, void *arg)
1.29 fvdl 652: {
653: struct pfsnode *pfs, *pnext;
654: struct vnode *vp;
655: struct mount *mp = (struct mount *)arg;
1.38 chs 656: struct pfs_hashhead *ppp;
1.29 fvdl 657:
1.77 pavel 658: if (!(p->p_flag & PK_SUGID))
1.29 fvdl 659: return;
660:
1.82 ad 661: mutex_enter(&pfs_ihash_lock);
1.38 chs 662: ppp = &pfs_hashtbl[PFSPIDHASH(p->p_pid)];
663: for (pfs = LIST_FIRST(ppp); pfs; pfs = pnext) {
1.29 fvdl 664: vp = PFSTOV(pfs);
1.38 chs 665: pnext = LIST_NEXT(pfs, pfs_hash);
1.102.2.1! rmind 666: if (pfs->pfs_pid != p->p_pid || vp->v_mount != mp)
! 667: continue;
1.99 rmind 668: mutex_enter(vp->v_interlock);
1.102.2.1! rmind 669: mutex_exit(&pfs_ihash_lock);
! 670: if (vget(vp, 0) != 0) {
1.82 ad 671: mutex_enter(&pfs_ihash_lock);
1.102.2.1! rmind 672: continue;
1.82 ad 673: }
1.102.2.1! rmind 674: VOP_REVOKE(vp, REVOKEALL);
! 675: vrele(vp);
! 676: mutex_enter(&pfs_ihash_lock);
1.29 fvdl 677: }
1.82 ad 678: mutex_exit(&pfs_ihash_lock);
1.42 christos 679: }
680:
681: int
1.75 ad 682: procfs_proc_lock(int pid, struct proc **bunghole, int notfound)
1.42 christos 683: {
1.75 ad 684: struct proc *tp;
685: int error = 0;
1.42 christos 686:
1.87 ad 687: mutex_enter(proc_lock);
1.42 christos 688:
1.75 ad 689: if (pid == 0)
690: tp = &proc0;
1.96 rmind 691: else if ((tp = proc_find(pid)) == NULL)
1.75 ad 692: error = notfound;
1.82 ad 693: if (tp != NULL && !rw_tryenter(&tp->p_reflock, RW_READER))
694: error = EBUSY;
1.75 ad 695:
1.87 ad 696: mutex_exit(proc_lock);
1.42 christos 697:
1.75 ad 698: *bunghole = tp;
699: return error;
700: }
1.49 jdolecek 701:
1.75 ad 702: void
703: procfs_proc_unlock(struct proc *p)
704: {
1.82 ad 705:
706: rw_exit(&p->p_reflock);
1.1 pk 707: }
1.71 christos 708:
709: int
1.72 christos 710: procfs_doemul(struct lwp *curl, struct proc *p,
711: struct pfsnode *pfs, struct uio *uio)
1.71 christos 712: {
713: const char *ename = p->p_emul->e_name;
714: return uiomove_frombuf(__UNCONST(ename), strlen(ename), uio);
715: }
CVSweb <webmaster@jp.NetBSD.org>