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