Home | History | Annotate | Line # | Download | only in procfs
procfs_vnops.c revision 1.17
      1   1.1       pk /*
      2   1.9      cgd  * Copyright (c) 1993 The Regents of the University of California.
      3   1.9      cgd  * Copyright (c) 1993 Jan-Simon Pendry
      4   1.2       pk  * All rights reserved.
      5   1.2       pk  *
      6   1.9      cgd  * This code is derived from software contributed to Berkeley by
      7   1.9      cgd  * Jan-Simon Pendry.
      8   1.9      cgd  *
      9   1.2       pk  * Redistribution and use in source and binary forms, with or without
     10   1.2       pk  * modification, are permitted provided that the following conditions
     11   1.2       pk  * are met:
     12   1.2       pk  * 1. Redistributions of source code must retain the above copyright
     13   1.2       pk  *    notice, this list of conditions and the following disclaimer.
     14   1.2       pk  * 2. Redistributions in binary form must reproduce the above copyright
     15   1.2       pk  *    notice, this list of conditions and the following disclaimer in the
     16   1.2       pk  *    documentation and/or other materials provided with the distribution.
     17   1.2       pk  * 3. All advertising materials mentioning features or use of this software
     18   1.2       pk  *    must display the following acknowledgement:
     19   1.9      cgd  *	This product includes software developed by the University of
     20   1.9      cgd  *	California, Berkeley and its contributors.
     21   1.9      cgd  * 4. Neither the name of the University nor the names of its contributors
     22   1.9      cgd  *    may be used to endorse or promote products derived from this software
     23   1.9      cgd  *    without specific prior written permission.
     24   1.9      cgd  *
     25   1.9      cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     26   1.9      cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     27   1.9      cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     28   1.9      cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     29   1.9      cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     30   1.9      cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     31   1.9      cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     32   1.9      cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     33   1.9      cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     34   1.9      cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     35   1.9      cgd  * SUCH DAMAGE.
     36   1.2       pk  *
     37   1.9      cgd  * From:
     38   1.9      cgd  *	Id: procfs_vnops.c,v 4.2 1994/01/02 15:28:44 jsp Exp
     39   1.9      cgd  *
     40  1.17  mycroft  *	$Id: procfs_vnops.c,v 1.17 1994/02/15 13:32:39 mycroft Exp $
     41   1.2       pk  */
     42   1.2       pk 
     43   1.2       pk /*
     44   1.9      cgd  * procfs vnode interface
     45   1.1       pk  */
     46   1.1       pk 
     47   1.8  mycroft #include <sys/param.h>
     48   1.8  mycroft #include <sys/systm.h>
     49   1.8  mycroft #include <sys/time.h>
     50   1.8  mycroft #include <sys/kernel.h>
     51   1.8  mycroft #include <sys/file.h>
     52   1.8  mycroft #include <sys/proc.h>
     53   1.8  mycroft #include <sys/vnode.h>
     54   1.8  mycroft #include <sys/namei.h>
     55   1.9      cgd #include <sys/malloc.h>
     56   1.8  mycroft #include <sys/resourcevar.h>
     57  1.14      cgd #include <sys/ptrace.h>
     58   1.9      cgd #include <miscfs/procfs/procfs.h>
     59   1.9      cgd #include <vm/vm.h>	/* for page_size */
     60   1.1       pk 
     61  1.11      cgd #include <machine/reg.h>
     62  1.11      cgd 
     63   1.9      cgd /*
     64   1.9      cgd  * Vnode Operations.
     65   1.9      cgd  *
     66   1.9      cgd  */
     67   1.1       pk 
     68   1.1       pk /*
     69   1.9      cgd  * This is a list of the valid names in the
     70   1.9      cgd  * process-specific sub-directories.  It is
     71   1.9      cgd  * used in procfs_lookup and procfs_readdir
     72   1.9      cgd  */
     73   1.9      cgd static struct pfsnames {
     74   1.9      cgd 	u_short	d_namlen;
     75   1.9      cgd 	char	d_name[PROCFS_NAMELEN];
     76   1.9      cgd 	pfstype	d_pfstype;
     77   1.9      cgd } procent[] = {
     78   1.9      cgd #define N(s) sizeof(s)-1, s
     79   1.9      cgd 	/* namlen, nam, type */
     80  1.12       ws 	{  N("."),	Pproc },
     81  1.12       ws 	{  N(".."),	Proot },
     82  1.17  mycroft 	{  N("file"),	Pfile },
     83   1.9      cgd 	{  N("mem"),    Pmem },
     84   1.9      cgd 	{  N("regs"),   Pregs },
     85  1.14      cgd 	{  N("fpregs"), Pfpregs },
     86   1.9      cgd 	{  N("ctl"),    Pctl },
     87   1.9      cgd 	{  N("status"), Pstatus },
     88   1.9      cgd 	{  N("note"),   Pnote },
     89   1.9      cgd 	{  N("notepg"), Pnotepg },
     90   1.9      cgd #undef N
     91   1.1       pk };
     92   1.9      cgd #define Nprocent (sizeof(procent)/sizeof(procent[0]))
     93   1.9      cgd 
     94  1.12       ws #define	PROCFS_XFILES	3	/* number of other entries, like "curproc" */
     95  1.12       ws 
     96   1.9      cgd static pid_t atopid __P((const char *, u_int));
     97   1.1       pk 
     98   1.1       pk /*
     99   1.9      cgd  * set things up for doing i/o on
    100   1.9      cgd  * the pfsnode (vp).  (vp) is locked
    101   1.9      cgd  * on entry, and should be left locked
    102   1.9      cgd  * on exit.
    103   1.1       pk  *
    104   1.9      cgd  * for procfs we don't need to do anything
    105   1.9      cgd  * in particular for i/o.  all that is done
    106   1.9      cgd  * is to support exclusive open on process
    107   1.9      cgd  * memory images.
    108   1.1       pk  */
    109   1.9      cgd procfs_open(vp, mode, cred, p)
    110   1.9      cgd 	struct vnode *vp;
    111   1.1       pk 	int mode;
    112   1.1       pk 	struct ucred *cred;
    113   1.1       pk 	struct proc *p;
    114   1.1       pk {
    115   1.9      cgd 	struct pfsnode *pfs = VTOPFS(vp);
    116   1.9      cgd 
    117   1.9      cgd 	switch (pfs->pfs_type) {
    118   1.9      cgd 	case Pmem:
    119   1.9      cgd 		if (PFIND(pfs->pfs_pid) == 0)
    120   1.9      cgd 			return (ENOENT);	/* was ESRCH, jsp */
    121   1.9      cgd 
    122   1.9      cgd 		if ((pfs->pfs_flags & FWRITE) && (mode & O_EXCL) ||
    123   1.9      cgd 				(pfs->pfs_flags & O_EXCL) && (mode & FWRITE))
    124   1.9      cgd 			return (EBUSY);
    125   1.1       pk 
    126   1.1       pk 
    127   1.9      cgd 		if (mode & FWRITE)
    128   1.9      cgd 			pfs->pfs_flags = (mode & (FWRITE|O_EXCL));
    129   1.1       pk 
    130   1.9      cgd 		return (0);
    131   1.1       pk 
    132   1.9      cgd 	default:
    133   1.9      cgd 		break;
    134   1.9      cgd 	}
    135   1.1       pk 
    136   1.9      cgd 	return (0);
    137   1.1       pk }
    138   1.1       pk 
    139   1.1       pk /*
    140   1.9      cgd  * close the pfsnode (vp) after doing i/o.
    141   1.9      cgd  * (vp) is not locked on entry or exit.
    142   1.9      cgd  *
    143   1.9      cgd  * nothing to do for procfs other than undo
    144   1.9      cgd  * any exclusive open flag (see _open above).
    145   1.1       pk  */
    146   1.9      cgd procfs_close(vp, flag, cred, p)
    147   1.9      cgd 	struct vnode *vp;
    148   1.1       pk 	int flag;
    149   1.1       pk 	struct ucred *cred;
    150   1.1       pk 	struct proc *p;
    151   1.1       pk {
    152   1.9      cgd 	struct pfsnode *pfs = VTOPFS(vp);
    153   1.1       pk 
    154   1.9      cgd 	switch (pfs->pfs_type) {
    155   1.9      cgd 	case Pmem:
    156   1.9      cgd 		if ((flag & FWRITE) && (pfs->pfs_flags & O_EXCL))
    157   1.9      cgd 			pfs->pfs_flags &= ~(FWRITE|O_EXCL);
    158   1.9      cgd 		break;
    159   1.9      cgd 	}
    160   1.1       pk 
    161   1.1       pk 	return (0);
    162   1.1       pk }
    163   1.1       pk 
    164   1.1       pk /*
    165   1.9      cgd  * do an ioctl operation on pfsnode (vp).
    166   1.9      cgd  * (vp) is not locked on entry or exit.
    167   1.1       pk  */
    168   1.9      cgd procfs_ioctl(vp, com, data, fflag, cred, p)
    169   1.1       pk 	struct vnode *vp;
    170   1.1       pk 	int com;
    171   1.1       pk 	caddr_t data;
    172   1.1       pk 	int fflag;
    173   1.1       pk 	struct ucred *cred;
    174   1.1       pk 	struct proc *p;
    175   1.1       pk {
    176   1.1       pk 
    177   1.9      cgd 	return (ENOTTY);
    178   1.1       pk }
    179   1.1       pk 
    180   1.1       pk /*
    181   1.9      cgd  * do block mapping for pfsnode (vp).
    182   1.9      cgd  * since we don't use the buffer cache
    183   1.9      cgd  * for procfs this function should never
    184   1.9      cgd  * be called.  in any case, it's not clear
    185   1.9      cgd  * what part of the kernel ever makes use
    186   1.9      cgd  * of this function.  for sanity, this is the
    187   1.9      cgd  * usual no-op bmap, although returning
    188   1.9      cgd  * (EIO) would be a reasonable alternative.
    189   1.1       pk  */
    190   1.9      cgd procfs_bmap(vp, bn, vpp, bnp)
    191   1.1       pk 	struct vnode *vp;
    192   1.1       pk 	daddr_t bn;
    193   1.1       pk 	struct vnode **vpp;
    194   1.1       pk 	daddr_t *bnp;
    195   1.1       pk {
    196   1.1       pk 
    197   1.1       pk 	if (vpp != NULL)
    198   1.1       pk 		*vpp = vp;
    199   1.1       pk 	if (bnp != NULL)
    200   1.1       pk 		*bnp = bn;
    201   1.1       pk 	return (0);
    202   1.1       pk }
    203   1.1       pk 
    204   1.1       pk /*
    205   1.9      cgd  * _inactive is called when the pfsnode
    206   1.9      cgd  * is vrele'd and the reference count goes
    207   1.9      cgd  * to zero.  (vp) will be on the vnode free
    208   1.9      cgd  * list, so to get it back vget() must be
    209   1.9      cgd  * used.
    210   1.9      cgd  *
    211   1.9      cgd  * for procfs, check if the process is still
    212   1.9      cgd  * alive and if it isn't then just throw away
    213   1.9      cgd  * the vnode by calling vgone().  this may
    214   1.9      cgd  * be overkill and a waste of time since the
    215   1.9      cgd  * chances are that the process will still be
    216   1.9      cgd  * there and PFIND is not free.
    217   1.9      cgd  *
    218   1.9      cgd  * (vp) is not locked on entry or exit.
    219   1.1       pk  */
    220   1.9      cgd procfs_inactive(vp, p)
    221   1.1       pk 	struct vnode *vp;
    222   1.1       pk 	struct proc *p;
    223   1.1       pk {
    224   1.9      cgd 	struct pfsnode *pfs = VTOPFS(vp);
    225   1.1       pk 
    226   1.9      cgd 	if (PFIND(pfs->pfs_pid) == 0)
    227   1.1       pk 		vgone(vp);
    228   1.5       pk 
    229   1.9      cgd 	return (0);
    230   1.1       pk }
    231   1.1       pk 
    232   1.1       pk /*
    233   1.9      cgd  * _reclaim is called when getnewvnode()
    234   1.9      cgd  * wants to make use of an entry on the vnode
    235   1.9      cgd  * free list.  at this time the filesystem needs
    236   1.9      cgd  * to free any private data and remove the node
    237   1.9      cgd  * from any private lists.
    238   1.1       pk  */
    239   1.9      cgd procfs_reclaim(vp)
    240   1.1       pk 	struct vnode *vp;
    241   1.1       pk {
    242   1.9      cgd 	int error;
    243   1.1       pk 
    244   1.9      cgd 	error = procfs_freevp(vp);
    245   1.9      cgd 	return (error);
    246   1.1       pk }
    247   1.1       pk 
    248   1.1       pk /*
    249   1.9      cgd  * _print is used for debugging.
    250   1.9      cgd  * just print a readable description
    251   1.9      cgd  * of (vp).
    252   1.1       pk  */
    253   1.9      cgd procfs_print(vp)
    254   1.1       pk 	struct vnode *vp;
    255   1.1       pk {
    256   1.9      cgd 	struct pfsnode *pfs = VTOPFS(vp);
    257   1.5       pk 
    258   1.9      cgd 	printf("tag VT_PROCFS, pid %d, mode %x, flags %x\n",
    259   1.9      cgd 		pfs->pfs_pid,
    260   1.9      cgd 		pfs->pfs_mode, pfs->pfs_flags);
    261   1.1       pk }
    262   1.1       pk 
    263   1.1       pk /*
    264   1.9      cgd  * _abortop is called when operations such as
    265   1.9      cgd  * rename and create fail.  this entry is responsible
    266   1.9      cgd  * for undoing any side-effects caused by the lookup.
    267   1.9      cgd  * this will always include freeing the pathname buffer.
    268   1.1       pk  */
    269   1.9      cgd procfs_abortop(ndp)
    270   1.9      cgd 	struct nameidata *ndp;
    271   1.1       pk {
    272   1.9      cgd 
    273   1.9      cgd 	if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF)
    274   1.9      cgd 		FREE(ndp->ni_pnbuf, M_NAMEI);
    275   1.9      cgd 	return (0);
    276   1.1       pk }
    277   1.1       pk 
    278   1.1       pk /*
    279   1.9      cgd  * generic entry point for unsupported operations
    280   1.1       pk  */
    281   1.9      cgd procfs_badop()
    282   1.1       pk {
    283   1.1       pk 
    284   1.9      cgd 	return (EIO);
    285   1.1       pk }
    286   1.1       pk 
    287   1.1       pk /*
    288   1.9      cgd  * Invent attributes for pfsnode (vp) and store
    289   1.9      cgd  * them in (vap).
    290   1.9      cgd  * Directories lengths are returned as zero since
    291   1.9      cgd  * any real length would require the genuine size
    292   1.9      cgd  * to be computed, and nothing cares anyway.
    293   1.9      cgd  *
    294   1.9      cgd  * this is relatively minimal for procfs.
    295   1.1       pk  */
    296   1.9      cgd procfs_getattr(vp, vap, cred, p)
    297   1.1       pk 	struct vnode *vp;
    298   1.1       pk 	struct vattr *vap;
    299   1.1       pk 	struct ucred *cred;
    300   1.1       pk 	struct proc *p;
    301   1.1       pk {
    302   1.9      cgd 	struct pfsnode *pfs = VTOPFS(vp);
    303   1.1       pk 	struct proc *procp;
    304   1.9      cgd 	int error;
    305   1.1       pk 
    306   1.9      cgd 	/* start by zeroing out the attributes */
    307   1.1       pk 	VATTR_NULL(vap);
    308   1.9      cgd 
    309   1.9      cgd 	/* next do all the common fields */
    310   1.1       pk 	vap->va_type = vp->v_type;
    311   1.9      cgd 	vap->va_mode = pfs->pfs_mode;
    312   1.9      cgd 	vap->va_fileid = pfs->pfs_fileno;
    313   1.9      cgd 	vap->va_flags = 0;
    314   1.9      cgd 	vap->va_blocksize = page_size;
    315   1.9      cgd 	vap->va_bytes = vap->va_size = 0;
    316   1.9      cgd 
    317   1.9      cgd 	/*
    318   1.9      cgd 	 * Make all times be current TOD.
    319   1.9      cgd 	 * It would be possible to get the process start
    320   1.9      cgd 	 * time from the p_stat structure, but there's
    321   1.9      cgd 	 * no "file creation" time stamp anyway, and the
    322   1.9      cgd 	 * p_stat structure is not addressible if u. gets
    323   1.9      cgd 	 * swapped out for that process.
    324   1.9      cgd 	 */
    325   1.9      cgd 	microtime(&vap->va_ctime);
    326   1.9      cgd 	vap->va_atime = vap->va_mtime = vap->va_ctime;
    327   1.9      cgd 
    328  1.12       ws 	error = 0;
    329  1.12       ws 
    330  1.12       ws 	if (pfs->pfs_type != Proot) {
    331  1.12       ws 		/* check the process still exists */
    332  1.12       ws 		procp = PFIND(pfs->pfs_pid);
    333  1.12       ws 		if (procp == 0)
    334  1.12       ws 			return (ENOENT);
    335  1.12       ws 		/* most of the time we want these values */
    336  1.12       ws 		vap->va_nlink = 1;
    337  1.12       ws 		vap->va_uid = procp->p_ucred->cr_uid;
    338  1.12       ws 		vap->va_gid = procp->p_ucred->cr_gid;
    339  1.12       ws 	}
    340  1.12       ws 
    341   1.9      cgd 	/*
    342   1.9      cgd 	 * now do the object specific fields
    343   1.9      cgd 	 *
    344   1.9      cgd 	 * The size could be set from struct reg, but it's hardly
    345   1.9      cgd 	 * worth the trouble, and it puts some (potentially) machine
    346   1.9      cgd 	 * dependent data into this machine-independent code.  If it
    347   1.9      cgd 	 * becomes important then this function should break out into
    348   1.9      cgd 	 * a per-file stat function in the corresponding .c file.
    349   1.9      cgd 	 */
    350   1.1       pk 
    351   1.9      cgd 	switch (pfs->pfs_type) {
    352   1.9      cgd 	case Proot:
    353  1.12       ws 		switch ((int)pfs->pfs_pid) {
    354  1.12       ws 		case 0:		/* /proc */
    355  1.12       ws 			vap->va_nlink = 2;
    356  1.12       ws 			vap->va_uid = 0;
    357  1.12       ws 			vap->va_gid = 0;
    358  1.12       ws 			vap->va_bytes = vap->va_size
    359  1.12       ws 				= (maxproc + 1 + PROCFS_XFILES) * UIO_MX;
    360  1.12       ws 			break;
    361  1.12       ws 		case 1:		/* /proc/curproc */
    362  1.12       ws 			vap->va_nlink = 1;
    363  1.12       ws 			vap->va_uid = 0;
    364  1.12       ws 			vap->va_gid = 0;
    365  1.12       ws 			break;
    366  1.12       ws 		default:
    367  1.12       ws 			panic("procfs_getattr root");
    368  1.12       ws 		}
    369   1.9      cgd 		break;
    370   1.9      cgd 
    371   1.9      cgd 	case Pproc:
    372   1.9      cgd 		vap->va_nlink = 2;
    373  1.12       ws 		vap->va_bytes = vap->va_size = Nprocent * UIO_MX;
    374   1.9      cgd 		break;
    375   1.9      cgd 
    376   1.9      cgd 	case Pmem:
    377   1.9      cgd 		vap->va_bytes = vap->va_size =
    378   1.9      cgd 			ctob(procp->p_vmspace->vm_tsize +
    379   1.9      cgd 				    procp->p_vmspace->vm_dsize +
    380   1.9      cgd 				    procp->p_vmspace->vm_ssize);
    381   1.9      cgd 		break;
    382   1.9      cgd 
    383   1.9      cgd 	case Pregs:
    384  1.14      cgd #if defined(PT_GETREGS) || defined(PT_SETREGS)
    385  1.11      cgd 		vap->va_bytes = vap->va_size = sizeof(struct reg);
    386  1.14      cgd #else
    387  1.14      cgd 		vap->va_bytes = vap->va_size = 0;
    388  1.14      cgd #endif
    389  1.14      cgd 		break;
    390  1.14      cgd 
    391  1.14      cgd 	case Pfpregs:
    392  1.14      cgd #if defined(PT_GETFPREGS) || defined(PT_SETFPREGS)
    393  1.14      cgd 		vap->va_bytes = vap->va_size = sizeof(struct fpreg);
    394  1.14      cgd #else
    395  1.14      cgd 		vap->va_bytes = vap->va_size = 0;
    396  1.14      cgd #endif
    397  1.12       ws 		break;
    398  1.12       ws 
    399  1.12       ws 	case Pstatus:
    400  1.12       ws 		vap->va_bytes = vap->va_size = 256;	/* only a maximum */
    401  1.12       ws 		break;
    402  1.12       ws 
    403   1.9      cgd 	case Pctl:
    404  1.13       ws 		vap->va_bytes = vap->va_size = PROCFS_CTLLEN;
    405  1.12       ws 		break;
    406  1.12       ws 
    407   1.9      cgd 	case Pnote:
    408  1.13       ws 		vap->va_bytes = vap->va_size = PROCFS_NOTELEN;
    409  1.13       ws 		break;
    410  1.13       ws 
    411   1.9      cgd 	case Pnotepg:
    412   1.9      cgd 		break;
    413   1.1       pk 
    414   1.9      cgd 	default:
    415  1.12       ws 		panic("procfs_getattr type");
    416   1.1       pk 	}
    417   1.1       pk 
    418   1.9      cgd 	return (error);
    419   1.1       pk }
    420   1.1       pk 
    421   1.9      cgd procfs_setattr(vp, vap, cred, p)
    422   1.5       pk 	struct vnode *vp;
    423   1.5       pk 	struct vattr *vap;
    424   1.5       pk 	struct ucred *cred;
    425   1.5       pk 	struct proc *p;
    426   1.5       pk {
    427   1.5       pk 	/*
    428   1.9      cgd 	 * just fake out attribute setting
    429   1.9      cgd 	 * it's not good to generate an error
    430   1.9      cgd 	 * return, otherwise things like creat()
    431   1.9      cgd 	 * will fail when they try to set the
    432   1.9      cgd 	 * file length to 0.  worse, this means
    433   1.9      cgd 	 * that echo $note > /proc/$pid/note will fail.
    434   1.5       pk 	 */
    435   1.5       pk 
    436   1.9      cgd 	return (0);
    437   1.5       pk }
    438   1.5       pk 
    439   1.9      cgd /*
    440   1.9      cgd  * implement access checking.
    441   1.9      cgd  *
    442   1.9      cgd  * something very similar to this code is duplicated
    443   1.9      cgd  * throughout the 4bsd kernel and should be moved
    444   1.9      cgd  * into kern/vfs_subr.c sometime.
    445   1.9      cgd  *
    446   1.9      cgd  * actually, the check for super-user is slightly
    447   1.9      cgd  * broken since it will allow read access to write-only
    448   1.9      cgd  * objects.  this doesn't cause any particular trouble
    449   1.9      cgd  * but does mean that the i/o entry points need to check
    450   1.9      cgd  * that the operation really does make sense.
    451   1.9      cgd  */
    452   1.9      cgd procfs_access(vp, mode, cred, p)
    453   1.1       pk 	struct vnode *vp;
    454   1.1       pk 	int mode;
    455   1.1       pk 	struct ucred *cred;
    456   1.1       pk 	struct proc *p;
    457   1.1       pk {
    458   1.9      cgd 	struct vattr *vap;
    459   1.1       pk 	struct vattr vattr;
    460   1.1       pk 	int error;
    461   1.1       pk 
    462   1.1       pk 	/*
    463   1.1       pk 	 * If you're the super-user,
    464   1.1       pk 	 * you always get access.
    465   1.1       pk 	 */
    466   1.9      cgd 	if (cred->cr_uid == (uid_t) 0)
    467   1.1       pk 		return (0);
    468   1.1       pk 	vap = &vattr;
    469   1.9      cgd 	if (error = VOP_GETATTR(vp, vap, cred, p))
    470   1.1       pk 		return (error);
    471   1.9      cgd 
    472   1.1       pk 	/*
    473   1.1       pk 	 * Access check is based on only one of owner, group, public.
    474   1.1       pk 	 * If not owner, then check group. If not a member of the
    475   1.1       pk 	 * group, then check public access.
    476   1.1       pk 	 */
    477   1.1       pk 	if (cred->cr_uid != vap->va_uid) {
    478   1.9      cgd 		gid_t *gp;
    479   1.9      cgd 		int i;
    480   1.9      cgd 
    481   1.1       pk 		mode >>= 3;
    482   1.1       pk 		gp = cred->cr_groups;
    483   1.1       pk 		for (i = 0; i < cred->cr_ngroups; i++, gp++)
    484   1.1       pk 			if (vap->va_gid == *gp)
    485   1.1       pk 				goto found;
    486   1.1       pk 		mode >>= 3;
    487   1.1       pk found:
    488   1.1       pk 		;
    489   1.1       pk 	}
    490   1.9      cgd 
    491   1.9      cgd 	if ((vap->va_mode & mode) == mode)
    492   1.1       pk 		return (0);
    493   1.9      cgd 
    494   1.1       pk 	return (EACCES);
    495   1.1       pk }
    496   1.1       pk 
    497   1.1       pk /*
    498   1.9      cgd  * lookup.  this is incredibly complicated in the
    499   1.9      cgd  * general case, however for most pseudo-filesystems
    500   1.9      cgd  * very little needs to be done.
    501   1.9      cgd  *
    502   1.9      cgd  * (dvp) is the directory in which the lookup takes place.
    503   1.9      cgd  * (ndp) contains all the information about the type of
    504   1.9      cgd  *       lookup being done.
    505   1.9      cgd  *
    506   1.9      cgd  * (dvp) is locked on entry.
    507   1.9      cgd  * the job of lookup is to set ndp->ni_dvp, and ndp->ni_vp.
    508   1.9      cgd  * (this changes in 4.4 where all we want is the equivalent
    509   1.9      cgd  * of ndp->ni_vp.)
    510   1.9      cgd  *
    511   1.9      cgd  * unless you want to get a migraine, just make sure your
    512   1.9      cgd  * filesystem doesn't do any locking of its own.  otherwise
    513   1.9      cgd  * read and inwardly digest ufs_lookup().
    514   1.9      cgd  */
    515   1.9      cgd procfs_lookup(dvp, ndp, p)
    516   1.9      cgd 	struct vnode *dvp;
    517   1.9      cgd 	struct nameidata *ndp;
    518   1.1       pk 	struct proc *p;
    519   1.1       pk {
    520   1.9      cgd 	char *pname = ndp->ni_ptr;
    521   1.9      cgd 	int error = 0;
    522   1.9      cgd 	int flag;
    523   1.1       pk 	pid_t pid;
    524   1.1       pk 	struct vnode *nvp;
    525   1.9      cgd 	struct pfsnode *pfs;
    526   1.1       pk 	struct proc *procp;
    527   1.9      cgd 	int mode;
    528   1.9      cgd 	pfstype pfs_type;
    529   1.9      cgd 	int i;
    530   1.1       pk 
    531   1.9      cgd 	if (ndp->ni_namelen == 1 && *pname == '.') {
    532   1.9      cgd 		ndp->ni_vp = dvp;
    533   1.9      cgd 		ndp->ni_dvp = dvp;
    534   1.9      cgd 		VREF(dvp);
    535   1.9      cgd 		return (0);
    536   1.9      cgd 	}
    537   1.1       pk 
    538   1.9      cgd 	ndp->ni_dvp = dvp;
    539   1.1       pk 	ndp->ni_vp = NULL;
    540   1.1       pk 
    541   1.9      cgd 	pfs = VTOPFS(dvp);
    542   1.9      cgd 	switch (pfs->pfs_type) {
    543   1.9      cgd 	case Proot:
    544   1.9      cgd 		if (ndp->ni_isdotdot)
    545   1.9      cgd 			return (EIO);
    546   1.9      cgd 
    547  1.12       ws 		if (NDEQ(ndp, "curproc", 7)) {
    548  1.12       ws 			if (error = procfs_allocvp(dvp->v_mount, &nvp, 1, Proot))
    549  1.12       ws 				return error;
    550  1.12       ws 			ndp->ni_vp = nvp;
    551  1.12       ws 			return 0;
    552  1.12       ws 		}
    553  1.12       ws 
    554  1.12       ws 		pid = atopid(pname, ndp->ni_namelen);
    555   1.9      cgd 		if (pid == NO_PID)
    556   1.9      cgd 			return (ENOENT);
    557   1.9      cgd 
    558   1.9      cgd 		procp = PFIND(pid);
    559   1.9      cgd 		if (procp == 0)
    560   1.9      cgd 			return (ENOENT);
    561   1.9      cgd 
    562   1.9      cgd 		error = procfs_allocvp(dvp->v_mount, &nvp, pid, Pproc);
    563   1.9      cgd 		if (error)
    564   1.9      cgd 			return (error);
    565   1.9      cgd 
    566   1.9      cgd 		ndp->ni_vp = nvp;
    567   1.9      cgd 		return (0);
    568   1.9      cgd 
    569   1.9      cgd 	case Pproc:
    570   1.9      cgd 		if (ndp->ni_isdotdot) {
    571   1.9      cgd 			ndp->ni_dvp = dvp;
    572   1.9      cgd 			error = procfs_root(dvp->v_mount, &ndp->ni_vp);
    573   1.9      cgd 			return (error);
    574   1.9      cgd 		}
    575   1.1       pk 
    576   1.9      cgd 		procp = PFIND(pfs->pfs_pid);
    577   1.9      cgd 		if (procp == 0)
    578   1.9      cgd 			return (ENOENT);
    579   1.9      cgd 
    580   1.9      cgd 		for (i = 0; i < Nprocent; i++) {
    581   1.9      cgd 			struct pfsnames *dp = &procent[i];
    582   1.9      cgd 
    583   1.9      cgd 			if (ndp->ni_namelen == dp->d_namlen &&
    584   1.9      cgd 			    bcmp(pname, dp->d_name, dp->d_namlen) == 0) {
    585   1.9      cgd 			    	pfs_type = dp->d_pfstype;
    586   1.9      cgd 				goto found;
    587   1.9      cgd 			}
    588   1.9      cgd 		}
    589   1.9      cgd 		return (ENOENT);
    590   1.1       pk 
    591   1.9      cgd 	found:
    592   1.9      cgd 		if (pfs_type == Pfile) {
    593   1.9      cgd 			nvp = procfs_findtextvp(procp);
    594   1.9      cgd 			if (nvp) {
    595   1.9      cgd 				VREF(nvp);
    596   1.9      cgd 				VOP_LOCK(nvp);
    597   1.9      cgd 			} else {
    598   1.9      cgd 				error = ENXIO;
    599   1.9      cgd 			}
    600   1.9      cgd 		} else {
    601   1.9      cgd 			error = procfs_allocvp(dvp->v_mount, &nvp,
    602   1.9      cgd 					pfs->pfs_pid, pfs_type);
    603   1.9      cgd 			if (error)
    604   1.9      cgd 				return (error);
    605   1.1       pk 
    606   1.9      cgd 			pfs = VTOPFS(nvp);
    607   1.9      cgd 		}
    608   1.9      cgd 		ndp->ni_vp = nvp;
    609   1.9      cgd 		return (error);
    610   1.1       pk 
    611   1.9      cgd 	default:
    612   1.9      cgd 		return (ENOTDIR);
    613   1.1       pk 	}
    614   1.1       pk }
    615   1.1       pk 
    616   1.9      cgd /*
    617   1.9      cgd  * readdir returns directory entries from pfsnode (vp).
    618   1.9      cgd  *
    619   1.9      cgd  * the strategy here with procfs is to generate a single
    620   1.9      cgd  * directory entry at a time (struct pfsdent) and then
    621   1.9      cgd  * copy that out to userland using uiomove.  a more efficent
    622   1.9      cgd  * though more complex implementation, would try to minimize
    623   1.9      cgd  * the number of calls to uiomove().  for procfs, this is
    624   1.9      cgd  * hardly worth the added code complexity.
    625   1.9      cgd  *
    626   1.9      cgd  * this should just be done through read()
    627   1.9      cgd  */
    628   1.9      cgd procfs_readdir(vp, uio, cred, eofflagp, cookies, ncookies)
    629   1.1       pk         struct vnode *vp;
    630   1.9      cgd         struct uio *uio;
    631   1.1       pk         struct ucred *cred;
    632   1.1       pk         int *eofflagp;
    633   1.6       ws 	u_int *cookies;
    634   1.6       ws 	int ncookies;
    635   1.1       pk {
    636   1.9      cgd 	struct pfsdent d;
    637   1.9      cgd 	struct pfsdent *dp = &d;
    638   1.9      cgd 	struct pfsnode *pfs;
    639   1.9      cgd 	int error;
    640   1.9      cgd 	int count;
    641   1.9      cgd 	int i;
    642   1.9      cgd 
    643  1.13       ws 	/*
    644  1.13       ws 	 * NFS mounting of procfs doesn't work correctly.
    645  1.13       ws 	 * The files in procfs are more similar to devices
    646  1.13       ws 	 * than to regular files.
    647  1.13       ws 	 * See also procfs_vptofh & procfs_fhtovp in procfs_vfsops.c
    648  1.13       ws 	 */
    649  1.13       ws 	if (cookies)
    650  1.13       ws 		panic("procfs_readdir");
    651  1.13       ws 
    652   1.9      cgd 	pfs = VTOPFS(vp);
    653   1.1       pk 
    654   1.9      cgd 	if (uio->uio_resid < UIO_MX)
    655   1.9      cgd 		return (EINVAL);
    656   1.9      cgd 	if (uio->uio_offset & (UIO_MX-1))
    657   1.9      cgd 		return (EINVAL);
    658   1.9      cgd 	if (uio->uio_offset < 0)
    659   1.1       pk 		return (EINVAL);
    660   1.1       pk 
    661   1.9      cgd 	error = 0;
    662   1.1       pk 	count = 0;
    663   1.9      cgd 	i = uio->uio_offset / UIO_MX;
    664   1.9      cgd 
    665   1.9      cgd 	switch (pfs->pfs_type) {
    666   1.9      cgd 	/*
    667   1.9      cgd 	 * this is for the process-specific sub-directories.
    668   1.9      cgd 	 * all that is needed to is copy out all the entries
    669   1.9      cgd 	 * from the procent[] table (top of this file).
    670   1.9      cgd 	 */
    671   1.9      cgd 	case Pproc: {
    672  1.12       ws 		while (uio->uio_resid >= UIO_MX && (!cookies || ncookies > 0)) {
    673   1.9      cgd 			struct pfsnames *dt;
    674  1.12       ws 			pid_t pid = pfs->pfs_pid;
    675   1.9      cgd 
    676   1.9      cgd 			if (i >= Nprocent) {
    677   1.9      cgd 				*eofflagp = 1;
    678   1.9      cgd 				break;
    679   1.9      cgd 			}
    680   1.9      cgd 
    681   1.9      cgd 			dt = &procent[i];
    682   1.9      cgd 			dp->d_reclen = UIO_MX;
    683  1.12       ws 
    684  1.12       ws 			if (dt->d_pfstype == Proot)
    685  1.12       ws 				pid = 0;
    686  1.12       ws 			dp->d_fileno = PROCFS_FILENO(pid, dt->d_pfstype);
    687  1.15       ws 
    688  1.15       ws 			if (dt->d_pfstype == Pfile) {
    689  1.15       ws 				struct proc *procp = PFIND(pid);
    690  1.15       ws 
    691  1.15       ws 				if (!procp || !procfs_findtextvp(procp))
    692  1.15       ws 					dp->d_fileno = 0;
    693  1.15       ws 			}
    694  1.15       ws 
    695   1.9      cgd 			dp->d_namlen = dt->d_namlen;
    696   1.9      cgd 			bcopy(dt->d_name, dp->d_name, sizeof(dt->d_name)-1);
    697   1.9      cgd 			error = uiomove((caddr_t) dp, UIO_MX, uio);
    698   1.9      cgd 			if (error)
    699   1.9      cgd 				break;
    700   1.9      cgd 			count += UIO_MX;
    701   1.9      cgd 			i++;
    702  1.12       ws 			if (cookies) {
    703  1.12       ws 				*cookies++ = i * UIO_MX;
    704  1.12       ws 				ncookies--;
    705  1.12       ws 			}
    706   1.6       ws 		}
    707   1.9      cgd 
    708   1.9      cgd 	    	break;
    709   1.9      cgd 
    710   1.9      cgd 	    }
    711   1.9      cgd 
    712   1.9      cgd 	/*
    713   1.9      cgd 	 * this is for the root of the procfs filesystem
    714   1.9      cgd 	 * what is needed is a special entry for "curproc"
    715   1.9      cgd 	 * followed by an entry for each process on allproc
    716   1.9      cgd #ifdef PROCFS_ZOMBIE
    717   1.9      cgd 	 * and zombproc.
    718   1.9      cgd #endif
    719   1.9      cgd 	 */
    720   1.9      cgd 
    721   1.9      cgd 	case Proot: {
    722   1.9      cgd 		int pcnt;
    723   1.9      cgd #ifdef PROCFS_ZOMBIE
    724   1.9      cgd 		int doingzomb = 0;
    725   1.9      cgd #endif
    726   1.9      cgd 		struct proc *p;
    727   1.9      cgd 
    728  1.10      cgd 		p = (struct proc *) allproc;
    729   1.9      cgd 
    730   1.9      cgd 		pcnt = PROCFS_XFILES;
    731   1.9      cgd 
    732  1.12       ws 		while (p && uio->uio_resid >= UIO_MX && (!cookies || ncookies > 0)) {
    733   1.9      cgd 			bzero((char *) dp, UIO_MX);
    734   1.9      cgd 			dp->d_reclen = UIO_MX;
    735   1.9      cgd 
    736   1.9      cgd 			switch (i) {
    737  1.12       ws 			case 0:		/* `.' */
    738  1.12       ws 			case 1:		/* `..' */
    739  1.12       ws 				dp->d_fileno = PROCFS_FILENO(0, Proot);
    740  1.12       ws 				bcopy("..",dp->d_name,3);
    741  1.12       ws 				dp->d_namlen = i + 1;
    742  1.12       ws 				dp->d_name[i + 1] = 0;
    743  1.12       ws 				break;
    744  1.12       ws 			case 2:
    745   1.9      cgd 				/* ship out entry for "curproc" */
    746  1.12       ws 				dp->d_fileno = PROCFS_FILENO(1, Proot);
    747   1.9      cgd 				dp->d_namlen = 7;
    748   1.9      cgd 				bcopy("curproc", dp->d_name, dp->d_namlen+1);
    749   1.9      cgd 				break;
    750   1.9      cgd 
    751   1.9      cgd 			default:
    752   1.9      cgd 				if (pcnt >= i) {
    753   1.9      cgd 					dp->d_fileno = PROCFS_FILENO(p->p_pid, Pproc);
    754   1.9      cgd 					dp->d_namlen = sprintf(dp->d_name, "%ld", (long) p->p_pid);
    755   1.9      cgd 				}
    756   1.9      cgd 
    757   1.9      cgd 				p = p->p_nxt;
    758   1.9      cgd 
    759   1.9      cgd #ifdef PROCFS_ZOMBIE
    760   1.9      cgd 				if (p == 0 && doingzomb == 0) {
    761   1.9      cgd 					doingzomb = 1;
    762   1.9      cgd 					p = zombproc;
    763   1.9      cgd 				}
    764   1.1       pk #endif
    765   1.1       pk 
    766   1.9      cgd 				if (pcnt++ < i)
    767   1.9      cgd 					continue;
    768   1.9      cgd 
    769   1.9      cgd 				break;
    770   1.1       pk 			}
    771   1.9      cgd 			error = uiomove((caddr_t) dp, UIO_MX, uio);
    772   1.9      cgd 			if (error)
    773   1.9      cgd 				break;
    774   1.9      cgd 			count += UIO_MX;
    775   1.9      cgd 			i++;
    776  1.12       ws 			if (cookies) {
    777  1.12       ws 				*cookies++ = i * UIO_MX;
    778  1.12       ws 				ncookies--;
    779  1.12       ws 			}
    780   1.1       pk 		}
    781   1.1       pk 
    782   1.9      cgd 		break;
    783   1.9      cgd 
    784   1.9      cgd 	    }
    785   1.9      cgd 
    786   1.9      cgd 	default:
    787   1.9      cgd 		error = ENOTDIR;
    788   1.9      cgd 		break;
    789   1.1       pk 	}
    790   1.9      cgd 
    791   1.9      cgd 	uio->uio_offset = i * UIO_MX;
    792   1.1       pk 	if (count == 0)
    793   1.1       pk 		*eofflagp = 1;
    794   1.1       pk 
    795   1.9      cgd 	return (error);
    796  1.12       ws }
    797  1.12       ws 
    798  1.12       ws /*
    799  1.12       ws  * readlink reads the link of "curproc"
    800  1.12       ws  */
    801  1.12       ws procfs_readlink(vp, uio, cred)
    802  1.12       ws 	struct vnode *vp;
    803  1.12       ws 	struct uio *uio;
    804  1.12       ws 	struct ucred *cred;
    805  1.12       ws {
    806  1.12       ws 	struct pfsnode *pfs = VTOPFS(vp);
    807  1.12       ws 	char buf[16];		/* should be enough */
    808  1.12       ws 	int len;
    809  1.12       ws 
    810  1.12       ws 	if (pfs->pfs_fileno != PROCFS_FILENO(1,Proot))
    811  1.12       ws 		return EINVAL;
    812  1.12       ws 
    813  1.12       ws 	len = sprintf(buf,"%ld",(long)curproc->p_pid);
    814  1.12       ws 
    815  1.12       ws 	return uiomove(buf, len, uio);
    816   1.1       pk }
    817   1.1       pk 
    818   1.1       pk /*
    819   1.9      cgd  * convert decimal ascii to pid_t
    820   1.1       pk  */
    821   1.9      cgd static pid_t
    822   1.9      cgd atopid(b, len)
    823   1.9      cgd 	const char *b;
    824   1.9      cgd 	u_int len;
    825   1.1       pk {
    826   1.9      cgd 	pid_t p = 0;
    827   1.1       pk 
    828   1.1       pk 	while (len--) {
    829   1.9      cgd 		char c = *b++;
    830   1.1       pk 		if (c < '0' || c > '9')
    831   1.9      cgd 			return (NO_PID);
    832   1.9      cgd 		p = 10 * p + (c - '0');
    833   1.9      cgd 		if (p > PID_MAX)
    834   1.9      cgd 			return (NO_PID);
    835   1.1       pk 	}
    836   1.9      cgd 
    837   1.9      cgd 	return (p);
    838   1.1       pk }
    839   1.9      cgd 
    840   1.9      cgd /*
    841   1.9      cgd  * procfs vnode operations.
    842   1.9      cgd  */
    843   1.9      cgd struct vnodeops procfs_vnodeops = {
    844   1.9      cgd 	procfs_lookup,		/* lookup */
    845   1.9      cgd 	procfs_create,		/* create */
    846   1.9      cgd 	procfs_mknod,		/* mknod */
    847   1.9      cgd 	procfs_open,		/* open */
    848   1.9      cgd 	procfs_close,		/* close */
    849   1.9      cgd 	procfs_access,		/* access */
    850   1.9      cgd 	procfs_getattr,		/* getattr */
    851   1.9      cgd 	procfs_setattr,		/* setattr */
    852   1.9      cgd 	procfs_read,		/* read */
    853   1.9      cgd 	procfs_write,		/* write */
    854   1.9      cgd 	procfs_ioctl,		/* ioctl */
    855   1.9      cgd 	procfs_select,		/* select */
    856   1.9      cgd 	procfs_mmap,		/* mmap */
    857   1.9      cgd 	procfs_fsync,		/* fsync */
    858   1.9      cgd 	procfs_seek,		/* seek */
    859   1.9      cgd 	procfs_remove,		/* remove */
    860   1.9      cgd 	procfs_link,		/* link */
    861   1.9      cgd 	procfs_rename,		/* rename */
    862   1.9      cgd 	procfs_mkdir,		/* mkdir */
    863   1.9      cgd 	procfs_rmdir,		/* rmdir */
    864   1.9      cgd 	procfs_symlink,		/* symlink */
    865   1.9      cgd 	procfs_readdir,		/* readdir */
    866   1.9      cgd 	procfs_readlink,	/* readlink */
    867   1.9      cgd 	procfs_abortop,		/* abortop */
    868   1.9      cgd 	procfs_inactive,	/* inactive */
    869   1.9      cgd 	procfs_reclaim,		/* reclaim */
    870   1.9      cgd 	procfs_lock,		/* lock */
    871   1.9      cgd 	procfs_unlock,		/* unlock */
    872   1.9      cgd 	procfs_bmap,		/* bmap */
    873   1.9      cgd 	procfs_strategy,	/* strategy */
    874   1.9      cgd 	procfs_print,		/* print */
    875   1.9      cgd 	procfs_islocked,	/* islocked */
    876   1.9      cgd 	procfs_advlock,		/* advlock */
    877   1.9      cgd };
    878