Merge branch 'vendor/GCC44'
[dragonfly.git] / sys / emulation / linux / i386 / linprocfs / linprocfs_vnops.c
1 /*
2  * Copyright (c) 2000 Dag-Erling Coïdan Smørgrav
3  * Copyright (c) 1999 Pierre Beyssac
4  * Copyright (c) 1993, 1995 Jan-Simon Pendry
5  * Copyright (c) 1993, 1995
6  *      The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Jan-Simon Pendry.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *      This product includes software developed by the University of
22  *      California, Berkeley and its contributors.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  *      @(#)procfs_vnops.c      8.18 (Berkeley) 5/21/95
40  *
41  * $FreeBSD: src/sys/i386/linux/linprocfs/linprocfs_vnops.c,v 1.3.2.5 2001/08/12 14:29:19 rwatson Exp $
42  * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c,v 1.42 2007/11/20 21:03:48 dillon Exp $
43  */
44
45 /*
46  * procfs vnode interface
47  */
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/time.h>
52 #include <sys/kernel.h>
53 #include <sys/lock.h>
54 #include <sys/fcntl.h>
55 #include <sys/proc.h>
56 #include <sys/priv.h>
57 #include <sys/signalvar.h>
58 #include <sys/vnode.h>
59 #include <sys/mount.h>
60 #include <sys/namei.h>
61 #include <sys/dirent.h>
62 #include <sys/malloc.h>
63 #include <sys/reg.h>
64 #include <vm/vm_zone.h>
65 #include "linprocfs.h"
66 #include <sys/pioctl.h>
67
68 #include <machine/limits.h>
69
70 extern struct vnode *procfs_findtextvp (struct proc *);
71
72 static int      linprocfs_access (struct vop_access_args *);
73 static int      linprocfs_badop (struct vop_generic_args *);
74 static int      linprocfs_bmap (struct vop_bmap_args *);
75 static int      linprocfs_close (struct vop_close_args *);
76 static int      linprocfs_getattr (struct vop_getattr_args *);
77 static int      linprocfs_inactive (struct vop_inactive_args *);
78 static int      linprocfs_ioctl (struct vop_ioctl_args *);
79 static int      linprocfs_lookup (struct vop_old_lookup_args *);
80 static int      linprocfs_open (struct vop_open_args *);
81 static int      linprocfs_print (struct vop_print_args *);
82 static int      linprocfs_readdir (struct vop_readdir_args *);
83 static int      linprocfs_readlink (struct vop_readlink_args *);
84 static int      linprocfs_reclaim (struct vop_reclaim_args *);
85 static int      linprocfs_setattr (struct vop_setattr_args *);
86
87 static int      linprocfs_readdir_proc(struct vop_readdir_args *);
88 static int      linprocfs_readdir_root(struct vop_readdir_args *);
89
90 /*
91  * procfs vnode operations.
92  */
93 struct vop_ops linprocfs_vnode_vops = {
94         .vop_default =          vop_defaultop,
95         .vop_access =           linprocfs_access,
96         .vop_advlock =          (void *)linprocfs_badop,
97         .vop_bmap =             linprocfs_bmap,
98         .vop_close =            linprocfs_close,
99         .vop_old_create =       (void *)linprocfs_badop,
100         .vop_getattr =          linprocfs_getattr,
101         .vop_inactive =         linprocfs_inactive,
102         .vop_old_link =         (void *)linprocfs_badop,
103         .vop_old_lookup =       linprocfs_lookup,
104         .vop_old_mkdir =        (void *)linprocfs_badop,
105         .vop_old_mknod =        (void *)linprocfs_badop,
106         .vop_open =             linprocfs_open,
107         .vop_pathconf =         vop_stdpathconf,
108         .vop_print =            linprocfs_print,
109         .vop_read =             (void *)linprocfs_rw,
110         .vop_readdir =          linprocfs_readdir,
111         .vop_readlink =         linprocfs_readlink,
112         .vop_reclaim =          linprocfs_reclaim,
113         .vop_old_remove =       (void *)linprocfs_badop,
114         .vop_old_rename =       (void *)linprocfs_badop,
115         .vop_old_rmdir =        (void *)linprocfs_badop,
116         .vop_setattr =          linprocfs_setattr,
117         .vop_old_symlink =      (void *)linprocfs_badop,
118         .vop_write =            (void *)linprocfs_rw,
119         .vop_ioctl =            linprocfs_ioctl
120 };
121
122 /*
123  * This is a list of the valid names in the
124  * process-specific sub-directories.  It is
125  * used in linprocfs_lookup and linprocfs_readdir
126  */
127 static struct proc_target {
128         u_char  pt_type;
129         u_char  pt_namlen;
130         char    *pt_name;
131         pfstype pt_pfstype;
132         int     (*pt_valid) (struct proc *p);
133 } proc_targets[] = {
134 #define N(s) sizeof(s)-1, s
135         /*        name          type            validp */
136         { DT_DIR, N("."),       Pproc,          NULL },
137         { DT_DIR, N(".."),      Proot,          NULL },
138         { DT_REG, N("mem"),     Pmem,           NULL },
139         { DT_LNK, N("exe"),     Pexe,           NULL },
140         { DT_REG, N("stat"),    Pprocstat,      NULL },
141         { DT_REG, N("status"),  Pprocstatus,    NULL },
142 #undef N
143 };
144 static const int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]);
145
146 static pid_t atopid (const char *, u_int);
147
148 /*
149  * set things up for doing i/o on
150  * the pfsnode (vp).  (vp) is locked
151  * on entry, and should be left locked
152  * on exit.
153  *
154  * for procfs we don't need to do anything
155  * in particular for i/o.  all that is done
156  * is to support exclusive open on process
157  * memory images.
158  */
159 static int
160 linprocfs_open(struct vop_open_args *ap)
161 {
162         struct pfsnode *pfs = VTOPFS(ap->a_vp);
163         struct proc *p2;
164
165         p2 = PFIND(pfs->pfs_pid);
166         if (p2 == NULL)
167                 return (ENOENT);
168         if (pfs->pfs_pid && !PRISON_CHECK(ap->a_cred, p2->p_ucred))
169                 return (ENOENT);
170
171         switch (pfs->pfs_type) {
172         case Pmem:
173                 if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) ||
174                     ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE)))
175                         return (EBUSY);
176
177                 if (p_trespass(ap->a_cred, p2->p_ucred))
178                         return (EPERM);
179
180                 if (ap->a_mode & FWRITE)
181                         pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL);
182
183                 break;
184         default:
185                 break;
186         }
187
188         return (vop_stdopen(ap));
189 }
190
191 /*
192  * close the pfsnode (vp) after doing i/o.
193  * (vp) is not locked on entry or exit.
194  *
195  * nothing to do for procfs other than undo
196  * any exclusive open flag (see _open above).
197  */
198 static int
199 linprocfs_close(struct vop_close_args *ap)
200 {
201         struct pfsnode *pfs = VTOPFS(ap->a_vp);
202         struct proc *p;
203
204         switch (pfs->pfs_type) {
205         case Pmem:
206                 if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL))
207                         pfs->pfs_flags &= ~(FWRITE|O_EXCL);
208                 /*
209                  * If this is the last close, then it checks to see if
210                  * the target process has PF_LINGER set in p_pfsflags,
211                  * if this is *not* the case, then the process' stop flags
212                  * are cleared, and the process is woken up.  This is
213                  * to help prevent the case where a process has been
214                  * told to stop on an event, but then the requesting process
215                  * has gone away or forgotten about it.
216                  */
217                 if ((ap->a_vp->v_opencount < 2)
218                     && (p = pfind(pfs->pfs_pid))
219                     && !(p->p_pfsflags & PF_LINGER)) {
220                         p->p_stops = 0;
221                         p->p_step = 0;
222                         wakeup(&p->p_step);
223                 }
224                 break;
225         default:
226                 break;
227         }
228         return (vop_stdclose(ap));
229 }
230
231 /*
232  * do an ioctl operation on a pfsnode (vp).
233  * (vp) is not locked on entry or exit.
234  */
235 static int
236 linprocfs_ioctl(struct vop_ioctl_args *ap)
237 {
238         struct pfsnode *pfs = VTOPFS(ap->a_vp);
239         struct proc *procp;
240         int error;
241         int signo;
242         struct procfs_status *psp;
243         unsigned char flags;
244
245         procp = pfind(pfs->pfs_pid);
246         if (procp == NULL) {
247                 return ENOTTY;
248         }
249
250         if (p_trespass(ap->a_cred, procp->p_ucred))
251                 return EPERM;
252
253         switch (ap->a_command) {
254         case PIOCBIS:
255           procp->p_stops |= *(unsigned int*)ap->a_data;
256           break;
257         case PIOCBIC:
258           procp->p_stops &= ~*(unsigned int*)ap->a_data;
259           break;
260         case PIOCSFL:
261           /*
262            * NFLAGS is "non-suser_xxx flags" -- currently, only
263            * PFS_ISUGID ("ignore set u/g id");
264            */
265 #define NFLAGS  (PF_ISUGID)
266           flags = (unsigned char)*(unsigned int*)ap->a_data;
267           if (flags & NFLAGS && (error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0)))
268             return error;
269           procp->p_pfsflags = flags;
270           break;
271         case PIOCGFL:
272           *(unsigned int*)ap->a_data = (unsigned int)procp->p_pfsflags;
273         case PIOCSTATUS:
274           psp = (struct procfs_status *)ap->a_data;
275           psp->state = (procp->p_step == 0);
276           psp->flags = procp->p_pfsflags;
277           psp->events = procp->p_stops;
278           if (procp->p_step) {
279             psp->why = procp->p_stype;
280             psp->val = procp->p_xstat;
281           } else {
282             psp->why = psp->val = 0;    /* Not defined values */
283           }
284           break;
285         case PIOCWAIT:
286           psp = (struct procfs_status *)ap->a_data;
287           if (procp->p_step == 0) {
288             error = tsleep(&procp->p_stype, PCATCH, "piocwait", 0);
289             if (error)
290               return error;
291           }
292           psp->state = 1;       /* It stopped */
293           psp->flags = procp->p_pfsflags;
294           psp->events = procp->p_stops;
295           psp->why = procp->p_stype;    /* why it stopped */
296           psp->val = procp->p_xstat;    /* any extra info */
297           break;
298         case PIOCCONT:  /* Restart a proc */
299           if (procp->p_step == 0)
300             return EINVAL;      /* Can only start a stopped process */
301           if ((signo = *(int*)ap->a_data) != 0) {
302             if (signo >= NSIG || signo <= 0)
303               return EINVAL;
304             ksignal(procp, signo);
305           }
306           procp->p_step = 0;
307           wakeup(&procp->p_step);
308           break;
309         default:
310           return (ENOTTY);
311         }
312         return 0;
313 }
314
315 /*
316  * do block mapping for pfsnode (vp).
317  * since we don't use the buffer cache
318  * for procfs this function should never
319  * be called.  in any case, it's not clear
320  * what part of the kernel ever makes use
321  * of this function.  for sanity, this is the
322  * usual no-op bmap, although returning
323  * (EIO) would be a reasonable alternative.
324  */
325 static int
326 linprocfs_bmap(struct vop_bmap_args *ap)
327 {
328         if (ap->a_doffsetp != NULL)
329                 *ap->a_doffsetp = ap->a_loffset;
330         if (ap->a_runp != NULL)
331                 *ap->a_runp = 0;
332         if (ap->a_runb != NULL)
333                 *ap->a_runb = 0;
334         return (0);
335 }
336
337 /*
338  * linprocfs_inactive is called when the pfsnode
339  * is vrele'd and the reference count is about
340  * to go to zero.  (vp) will be on the vnode free
341  * list, so to get it back vget() must be
342  * used.
343  *
344  * (vp) is locked on entry and must remain locked
345  *      on exit.
346  */
347 static int
348 linprocfs_inactive(struct vop_inactive_args *ap)
349 {
350         /*struct vnode *vp = ap->a_vp;*/
351
352         return (0);
353 }
354
355 /*
356  * _reclaim is called when getnewvnode()
357  * wants to make use of an entry on the vnode
358  * free list.  at this time the filesystem needs
359  * to free any private data and remove the node
360  * from any private lists.
361  */
362 static int
363 linprocfs_reclaim(struct vop_reclaim_args *ap)
364 {
365         return (linprocfs_freevp(ap->a_vp));
366 }
367
368 /*
369  * _print is used for debugging.
370  * just print a readable description
371  * of (vp).
372  */
373 static int
374 linprocfs_print(struct vop_print_args *ap)
375 {
376         struct pfsnode *pfs = VTOPFS(ap->a_vp);
377
378         kprintf("tag VT_PROCFS, type %d, pid %ld, mode %x, flags %lx\n",
379             pfs->pfs_type, (long)pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags);
380         return (0);
381 }
382
383 /*
384  * generic entry point for unsupported operations
385  */
386 static int
387 linprocfs_badop(struct vop_generic_args *ap __unused)
388 {
389
390         return (EIO);
391 }
392
393 /*
394  * Invent attributes for pfsnode (vp) and store
395  * them in (vap).
396  * Directories lengths are returned as zero since
397  * any real length would require the genuine size
398  * to be computed, and nothing cares anyway.
399  *
400  * this is relatively minimal for procfs.
401  */
402 static int
403 linprocfs_getattr(struct vop_getattr_args *ap)
404 {
405         struct pfsnode *pfs = VTOPFS(ap->a_vp);
406         struct vattr *vap = ap->a_vap;
407         struct proc *procp;
408         int error;
409
410         /*
411          * First make sure that the process and its credentials 
412          * still exist.
413          */
414         switch (pfs->pfs_type) {
415         case Proot:
416         case Pself:
417                 procp = 0;
418                 break;
419
420         default:
421                 procp = PFIND(pfs->pfs_pid);
422                 if (procp == 0 || procp->p_ucred == NULL)
423                         return (ENOENT);
424         }
425
426         error = 0;
427
428         /* start by zeroing out the attributes */
429         VATTR_NULL(vap);
430
431         /* next do all the common fields */
432         vap->va_type = ap->a_vp->v_type;
433         vap->va_mode = pfs->pfs_mode;
434         vap->va_fileid = pfs->pfs_fileno;
435         vap->va_flags = 0;
436         vap->va_blocksize = PAGE_SIZE;
437         vap->va_bytes = vap->va_size = 0;
438         vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
439
440         /*
441          * Make all times be current TOD.
442          * It would be possible to get the process start
443          * time from the p_stat structure, but there's
444          * no "file creation" time stamp anyway, and the
445          * p_stat structure is not addressible if u. gets
446          * swapped out for that process.
447          */
448         nanotime(&vap->va_ctime);
449         vap->va_atime = vap->va_mtime = vap->va_ctime;
450
451         /*
452          * now do the object specific fields
453          *
454          * The size could be set from struct reg, but it's hardly
455          * worth the trouble, and it puts some (potentially) machine
456          * dependent data into this machine-independent code.  If it
457          * becomes important then this function should break out into
458          * a per-file stat function in the corresponding .c file.
459          */
460
461         vap->va_nlink = 1;
462         if (procp) {
463                 vap->va_uid = procp->p_ucred->cr_uid;
464                 vap->va_gid = procp->p_ucred->cr_gid;
465         }
466
467         switch (pfs->pfs_type) {
468         case Proot:
469                 /*
470                  * Set nlink to 1 to tell fts(3) we don't actually know.
471                  */
472                 vap->va_nlink = 1;
473                 vap->va_uid = 0;
474                 vap->va_gid = 0;
475                 vap->va_size = vap->va_bytes = DEV_BSIZE;
476                 break;
477
478         case Pself: {
479                 char buf[16];           /* should be enough */
480                 vap->va_uid = 0;
481                 vap->va_gid = 0;
482                 vap->va_size = vap->va_bytes =
483                     ksnprintf(buf, sizeof(buf), "%ld", (long)curproc->p_pid);
484                 break;
485         }
486
487         case Pproc:
488                 vap->va_nlink = nproc_targets;
489                 vap->va_size = vap->va_bytes = DEV_BSIZE;
490                 break;
491
492         case Pexe: {
493                 char *fullpath, *freepath;
494                 error = vn_fullpath(procp, NULL, &fullpath, &freepath);
495                 if (error == 0) {
496                         vap->va_size = strlen(fullpath);
497                         kfree(freepath, M_TEMP);
498                 } else {
499                         vap->va_size = sizeof("unknown") - 1;
500                         error = 0;
501                 }
502                 vap->va_bytes = vap->va_size;
503                 break;
504         }
505
506         case Pmeminfo:
507         case Pcpuinfo:
508         case Pstat:
509         case Puptime:
510         case Pversion:
511         case Ploadavg:
512                 vap->va_bytes = vap->va_size = 0;
513                 vap->va_uid = 0;
514                 vap->va_gid = 0;
515                 break;
516                 
517         case Pmem:
518                 /*
519                  * If we denied owner access earlier, then we have to
520                  * change the owner to root - otherwise 'ps' and friends
521                  * will break even though they are setgid kmem. *SIGH*
522                  */
523                 if (procp->p_flag & P_SUGID)
524                         vap->va_uid = 0;
525                 else
526                         vap->va_uid = procp->p_ucred->cr_uid;
527                 break;
528
529         case Pprocstat:
530         case Pprocstatus:
531                 vap->va_bytes = vap->va_size = 0;
532                 /* uid, gid are already set */
533                 break;
534
535         default:
536                 panic("linprocfs_getattr");
537         }
538
539         return (error);
540 }
541
542 static int
543 linprocfs_setattr(struct vop_setattr_args *ap)
544 {
545
546         if (ap->a_vap->va_flags != VNOVAL)
547                 return (EOPNOTSUPP);
548
549         /*
550          * just fake out attribute setting
551          * it's not good to generate an error
552          * return, otherwise things like creat()
553          * will fail when they try to set the
554          * file length to 0.  worse, this means
555          * that echo $note > /proc/$pid/note will fail.
556          */
557
558         return (0);
559 }
560
561 /*
562  * implement access checking.
563  *
564  * something very similar to this code is duplicated
565  * throughout the 4bsd kernel and should be moved
566  * into kern/vfs_subr.c sometime.
567  *
568  * actually, the check for super-user is slightly
569  * broken since it will allow read access to write-only
570  * objects.  this doesn't cause any particular trouble
571  * but does mean that the i/o entry points need to check
572  * that the operation really does make sense.
573  */
574 static int
575 linprocfs_access(struct vop_access_args *ap)
576 {
577         struct vattr *vap;
578         struct vattr vattr;
579         int error;
580
581         /*
582          * If you're the super-user,
583          * you always get access.
584          */
585         if (ap->a_cred->cr_uid == 0)
586                 return (0);
587
588         vap = &vattr;
589         error = VOP_GETATTR(ap->a_vp, vap);
590         if (error)
591                 return (error);
592
593         /*
594          * Access check is based on only one of owner, group, public.
595          * If not owner, then check group. If not a member of the
596          * group, then check public access.
597          */
598         if (ap->a_cred->cr_uid != vap->va_uid) {
599                 gid_t *gp;
600                 int i;
601
602                 ap->a_mode >>= 3;
603                 gp = ap->a_cred->cr_groups;
604                 for (i = 0; i < ap->a_cred->cr_ngroups; i++, gp++)
605                         if (vap->va_gid == *gp)
606                                 goto found;
607                 ap->a_mode >>= 3;
608 found:
609                 ;
610         }
611
612         if ((vap->va_mode & ap->a_mode) == ap->a_mode)
613                 return (0);
614
615         return (EACCES);
616 }
617
618 /*
619  * lookup.  this is incredibly complicated in the general case, however
620  * for most pseudo-filesystems very little needs to be done.
621  */
622 static int
623 linprocfs_lookup(struct vop_old_lookup_args *ap)
624 {
625         struct componentname *cnp = ap->a_cnp;
626         struct vnode **vpp = ap->a_vpp;
627         struct vnode *dvp = ap->a_dvp;
628         char *pname = cnp->cn_nameptr;
629         struct proc_target *pt;
630         pid_t pid;
631         struct pfsnode *pfs;
632         struct proc *p;
633         int i;
634         int error;
635
636         *vpp = NULL;
637
638         if (cnp->cn_nameiop == NAMEI_DELETE || 
639             cnp->cn_nameiop == NAMEI_RENAME ||
640             cnp->cn_nameiop == NAMEI_CREATE) {
641                 return (EROFS);
642         }
643
644         error = 0;
645
646         if (cnp->cn_namelen == 1 && *pname == '.') {
647                 *vpp = dvp;
648                 vref(*vpp);
649                 goto out;
650         }
651
652         pfs = VTOPFS(dvp);
653         switch (pfs->pfs_type) {
654         case Proot:
655                 if (cnp->cn_flags & CNP_ISDOTDOT)
656                         return (EIO);
657
658                 if (CNEQ(cnp, "self", 4)) {
659                         error = linprocfs_allocvp(dvp->v_mount, vpp, 0, Pself);
660                         goto out;
661                 }
662                 if (CNEQ(cnp, "meminfo", 7)) {
663                         error = linprocfs_allocvp(dvp->v_mount, vpp, 0, Pmeminfo);
664                         goto out;
665                 }
666                 if (CNEQ(cnp, "cpuinfo", 7)) {
667                         error = linprocfs_allocvp(dvp->v_mount, vpp, 0, Pcpuinfo);
668                         goto out;
669                 }
670                 if (CNEQ(cnp, "stat", 4)) {
671                         error = linprocfs_allocvp(dvp->v_mount, vpp, 0, Pstat);
672                         goto out;
673                 }
674                 if (CNEQ(cnp, "uptime", 6)) {
675                         error = linprocfs_allocvp(dvp->v_mount, vpp, 0, Puptime);
676                         goto out;
677                 }
678                 if (CNEQ(cnp, "version", 7)) {
679                         error = linprocfs_allocvp(dvp->v_mount, vpp, 0, Pversion);
680                         goto out;
681                 }
682                 if (CNEQ(cnp, "loadavg", 7)) {
683                         error = linprocfs_allocvp(dvp->v_mount, vpp, 0, Ploadavg);
684                         goto out;
685                 }
686
687                 pid = atopid(pname, cnp->cn_namelen);
688                 if (pid == NO_PID)
689                         break;
690
691                 p = PFIND(pid);
692                 if (p == 0)
693                         break;
694
695                 if (!PRISON_CHECK(ap->a_cnp->cn_cred, p->p_ucred))
696                         break;
697
698                 if (ps_showallprocs == 0 && ap->a_cnp->cn_cred->cr_uid != 0 &&
699                     ap->a_cnp->cn_cred->cr_uid != p->p_ucred->cr_uid)
700                         break;
701
702                 error = linprocfs_allocvp(dvp->v_mount, vpp, pid, Pproc);
703                 goto out;
704
705         case Pproc:
706                 if (cnp->cn_flags & CNP_ISDOTDOT) {
707                         error = linprocfs_root(dvp->v_mount, vpp);
708                         goto out;
709                 }
710
711                 p = PFIND(pfs->pfs_pid);
712                 if (p == 0)
713                         break;
714
715                 if (!PRISON_CHECK(ap->a_cnp->cn_cred, p->p_ucred))
716                         break;
717
718                 if (ps_showallprocs == 0 && ap->a_cnp->cn_cred->cr_uid != 0 &&
719                     ap->a_cnp->cn_cred->cr_uid != p->p_ucred->cr_uid)
720                         break;
721
722                 for (pt = proc_targets, i = 0; i < nproc_targets; pt++, i++) {
723                         if (cnp->cn_namelen == pt->pt_namlen &&
724                             bcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 &&
725                             (pt->pt_valid == NULL || (*pt->pt_valid)(p)))
726                                 goto found;
727                 }
728                 break;
729
730         found:
731                 error = linprocfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
732                                         pt->pt_pfstype);
733                 goto out;
734
735         default:
736                 error = ENOTDIR;
737                 goto out;
738         }
739
740         if (cnp->cn_nameiop == NAMEI_LOOKUP)
741                 error = ENOENT;
742         else
743                 error = EROFS;
744
745         /*
746          * If no error occured *vpp will hold a referenced locked vnode.
747          * dvp was passed to us locked and *vpp must be returned locked
748          * so if dvp != *vpp and CNP_LOCKPARENT is not set, unlock dvp.
749          */
750 out:
751         if (error == 0) {
752                 if (*vpp != dvp && (cnp->cn_flags & CNP_LOCKPARENT) == 0) {
753                         cnp->cn_flags |= CNP_PDIRUNLOCK;
754                         vn_unlock(dvp);
755                 }
756         }
757         return (error);
758 }
759
760 /*
761  * Does this process have a text file?
762  */
763 int
764 linprocfs_validfile(struct proc *p)
765 {
766
767         return (procfs_findtextvp(p) != NULLVP);
768 }
769
770 /*
771  * readdir() returns directory entries from pfsnode (vp).
772  *
773  * We generate just one directory entry at a time, as it would probably
774  * not pay off to buffer several entries locally to save uiomove calls.
775  *
776  * linprocfs_readdir(struct vnode *a_vp, struct uio *a_uio,
777  *                   struct ucred *a_cred, int *a_eofflag,
778  *                   int *a_ncookies, off_t **a_cookies)
779  */
780 static int
781 linprocfs_readdir(struct vop_readdir_args *ap)
782 {
783         struct pfsnode *pfs;
784         int error;
785
786         if (ap->a_uio->uio_offset < 0 || ap->a_uio->uio_offset > INT_MAX)
787                 return (EINVAL);
788
789         pfs = VTOPFS(ap->a_vp);
790         if ((error = vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY)) != 0)
791                 return (error);
792
793         switch (pfs->pfs_type) {
794         case Pproc:
795                 /*
796                  * This is for the process-specific sub-directories.
797                  * all that is needed to is copy out all the entries
798                  * from the procent[] table (top of this file).
799                  */
800                 error = linprocfs_readdir_proc(ap);
801                 break;
802         case Proot:
803                 /*
804                  * This is for the root of the procfs filesystem
805                  * what is needed is a special entry for "self"
806                  * followed by an entry for each process on allproc
807                  */
808                 error = linprocfs_readdir_root(ap);
809                 break;
810         default:
811                 error = ENOTDIR;
812                 break;
813         }
814         vn_unlock(ap->a_vp);
815
816         return (error);
817 }
818
819 static int
820 linprocfs_readdir_proc(struct vop_readdir_args *ap)
821 {
822         struct pfsnode *pfs;
823         int error, i, retval;
824         struct proc *p;
825         struct proc_target *pt;
826         struct uio *uio = ap->a_uio;
827
828         pfs = VTOPFS(ap->a_vp);
829         p = PFIND(pfs->pfs_pid);
830         if (p == NULL)
831                 return(0);
832         if (!PRISON_CHECK(ap->a_cred, p->p_ucred))
833                 return(0);
834
835         error = 0;
836         i = uio->uio_offset;
837
838         for (pt = &proc_targets[i];
839              !error && uio->uio_resid > 0 && i < nproc_targets; pt++, i++) {
840                 if (pt->pt_valid && (*pt->pt_valid)(p) == 0)
841                         continue;
842
843                 retval = vop_write_dirent(&error, uio,
844                     PROCFS_FILENO(pfs->pfs_pid, pt->pt_pfstype), pt->pt_type,
845                     pt->pt_namlen, pt->pt_name);
846                 if (retval)
847                         break;
848         }
849
850         uio->uio_offset = i;
851
852         return(error);
853 }
854
855 struct linprocfs_readdir_root_info {
856         int error;
857         int pcnt;
858         int i;
859         struct uio *uio;
860         struct ucred *cred;
861 };
862
863 /*
864  * Scan the root directory by scanning all process
865  */
866 static int linprocfs_readdir_root_callback(struct proc *p, void *data);
867
868 static int
869 linprocfs_readdir_root(struct vop_readdir_args *ap)
870 {
871         struct linprocfs_readdir_root_info info;
872         struct uio *uio = ap->a_uio;
873         int res;
874
875         info.error = 0;
876         info.i = uio->uio_offset;
877         info.pcnt = 0;
878         info.uio = uio;
879         info.cred = ap->a_cred;
880
881         while (info.pcnt < 9) {
882                 res = linprocfs_readdir_root_callback(NULL, &info);
883                 if (res < 0)
884                         break;
885         }
886         if (res >= 0)
887                 allproc_scan(linprocfs_readdir_root_callback, &info);
888
889         uio->uio_offset = info.i;
890         return(info.error);
891 }
892
893 static int
894 linprocfs_readdir_root_callback(struct proc *p, void *data)
895 {
896         struct linprocfs_readdir_root_info *info = data;
897         int retval;
898         struct uio *uio = info->uio;
899         ino_t d_ino;
900         const char *d_name;
901         char d_name_pid[20];
902         size_t d_namlen;
903         uint8_t d_type;
904
905         switch (info->pcnt) {
906         case 0:         /* `.' */
907                 d_ino = PROCFS_FILENO(0, Proot);
908                 d_name = ".";
909                 d_namlen = 1;
910                 d_type = DT_DIR;
911                 break;
912         case 1:         /* `..' */
913                 d_ino = PROCFS_FILENO(0, Proot);
914                 d_name = "..";
915                 d_namlen = 2;
916                 d_type = DT_DIR;
917                 break;
918
919         case 2:
920                 d_ino = PROCFS_FILENO(0, Proot);
921                 d_namlen = 4;
922                 d_name = "self";
923                 d_type = DT_LNK;
924                 break;
925
926         case 3:
927                 d_ino = PROCFS_FILENO(0, Pmeminfo);
928                 d_namlen = 7;
929                 d_name = "meminfo";
930                 d_type = DT_REG;
931                 break;
932
933         case 4:
934                 d_ino = PROCFS_FILENO(0, Pcpuinfo);
935                 d_namlen = 7;
936                 d_name = "cpuinfo";
937                 d_type = DT_REG;
938                 break;
939
940         case 5:
941                 d_ino = PROCFS_FILENO(0, Pstat);
942                 d_namlen = 4;
943                 d_name = "stat";
944                 d_type = DT_REG;
945                 break;
946                     
947         case 6:
948                 d_ino = PROCFS_FILENO(0, Puptime);
949                 d_namlen = 6;
950                 d_name = "uptime";
951                 d_type = DT_REG;
952                 break;
953
954         case 7:
955                 d_ino = PROCFS_FILENO(0, Pversion);
956                 d_namlen = 7;
957                 d_name = "version";
958                 d_type = DT_REG;
959                 break;
960
961         case 8:
962                 d_ino = PROCFS_FILENO(0, Ploadavg);
963                 d_namlen = 7;
964                 d_name = "loadavg";
965                 d_type = DT_REG;
966                 break;
967
968         default:
969                 /*
970                  * Ignore processes that aren't in our prison
971                  */
972                 if (PRISON_CHECK(info->cred, p->p_ucred) == 0)
973                         return(0);
974
975                 /*
976                  * Ignore processes that we do not want to be visible.
977                  */
978                 if (ps_showallprocs == 0 && 
979                     info->cred->cr_uid != 0 &&
980                     info->cred->cr_uid != p->p_ucred->cr_uid) {
981                         return(0);
982                 }
983
984                 /*
985                  * Skip processes we have already read (optimization)
986                  */
987                 if (info->pcnt < info->i) {
988                         ++info->pcnt;
989                         return(0);
990                 }
991                 d_ino = PROCFS_FILENO(p->p_pid, Pproc);
992                 d_namlen = ksnprintf(d_name_pid, sizeof(d_name_pid),
993                     "%ld", (long)p->p_pid);
994                 d_name = d_name_pid;
995                 d_type = DT_DIR;
996                 break;
997         }
998
999         /*
1000          * Skip processes we have already read
1001          */
1002         if (info->pcnt < info->i) {
1003                 ++info->pcnt;
1004                 return(0);
1005         }
1006         retval = vop_write_dirent(&info->error, info->uio, 
1007                                   d_ino, d_type, d_namlen, d_name);
1008         if (retval == 0) {
1009                 ++info->pcnt;   /* iterate proc candidates scanned */
1010                 ++info->i;      /* iterate entries written */
1011         }
1012         if (retval || info->error || uio->uio_resid <= 0)
1013                 return(-1);
1014         return(0);
1015 }
1016
1017 /*
1018  * readlink reads the link of `self' or `exe'
1019  */
1020 static int
1021 linprocfs_readlink(struct vop_readlink_args *ap)
1022 {
1023         char buf[16];           /* should be enough */
1024         struct proc *procp;
1025         struct vnode *vp = ap->a_vp;
1026         struct pfsnode *pfs = VTOPFS(vp);
1027         char *fullpath, *freepath;
1028         int error, len;
1029
1030         switch (pfs->pfs_type) {
1031         case Pself:
1032                 if (pfs->pfs_fileno != PROCFS_FILENO(0, Pself))
1033                         return (EINVAL);
1034
1035                 len = ksnprintf(buf, sizeof(buf), "%ld", (long)curproc->p_pid);
1036
1037                 return (uiomove(buf, len, ap->a_uio));
1038         /*
1039          * There _should_ be no way for an entire process to disappear
1040          * from under us...
1041          */
1042         case Pexe:
1043                 procp = PFIND(pfs->pfs_pid);
1044                 if (procp == NULL || procp->p_ucred == NULL) {
1045                         kprintf("linprocfs_readlink: pid %d disappeared\n",
1046                             pfs->pfs_pid);
1047                         return (uiomove("unknown", sizeof("unknown") - 1,
1048                             ap->a_uio));
1049                 }
1050                 error = vn_fullpath(procp, NULL, &fullpath, &freepath);
1051                 if (error != 0)
1052                         return (uiomove("unknown", sizeof("unknown") - 1,
1053                             ap->a_uio));
1054                 error = uiomove(fullpath, strlen(fullpath), ap->a_uio);
1055                 kfree(freepath, M_TEMP);
1056                 return (error);
1057         default:
1058                 return (EINVAL);
1059         }
1060 }
1061
1062 /*
1063  * convert decimal ascii to pid_t
1064  */
1065 static pid_t
1066 atopid(const char *b, u_int len)
1067 {
1068         pid_t p = 0;
1069
1070         while (len--) {
1071                 char c = *b++;
1072                 if (c < '0' || c > '9')
1073                         return (NO_PID);
1074                 p = 10 * p + (c - '0');
1075                 if (p > PID_MAX)
1076                         return (NO_PID);
1077         }
1078
1079         return (p);
1080 }
1081