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