procfs_vnops.c revision 1.140.2.7 1 /* $NetBSD: procfs_vnops.c,v 1.140.2.7 2007/09/27 17:47:47 xtraeme Exp $ */
2
3 /*
4 * Copyright (c) 1993, 1995
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Jan-Simon Pendry.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
35 */
36
37 /*
38 * Copyright (c) 1993 Jan-Simon Pendry
39 *
40 * This code is derived from software contributed to Berkeley by
41 * Jan-Simon Pendry.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed by the University of
54 * California, Berkeley and its contributors.
55 * 4. Neither the name of the University nor the names of its contributors
56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 *
71 * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
72 */
73
74 /*
75 * procfs vnode interface
76 */
77
78 #include <sys/cdefs.h>
79 __KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.140.2.7 2007/09/27 17:47:47 xtraeme Exp $");
80
81 #include <sys/param.h>
82 #include <sys/systm.h>
83 #include <sys/time.h>
84 #include <sys/kernel.h>
85 #include <sys/file.h>
86 #include <sys/filedesc.h>
87 #include <sys/proc.h>
88 #include <sys/vnode.h>
89 #include <sys/namei.h>
90 #include <sys/malloc.h>
91 #include <sys/mount.h>
92 #include <sys/dirent.h>
93 #include <sys/resourcevar.h>
94 #include <sys/stat.h>
95 #include <sys/ptrace.h>
96 #include <sys/kauth.h>
97
98 #include <uvm/uvm_extern.h> /* for PAGE_SIZE */
99
100 #include <machine/reg.h>
101
102 #include <miscfs/genfs/genfs.h>
103 #include <miscfs/procfs/procfs.h>
104
105 /*
106 * Vnode Operations.
107 *
108 */
109
110 static int procfs_validfile_linux(struct lwp *, struct mount *);
111 static int procfs_root_readdir_callback(struct proc *, void *);
112 static struct vnode *procfs_dir(pfstype, struct lwp *, struct proc *,
113 char **, char *, int);
114
115 /*
116 * This is a list of the valid names in the
117 * process-specific sub-directories. It is
118 * used in procfs_lookup and procfs_readdir
119 */
120 static const struct proc_target {
121 u_char pt_type;
122 u_char pt_namlen;
123 const char *pt_name;
124 pfstype pt_pfstype;
125 int (*pt_valid)(struct lwp *, struct mount *);
126 } proc_targets[] = {
127 #define N(s) sizeof(s)-1, s
128 /* name type validp */
129 { DT_DIR, N("."), PFSproc, NULL },
130 { DT_DIR, N(".."), PFSroot, NULL },
131 { DT_DIR, N("fd"), PFSfd, NULL },
132 { DT_REG, N("file"), PFSfile, procfs_validfile },
133 { DT_REG, N("mem"), PFSmem, NULL },
134 { DT_REG, N("regs"), PFSregs, procfs_validregs },
135 { DT_REG, N("fpregs"), PFSfpregs, procfs_validfpregs },
136 { DT_REG, N("ctl"), PFSctl, NULL },
137 { DT_REG, N("stat"), PFSstat, procfs_validfile_linux },
138 { DT_REG, N("status"), PFSstatus, NULL },
139 { DT_REG, N("note"), PFSnote, NULL },
140 { DT_REG, N("notepg"), PFSnotepg, NULL },
141 { DT_REG, N("map"), PFSmap, procfs_validmap },
142 { DT_REG, N("maps"), PFSmaps, procfs_validmap },
143 { DT_REG, N("cmdline"), PFScmdline, NULL },
144 { DT_REG, N("exe"), PFSexe, procfs_validfile },
145 { DT_LNK, N("cwd"), PFScwd, NULL },
146 { DT_LNK, N("root"), PFSchroot, NULL },
147 { DT_LNK, N("emul"), PFSemul, NULL },
148 #ifdef __HAVE_PROCFS_MACHDEP
149 PROCFS_MACHDEP_NODETYPE_DEFNS
150 #endif
151 #undef N
152 };
153 static const int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]);
154
155 /*
156 * List of files in the root directory. Note: the validate function will
157 * be called with p == NULL for these ones.
158 */
159 static const struct proc_target proc_root_targets[] = {
160 #define N(s) sizeof(s)-1, s
161 /* name type validp */
162 { DT_REG, N("meminfo"), PFSmeminfo, procfs_validfile_linux },
163 { DT_REG, N("cpuinfo"), PFScpuinfo, procfs_validfile_linux },
164 { DT_REG, N("uptime"), PFSuptime, procfs_validfile_linux },
165 { DT_REG, N("mounts"), PFSmounts, procfs_validfile_linux },
166 { DT_REG, N("devices"), PFSdevices, procfs_validfile_linux },
167 #undef N
168 };
169 static const int nproc_root_targets =
170 sizeof(proc_root_targets) / sizeof(proc_root_targets[0]);
171
172 int procfs_lookup(void *);
173 #define procfs_create genfs_eopnotsupp
174 #define procfs_mknod genfs_eopnotsupp
175 int procfs_open(void *);
176 int procfs_close(void *);
177 int procfs_access(void *);
178 int procfs_getattr(void *);
179 int procfs_setattr(void *);
180 #define procfs_read procfs_rw
181 #define procfs_write procfs_rw
182 #define procfs_fcntl genfs_fcntl
183 #define procfs_ioctl genfs_enoioctl
184 #define procfs_poll genfs_poll
185 #define procfs_revoke genfs_revoke
186 #define procfs_fsync genfs_nullop
187 #define procfs_seek genfs_nullop
188 #define procfs_remove genfs_eopnotsupp
189 int procfs_link(void *);
190 #define procfs_rename genfs_eopnotsupp
191 #define procfs_mkdir genfs_eopnotsupp
192 #define procfs_rmdir genfs_eopnotsupp
193 int procfs_symlink(void *);
194 int procfs_readdir(void *);
195 int procfs_readlink(void *);
196 #define procfs_abortop genfs_abortop
197 int procfs_inactive(void *);
198 int procfs_reclaim(void *);
199 #define procfs_lock genfs_lock
200 #define procfs_unlock genfs_unlock
201 #define procfs_bmap genfs_badop
202 #define procfs_strategy genfs_badop
203 int procfs_print(void *);
204 int procfs_pathconf(void *);
205 #define procfs_islocked genfs_islocked
206 #define procfs_advlock genfs_einval
207 #define procfs_bwrite genfs_eopnotsupp
208 #define procfs_putpages genfs_null_putpages
209
210 static int atoi(const char *, size_t);
211
212 /*
213 * procfs vnode operations.
214 */
215 int (**procfs_vnodeop_p)(void *);
216 const struct vnodeopv_entry_desc procfs_vnodeop_entries[] = {
217 { &vop_default_desc, vn_default_error },
218 { &vop_lookup_desc, procfs_lookup }, /* lookup */
219 { &vop_create_desc, procfs_create }, /* create */
220 { &vop_mknod_desc, procfs_mknod }, /* mknod */
221 { &vop_open_desc, procfs_open }, /* open */
222 { &vop_close_desc, procfs_close }, /* close */
223 { &vop_access_desc, procfs_access }, /* access */
224 { &vop_getattr_desc, procfs_getattr }, /* getattr */
225 { &vop_setattr_desc, procfs_setattr }, /* setattr */
226 { &vop_read_desc, procfs_read }, /* read */
227 { &vop_write_desc, procfs_write }, /* write */
228 { &vop_fcntl_desc, procfs_fcntl }, /* fcntl */
229 { &vop_ioctl_desc, procfs_ioctl }, /* ioctl */
230 { &vop_poll_desc, procfs_poll }, /* poll */
231 { &vop_revoke_desc, procfs_revoke }, /* revoke */
232 { &vop_fsync_desc, procfs_fsync }, /* fsync */
233 { &vop_seek_desc, procfs_seek }, /* seek */
234 { &vop_remove_desc, procfs_remove }, /* remove */
235 { &vop_link_desc, procfs_link }, /* link */
236 { &vop_rename_desc, procfs_rename }, /* rename */
237 { &vop_mkdir_desc, procfs_mkdir }, /* mkdir */
238 { &vop_rmdir_desc, procfs_rmdir }, /* rmdir */
239 { &vop_symlink_desc, procfs_symlink }, /* symlink */
240 { &vop_readdir_desc, procfs_readdir }, /* readdir */
241 { &vop_readlink_desc, procfs_readlink }, /* readlink */
242 { &vop_abortop_desc, procfs_abortop }, /* abortop */
243 { &vop_inactive_desc, procfs_inactive }, /* inactive */
244 { &vop_reclaim_desc, procfs_reclaim }, /* reclaim */
245 { &vop_lock_desc, procfs_lock }, /* lock */
246 { &vop_unlock_desc, procfs_unlock }, /* unlock */
247 { &vop_bmap_desc, procfs_bmap }, /* bmap */
248 { &vop_strategy_desc, procfs_strategy }, /* strategy */
249 { &vop_print_desc, procfs_print }, /* print */
250 { &vop_islocked_desc, procfs_islocked }, /* islocked */
251 { &vop_pathconf_desc, procfs_pathconf }, /* pathconf */
252 { &vop_advlock_desc, procfs_advlock }, /* advlock */
253 { &vop_putpages_desc, procfs_putpages }, /* putpages */
254 { NULL, NULL }
255 };
256 const struct vnodeopv_desc procfs_vnodeop_opv_desc =
257 { &procfs_vnodeop_p, procfs_vnodeop_entries };
258 /*
259 * set things up for doing i/o on
260 * the pfsnode (vp). (vp) is locked
261 * on entry, and should be left locked
262 * on exit.
263 *
264 * for procfs we don't need to do anything
265 * in particular for i/o. all that is done
266 * is to support exclusive open on process
267 * memory images.
268 */
269 int
270 procfs_open(v)
271 void *v;
272 {
273 struct vop_open_args /* {
274 struct vnode *a_vp;
275 int a_mode;
276 kauth_cred_t a_cred;
277 struct lwp *a_l;
278 } */ *ap = v;
279 struct pfsnode *pfs = VTOPFS(ap->a_vp);
280 struct lwp *l1;
281 struct proc *p2;
282 int error;
283
284 l1 = ap->a_l; /* tracer */
285 p2 = PFIND(pfs->pfs_pid); /* traced */
286
287 if (p2 == NULL)
288 return (ENOENT); /* was ESRCH, jsp */
289
290 if (ISSET(p2->p_flag, P_INEXEC))
291 return (EAGAIN);
292
293 #define M2K(m) (((m) & FREAD) && ((m) & FWRITE) ? \
294 KAUTH_REQ_PROCESS_CANPROCFS_RW : \
295 (m) & FWRITE ? KAUTH_REQ_PROCESS_CANPROCFS_WRITE : \
296 KAUTH_REQ_PROCESS_CANPROCFS_READ)
297
298 error = kauth_authorize_process(l1->l_cred, KAUTH_PROCESS_CANPROCFS,
299 p2, pfs, KAUTH_ARG(M2K(ap->a_mode)), NULL);
300 if (error)
301 return (error);
302
303 #undef M2K
304
305 switch (pfs->pfs_type) {
306 case PFSmem:
307 if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) ||
308 ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE)))
309 return (EBUSY);
310
311 if (!proc_isunder(p2, l1))
312 return (EPERM);
313
314 if (ap->a_mode & FWRITE)
315 pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL);
316
317 break;
318
319 case PFSregs:
320 case PFSfpregs:
321 if (!proc_isunder(p2, l1))
322 return (EPERM);
323
324 break;
325
326 default:
327 break;
328 }
329
330 return (0);
331 }
332
333 /*
334 * close the pfsnode (vp) after doing i/o.
335 * (vp) is not locked on entry or exit.
336 *
337 * nothing to do for procfs other than undo
338 * any exclusive open flag (see _open above).
339 */
340 int
341 procfs_close(v)
342 void *v;
343 {
344 struct vop_close_args /* {
345 struct vnode *a_vp;
346 int a_fflag;
347 kauth_cred_t a_cred;
348 struct lwp *a_l;
349 } */ *ap = v;
350 struct pfsnode *pfs = VTOPFS(ap->a_vp);
351
352 switch (pfs->pfs_type) {
353 case PFSmem:
354 if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL))
355 pfs->pfs_flags &= ~(FWRITE|O_EXCL);
356 break;
357
358 default:
359 break;
360 }
361
362 return (0);
363 }
364
365 /*
366 * _inactive is called when the pfsnode
367 * is vrele'd and the reference count goes
368 * to zero. (vp) will be on the vnode free
369 * list, so to get it back vget() must be
370 * used.
371 *
372 * for procfs, check if the process is still
373 * alive and if it isn't then just throw away
374 * the vnode by calling vgone(). this may
375 * be overkill and a waste of time since the
376 * chances are that the process will still be
377 * there and PFIND is not free.
378 *
379 * (vp) is locked on entry, but must be unlocked on exit.
380 */
381 int
382 procfs_inactive(v)
383 void *v;
384 {
385 struct vop_inactive_args /* {
386 struct vnode *a_vp;
387 struct proc *a_p;
388 } */ *ap = v;
389 struct vnode *vp = ap->a_vp;
390 struct pfsnode *pfs = VTOPFS(vp);
391
392 VOP_UNLOCK(vp, 0);
393 if (PFIND(pfs->pfs_pid) == NULL && (vp->v_flag & VXLOCK) == 0)
394 vgone(vp);
395
396 return (0);
397 }
398
399 /*
400 * _reclaim is called when getnewvnode()
401 * wants to make use of an entry on the vnode
402 * free list. at this time the filesystem needs
403 * to free any private data and remove the node
404 * from any private lists.
405 */
406 int
407 procfs_reclaim(v)
408 void *v;
409 {
410 struct vop_reclaim_args /* {
411 struct vnode *a_vp;
412 } */ *ap = v;
413
414 return (procfs_freevp(ap->a_vp));
415 }
416
417 /*
418 * Return POSIX pathconf information applicable to special devices.
419 */
420 int
421 procfs_pathconf(v)
422 void *v;
423 {
424 struct vop_pathconf_args /* {
425 struct vnode *a_vp;
426 int a_name;
427 register_t *a_retval;
428 } */ *ap = v;
429
430 switch (ap->a_name) {
431 case _PC_LINK_MAX:
432 *ap->a_retval = LINK_MAX;
433 return (0);
434 case _PC_MAX_CANON:
435 *ap->a_retval = MAX_CANON;
436 return (0);
437 case _PC_MAX_INPUT:
438 *ap->a_retval = MAX_INPUT;
439 return (0);
440 case _PC_PIPE_BUF:
441 *ap->a_retval = PIPE_BUF;
442 return (0);
443 case _PC_CHOWN_RESTRICTED:
444 *ap->a_retval = 1;
445 return (0);
446 case _PC_VDISABLE:
447 *ap->a_retval = _POSIX_VDISABLE;
448 return (0);
449 case _PC_SYNC_IO:
450 *ap->a_retval = 1;
451 return (0);
452 default:
453 return (EINVAL);
454 }
455 /* NOTREACHED */
456 }
457
458 /*
459 * _print is used for debugging.
460 * just print a readable description
461 * of (vp).
462 */
463 int
464 procfs_print(v)
465 void *v;
466 {
467 struct vop_print_args /* {
468 struct vnode *a_vp;
469 } */ *ap = v;
470 struct pfsnode *pfs = VTOPFS(ap->a_vp);
471
472 printf("tag VT_PROCFS, type %d, pid %d, mode %x, flags %lx\n",
473 pfs->pfs_type, pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags);
474 return 0;
475 }
476
477 int
478 procfs_link(v)
479 void *v;
480 {
481 struct vop_link_args /* {
482 struct vnode *a_dvp;
483 struct vnode *a_vp;
484 struct componentname *a_cnp;
485 } */ *ap = v;
486
487 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
488 vput(ap->a_dvp);
489 return (EROFS);
490 }
491
492 int
493 procfs_symlink(v)
494 void *v;
495 {
496 struct vop_symlink_args /* {
497 struct vnode *a_dvp;
498 struct vnode **a_vpp;
499 struct componentname *a_cnp;
500 struct vattr *a_vap;
501 char *a_target;
502 } */ *ap = v;
503
504 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
505 vput(ap->a_dvp);
506 return (EROFS);
507 }
508
509 /*
510 * Works out the path to (and vnode of) the target process's current
511 * working directory or chroot. If the caller is in a chroot and
512 * can't "reach" the target's cwd or root (or some other error
513 * occurs), a "/" is returned for the path and a NULL pointer is
514 * returned for the vnode.
515 */
516 static struct vnode *
517 procfs_dir(pfstype t, struct lwp *caller, struct proc *target,
518 char **bpp, char *path, int len)
519 {
520 struct vnode *vp, *rvp = caller->l_proc->p_cwdi->cwdi_rdir;
521 char *bp;
522
523 bp = bpp ? *bpp : NULL;
524
525 switch (t) {
526 case PFScwd:
527 vp = target->p_cwdi->cwdi_cdir;
528 break;
529 case PFSchroot:
530 vp = target->p_cwdi->cwdi_rdir;
531 break;
532 case PFSexe:
533 vp = target->p_textvp;
534 break;
535 default:
536 return (NULL);
537 }
538
539 /*
540 * XXX: this horrible kludge avoids locking panics when
541 * attempting to lookup links that point to within procfs
542 */
543 if (vp != NULL && vp->v_tag == VT_PROCFS) {
544 if (bpp) {
545 *--bp = '/';
546 *bpp = bp;
547 }
548 return vp;
549 }
550
551 if (rvp == NULL)
552 rvp = rootvnode;
553 if (vp == NULL || getcwd_common(vp, rvp, bp ? &bp : NULL, path,
554 len / 2, 0, caller) != 0) {
555 vp = NULL;
556 if (bpp) {
557 bp = *bpp;
558 *--bp = '/';
559 }
560 }
561
562 if (bpp)
563 *bpp = bp;
564
565 return (vp);
566 }
567
568 /*
569 * Invent attributes for pfsnode (vp) and store
570 * them in (vap).
571 * Directories lengths are returned as zero since
572 * any real length would require the genuine size
573 * to be computed, and nothing cares anyway.
574 *
575 * this is relatively minimal for procfs.
576 */
577 int
578 procfs_getattr(v)
579 void *v;
580 {
581 struct vop_getattr_args /* {
582 struct vnode *a_vp;
583 struct vattr *a_vap;
584 kauth_cred_t a_cred;
585 struct lwp *a_l;
586 } */ *ap = v;
587 struct pfsnode *pfs = VTOPFS(ap->a_vp);
588 struct vattr *vap = ap->a_vap;
589 struct proc *procp;
590 int error;
591
592 /* first check the process still exists */
593 switch (pfs->pfs_type) {
594 case PFSroot:
595 case PFScurproc:
596 case PFSself:
597 procp = 0;
598 break;
599
600 default:
601 procp = PFIND(pfs->pfs_pid);
602 if (procp == NULL)
603 return (ENOENT);
604 break;
605 }
606
607 if (procp != NULL) {
608 if (kauth_authorize_process(kauth_cred_get(),
609 KAUTH_PROCESS_CANSEE, procp, NULL, NULL, NULL) != 0)
610 return (ENOENT);
611 }
612
613 error = 0;
614
615 /* start by zeroing out the attributes */
616 VATTR_NULL(vap);
617
618 /* next do all the common fields */
619 vap->va_type = ap->a_vp->v_type;
620 vap->va_mode = pfs->pfs_mode;
621 vap->va_fileid = pfs->pfs_fileno;
622 vap->va_flags = 0;
623 vap->va_blocksize = PAGE_SIZE;
624
625 /*
626 * Make all times be current TOD.
627 *
628 * It would be possible to get the process start
629 * time from the p_stats structure, but there's
630 * no "file creation" time stamp anyway, and the
631 * p_stats structure is not addressable if u. gets
632 * swapped out for that process.
633 */
634 getnanotime(&vap->va_ctime);
635 vap->va_atime = vap->va_mtime = vap->va_ctime;
636 if (procp)
637 TIMEVAL_TO_TIMESPEC(&procp->p_stats->p_start,
638 &vap->va_birthtime);
639 else
640 getnanotime(&vap->va_birthtime);
641
642 switch (pfs->pfs_type) {
643 case PFSmem:
644 case PFSregs:
645 case PFSfpregs:
646 #if defined(__HAVE_PROCFS_MACHDEP) && defined(PROCFS_MACHDEP_PROTECT_CASES)
647 PROCFS_MACHDEP_PROTECT_CASES
648 #endif
649 /*
650 * If the process has exercised some setuid or setgid
651 * privilege, then rip away read/write permission so
652 * that only root can gain access.
653 */
654 if (procp->p_flag & P_SUGID)
655 vap->va_mode &= ~(S_IRUSR|S_IWUSR);
656 /* FALLTHROUGH */
657 case PFSctl:
658 case PFSstatus:
659 case PFSstat:
660 case PFSnote:
661 case PFSnotepg:
662 case PFSmap:
663 case PFSmaps:
664 case PFScmdline:
665 case PFSemul:
666 vap->va_nlink = 1;
667 vap->va_uid = kauth_cred_geteuid(procp->p_cred);
668 vap->va_gid = kauth_cred_getegid(procp->p_cred);
669 break;
670 case PFSmeminfo:
671 case PFSdevices:
672 case PFScpuinfo:
673 case PFSuptime:
674 case PFSmounts:
675 vap->va_nlink = 1;
676 vap->va_uid = vap->va_gid = 0;
677 break;
678
679 default:
680 break;
681 }
682
683 /*
684 * now do the object specific fields
685 *
686 * The size could be set from struct reg, but it's hardly
687 * worth the trouble, and it puts some (potentially) machine
688 * dependent data into this machine-independent code. If it
689 * becomes important then this function should break out into
690 * a per-file stat function in the corresponding .c file.
691 */
692
693 switch (pfs->pfs_type) {
694 case PFSroot:
695 /*
696 * Set nlink to 1 to tell fts(3) we don't actually know.
697 */
698 vap->va_nlink = 1;
699 vap->va_uid = 0;
700 vap->va_gid = 0;
701 vap->va_bytes = vap->va_size = DEV_BSIZE;
702 break;
703
704 case PFSself:
705 case PFScurproc: {
706 char bf[16]; /* should be enough */
707 vap->va_nlink = 1;
708 vap->va_uid = 0;
709 vap->va_gid = 0;
710 vap->va_bytes = vap->va_size =
711 snprintf(bf, sizeof(bf), "%ld", (long)curproc->p_pid);
712 break;
713 }
714
715 case PFSfd:
716 if (pfs->pfs_fd != -1) {
717 struct file *fp;
718 struct proc *pown;
719
720 if ((error = procfs_getfp(pfs, &pown, &fp)) != 0)
721 return error;
722 FILE_USE(fp);
723 vap->va_nlink = 1;
724 vap->va_uid = kauth_cred_geteuid(fp->f_cred);
725 vap->va_gid = kauth_cred_getegid(fp->f_cred);
726 switch (fp->f_type) {
727 case DTYPE_VNODE:
728 vap->va_bytes = vap->va_size =
729 ((struct vnode *)fp->f_data)->v_size;
730 break;
731 default:
732 vap->va_bytes = vap->va_size = 0;
733 break;
734 }
735 FILE_UNUSE(fp, proc_representative_lwp(pown));
736 break;
737 }
738 /*FALLTHROUGH*/
739 case PFSproc:
740 vap->va_nlink = 2;
741 vap->va_uid = kauth_cred_geteuid(procp->p_cred);
742 vap->va_gid = kauth_cred_getegid(procp->p_cred);
743 vap->va_bytes = vap->va_size = DEV_BSIZE;
744 break;
745
746 case PFSfile:
747 error = EOPNOTSUPP;
748 break;
749
750 case PFSmem:
751 vap->va_bytes = vap->va_size =
752 ctob(procp->p_vmspace->vm_tsize +
753 procp->p_vmspace->vm_dsize +
754 procp->p_vmspace->vm_ssize);
755 break;
756
757 #if defined(PT_GETREGS) || defined(PT_SETREGS)
758 case PFSregs:
759 vap->va_bytes = vap->va_size = sizeof(struct reg);
760 break;
761 #endif
762
763 #if defined(PT_GETFPREGS) || defined(PT_SETFPREGS)
764 case PFSfpregs:
765 vap->va_bytes = vap->va_size = sizeof(struct fpreg);
766 break;
767 #endif
768
769 case PFSctl:
770 case PFSstatus:
771 case PFSstat:
772 case PFSnote:
773 case PFSnotepg:
774 case PFScmdline:
775 case PFSmeminfo:
776 case PFSdevices:
777 case PFScpuinfo:
778 case PFSuptime:
779 case PFSmounts:
780 vap->va_bytes = vap->va_size = 0;
781 break;
782 case PFSmap:
783 case PFSmaps:
784 /*
785 * Advise a larger blocksize for the map files, so that
786 * they may be read in one pass.
787 */
788 vap->va_blocksize = 4 * PAGE_SIZE;
789 vap->va_bytes = vap->va_size = 0;
790 break;
791
792 case PFScwd:
793 case PFSchroot:
794 case PFSexe: {
795 char *path, *bp;
796
797 MALLOC(path, char *, MAXPATHLEN + 4, M_TEMP,
798 M_WAITOK|M_CANFAIL);
799 if (path == NULL)
800 return (ENOMEM);
801 vap->va_nlink = 1;
802 vap->va_uid = 0;
803 vap->va_gid = 0;
804 bp = path + MAXPATHLEN;
805 *--bp = '\0';
806 (void)procfs_dir(pfs->pfs_type, curlwp, procp, &bp, path,
807 MAXPATHLEN);
808 vap->va_bytes = vap->va_size = strlen(bp);
809 free(path, M_TEMP);
810 break;
811 }
812
813 case PFSemul:
814 vap->va_bytes = vap->va_size = strlen(procp->p_emul->e_name);
815 break;
816
817 #ifdef __HAVE_PROCFS_MACHDEP
818 PROCFS_MACHDEP_NODETYPE_CASES
819 error = procfs_machdep_getattr(ap->a_vp, vap, procp);
820 break;
821 #endif
822
823 default:
824 panic("procfs_getattr");
825 }
826
827 return (error);
828 }
829
830 /*ARGSUSED*/
831 int
832 procfs_setattr(void *v)
833 {
834 /*
835 * just fake out attribute setting
836 * it's not good to generate an error
837 * return, otherwise things like creat()
838 * will fail when they try to set the
839 * file length to 0. worse, this means
840 * that echo $note > /proc/$pid/note will fail.
841 */
842
843 return (0);
844 }
845
846 /*
847 * implement access checking.
848 *
849 * actually, the check for super-user is slightly
850 * broken since it will allow read access to write-only
851 * objects. this doesn't cause any particular trouble
852 * but does mean that the i/o entry points need to check
853 * that the operation really does make sense.
854 */
855 int
856 procfs_access(v)
857 void *v;
858 {
859 struct vop_access_args /* {
860 struct vnode *a_vp;
861 int a_mode;
862 kauth_cred_t a_cred;
863 struct lwp *a_l;
864 } */ *ap = v;
865 struct vattr va;
866 int error;
867
868 if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_l)) != 0)
869 return (error);
870
871 return (vaccess(va.va_type, va.va_mode,
872 va.va_uid, va.va_gid, ap->a_mode, ap->a_cred));
873 }
874
875 /*
876 * lookup. this is incredibly complicated in the
877 * general case, however for most pseudo-filesystems
878 * very little needs to be done.
879 *
880 * Locking isn't hard here, just poorly documented.
881 *
882 * If we're looking up ".", just vref the parent & return it.
883 *
884 * If we're looking up "..", unlock the parent, and lock "..". If everything
885 * went ok, and we're on the last component and the caller requested the
886 * parent locked, try to re-lock the parent. We do this to prevent lock
887 * races.
888 *
889 * For anything else, get the needed node. Then unlock the parent if not
890 * the last component or not LOCKPARENT (i.e. if we wouldn't re-lock the
891 * parent in the .. case).
892 *
893 * We try to exit with the parent locked in error cases.
894 */
895 int
896 procfs_lookup(v)
897 void *v;
898 {
899 struct vop_lookup_args /* {
900 struct vnode * a_dvp;
901 struct vnode ** a_vpp;
902 struct componentname * a_cnp;
903 } */ *ap = v;
904 struct componentname *cnp = ap->a_cnp;
905 struct vnode **vpp = ap->a_vpp;
906 struct vnode *dvp = ap->a_dvp;
907 const char *pname = cnp->cn_nameptr;
908 const struct proc_target *pt = NULL;
909 struct vnode *fvp;
910 pid_t pid;
911 struct pfsnode *pfs;
912 struct proc *p = NULL;
913 struct lwp *l = NULL;
914 int i, error, iscurproc = 0, isself = 0;
915
916 *vpp = NULL;
917
918 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
919 return (EROFS);
920
921 if (cnp->cn_namelen == 1 && *pname == '.') {
922 *vpp = dvp;
923 VREF(dvp);
924 return (0);
925 }
926
927 pfs = VTOPFS(dvp);
928 switch (pfs->pfs_type) {
929 case PFSroot:
930 /*
931 * Shouldn't get here with .. in the root node.
932 */
933 if (cnp->cn_flags & ISDOTDOT)
934 return (EIO);
935
936 iscurproc = CNEQ(cnp, "curproc", 7);
937 isself = CNEQ(cnp, "self", 4);
938
939 if (iscurproc || isself) {
940 error = procfs_allocvp(dvp->v_mount, vpp, 0,
941 iscurproc ? PFScurproc : PFSself, -1);
942 return (error);
943 }
944
945 for (i = 0; i < nproc_root_targets; i++) {
946 pt = &proc_root_targets[i];
947 /*
948 * check for node match. proc is always NULL here,
949 * so call pt_valid with constant NULL lwp.
950 */
951 if (cnp->cn_namelen == pt->pt_namlen &&
952 memcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 &&
953 (pt->pt_valid == NULL ||
954 (*pt->pt_valid)(NULL, dvp->v_mount)))
955 break;
956 }
957
958 if (i != nproc_root_targets) {
959 error = procfs_allocvp(dvp->v_mount, vpp, 0,
960 pt->pt_pfstype, -1);
961 return (error);
962 }
963
964 pid = (pid_t)atoi(pname, cnp->cn_namelen);
965
966 p = PFIND(pid);
967 if (p == NULL)
968 break;
969
970 error = procfs_allocvp(dvp->v_mount, vpp, pid, PFSproc, -1);
971 return (error);
972
973 case PFSproc:
974 /*
975 * do the .. dance. We unlock the directory, and then
976 * get the root dir. That will automatically return ..
977 * locked. Then if the caller wanted dvp locked, we
978 * re-lock.
979 */
980 if (cnp->cn_flags & ISDOTDOT) {
981 VOP_UNLOCK(dvp, 0);
982 error = procfs_root(dvp->v_mount, vpp);
983 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
984 return (error);
985 }
986
987 p = PFIND(pfs->pfs_pid);
988 if (p == NULL)
989 break;
990 l = proc_representative_lwp(p);
991
992 for (pt = proc_targets, i = 0; i < nproc_targets; pt++, i++) {
993 if (cnp->cn_namelen == pt->pt_namlen &&
994 memcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 &&
995 (pt->pt_valid == NULL || (p != NULL &&
996 (*pt->pt_valid)(proc_representative_lwp(p),
997 dvp->v_mount))))
998 goto found;
999 }
1000 break;
1001
1002 found:
1003 if (pt->pt_pfstype == PFSfile) {
1004 fvp = p->p_textvp;
1005 /* We already checked that it exists. */
1006 VREF(fvp);
1007 vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY);
1008 *vpp = fvp;
1009 return (0);
1010 }
1011
1012 error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
1013 pt->pt_pfstype, -1);
1014 return (error);
1015
1016 case PFSfd: {
1017 int fd;
1018 struct file *fp;
1019 /*
1020 * do the .. dance. We unlock the directory, and then
1021 * get the proc dir. That will automatically return ..
1022 * locked. Then re-lock the directory.
1023 */
1024 if (cnp->cn_flags & ISDOTDOT) {
1025 VOP_UNLOCK(dvp, 0);
1026 error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
1027 PFSproc, -1);
1028 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
1029 return (error);
1030 }
1031 fd = atoi(pname, cnp->cn_namelen);
1032 p = PFIND(pfs->pfs_pid);
1033 if (p == NULL || (fp = fd_getfile(p->p_fd, fd)) == NULL)
1034 return ENOENT;
1035 FILE_USE(fp);
1036
1037 switch (fp->f_type) {
1038 case DTYPE_VNODE:
1039 fvp = (struct vnode *)fp->f_data;
1040
1041 /* Don't show directories */
1042 if (fvp->v_type == VDIR)
1043 goto symlink;
1044
1045 VREF(fvp);
1046 FILE_UNUSE(fp, l);
1047 vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY |
1048 (p == curproc ? LK_CANRECURSE : 0));
1049 *vpp = fvp;
1050 error = 0;
1051 break;
1052 default:
1053 symlink:
1054 FILE_UNUSE(fp, l);
1055 error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
1056 PFSfd, fd);
1057 break;
1058 }
1059 return error;
1060 }
1061 default:
1062 return (ENOTDIR);
1063 }
1064
1065 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
1066 }
1067
1068 int
1069 procfs_validfile(struct lwp *l, struct mount *mp)
1070 {
1071 return l != NULL && l->l_proc != NULL && l->l_proc->p_textvp != NULL;
1072 }
1073
1074 static int
1075 procfs_validfile_linux(l, mp)
1076 struct lwp *l;
1077 struct mount *mp;
1078 {
1079 int flags;
1080
1081 flags = VFSTOPROC(mp)->pmnt_flags;
1082 return (flags & PROCFSMNT_LINUXCOMPAT) &&
1083 (l == NULL || l->l_proc == NULL || procfs_validfile(l, mp));
1084 }
1085
1086 struct procfs_root_readdir_ctx {
1087 struct uio *uiop;
1088 off_t *cookies;
1089 int ncookies;
1090 off_t off;
1091 off_t startoff;
1092 int error;
1093 };
1094
1095 static int
1096 procfs_root_readdir_callback(struct proc *p, void *arg)
1097 {
1098 struct procfs_root_readdir_ctx *ctxp = arg;
1099 struct dirent d;
1100 struct uio *uiop;
1101 int error;
1102
1103 uiop = ctxp->uiop;
1104 if (uiop->uio_resid < UIO_MX)
1105 return -1; /* no space */
1106
1107 if (ctxp->off < ctxp->startoff) {
1108 ctxp->off++;
1109 return 0;
1110 }
1111
1112 if (kauth_authorize_process(kauth_cred_get(),
1113 KAUTH_PROCESS_CANSEE, p, NULL, NULL, NULL) != 0)
1114 return 0;
1115
1116 memset(&d, 0, UIO_MX);
1117 d.d_reclen = UIO_MX;
1118 d.d_fileno = PROCFS_FILENO(p->p_pid, PFSproc, -1);
1119 d.d_namlen = snprintf(d.d_name,
1120 UIO_MX - offsetof(struct dirent, d_name), "%ld", (long)p->p_pid);
1121 d.d_type = DT_DIR;
1122
1123 proclist_unlock_read();
1124 error = uiomove(&d, UIO_MX, uiop);
1125 proclist_lock_read();
1126 if (error) {
1127 ctxp->error = error;
1128 return -1;
1129 }
1130
1131 ctxp->ncookies++;
1132 if (ctxp->cookies)
1133 *(ctxp->cookies)++ = ctxp->off + 1;
1134 ctxp->off++;
1135
1136 return 0;
1137 }
1138
1139 /*
1140 * readdir returns directory entries from pfsnode (vp).
1141 *
1142 * the strategy here with procfs is to generate a single
1143 * directory entry at a time (struct dirent) and then
1144 * copy that out to userland using uiomove. a more efficent
1145 * though more complex implementation, would try to minimize
1146 * the number of calls to uiomove(). for procfs, this is
1147 * hardly worth the added code complexity.
1148 *
1149 * this should just be done through read()
1150 */
1151 int
1152 procfs_readdir(v)
1153 void *v;
1154 {
1155 struct vop_readdir_args /* {
1156 struct vnode *a_vp;
1157 struct uio *a_uio;
1158 kauth_cred_t a_cred;
1159 int *a_eofflag;
1160 off_t **a_cookies;
1161 int *a_ncookies;
1162 } */ *ap = v;
1163 struct uio *uio = ap->a_uio;
1164 struct dirent d;
1165 struct pfsnode *pfs;
1166 off_t i;
1167 int error;
1168 off_t *cookies = NULL;
1169 int ncookies;
1170 struct vnode *vp;
1171 const struct proc_target *pt;
1172 struct procfs_root_readdir_ctx ctx;
1173
1174 vp = ap->a_vp;
1175 pfs = VTOPFS(vp);
1176
1177 if (uio->uio_resid < UIO_MX)
1178 return (EINVAL);
1179 if (uio->uio_offset < 0)
1180 return (EINVAL);
1181
1182 error = 0;
1183 i = uio->uio_offset;
1184 memset(&d, 0, UIO_MX);
1185 d.d_reclen = UIO_MX;
1186 ncookies = uio->uio_resid / UIO_MX;
1187
1188 switch (pfs->pfs_type) {
1189 /*
1190 * this is for the process-specific sub-directories.
1191 * all that is needed to is copy out all the entries
1192 * from the procent[] table (top of this file).
1193 */
1194 case PFSproc: {
1195 struct proc *p;
1196
1197 if (i >= nproc_targets)
1198 return 0;
1199
1200 p = PFIND(pfs->pfs_pid);
1201 if (p == NULL)
1202 break;
1203
1204 if (ap->a_ncookies) {
1205 ncookies = min(ncookies, (nproc_targets - i));
1206 cookies = malloc(ncookies * sizeof (off_t),
1207 M_TEMP, M_WAITOK);
1208 *ap->a_cookies = cookies;
1209 }
1210
1211 for (pt = &proc_targets[i];
1212 uio->uio_resid >= UIO_MX && i < nproc_targets; pt++, i++) {
1213 if (pt->pt_valid &&
1214 (*pt->pt_valid)(proc_representative_lwp(p), vp->v_mount) == 0)
1215 continue;
1216
1217 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid,
1218 pt->pt_pfstype, -1);
1219 d.d_namlen = pt->pt_namlen;
1220 memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1);
1221 d.d_type = pt->pt_type;
1222
1223 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1224 break;
1225 if (cookies)
1226 *cookies++ = i + 1;
1227 }
1228
1229 break;
1230 }
1231 case PFSfd: {
1232 struct proc *p;
1233 struct filedesc *fdp;
1234 struct file *fp;
1235 int lim, nc = 0;
1236
1237 p = PFIND(pfs->pfs_pid);
1238 if (p == NULL)
1239 return ESRCH;
1240
1241 if (kauth_authorize_process(kauth_cred_get(),
1242 KAUTH_PROCESS_CANSEE, p, NULL, NULL, NULL) != 0)
1243 return ESRCH;
1244
1245 fdp = p->p_fd;
1246
1247 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
1248 if (i >= lim)
1249 return 0;
1250
1251 if (ap->a_ncookies) {
1252 ncookies = min(ncookies, (fdp->fd_nfiles + 2 - i));
1253 cookies = malloc(ncookies * sizeof (off_t),
1254 M_TEMP, M_WAITOK);
1255 *ap->a_cookies = cookies;
1256 }
1257
1258 for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
1259 pt = &proc_targets[i];
1260 d.d_namlen = pt->pt_namlen;
1261 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid,
1262 pt->pt_pfstype, -1);
1263 (void)memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1);
1264 d.d_type = pt->pt_type;
1265 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1266 break;
1267 if (cookies)
1268 *cookies++ = i + 1;
1269 nc++;
1270 }
1271 if (error) {
1272 ncookies = nc;
1273 break;
1274 }
1275 for (; uio->uio_resid >= UIO_MX && i < fdp->fd_nfiles; i++) {
1276 /* check the descriptor exists */
1277 if ((fp = fd_getfile(fdp, i - 2)) == NULL)
1278 continue;
1279 simple_unlock(&fp->f_slock);
1280
1281 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, PFSfd, i - 2);
1282 d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1283 "%lld", (long long)(i - 2));
1284 d.d_type = VREG;
1285 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1286 break;
1287 if (cookies)
1288 *cookies++ = i + 1;
1289 nc++;
1290 }
1291 ncookies = nc;
1292 break;
1293 }
1294
1295 /*
1296 * this is for the root of the procfs filesystem
1297 * what is needed are special entries for "curproc"
1298 * and "self" followed by an entry for each process
1299 * on allproc.
1300 */
1301
1302 case PFSroot: {
1303 int nc = 0;
1304
1305 if (ap->a_ncookies) {
1306 /*
1307 * XXX Potentially allocating too much space here,
1308 * but I'm lazy. This loop needs some work.
1309 */
1310 cookies = malloc(ncookies * sizeof (off_t),
1311 M_TEMP, M_WAITOK);
1312 *ap->a_cookies = cookies;
1313 }
1314 error = 0;
1315 /* 0 ... 3 are static entries. */
1316 for (; i <= 3 && uio->uio_resid >= UIO_MX; i++) {
1317 switch (i) {
1318 case 0: /* `.' */
1319 case 1: /* `..' */
1320 d.d_fileno = PROCFS_FILENO(0, PFSroot, -1);
1321 d.d_namlen = i + 1;
1322 memcpy(d.d_name, "..", d.d_namlen);
1323 d.d_name[i + 1] = '\0';
1324 d.d_type = DT_DIR;
1325 break;
1326
1327 case 2:
1328 d.d_fileno = PROCFS_FILENO(0, PFScurproc, -1);
1329 d.d_namlen = sizeof("curproc") - 1;
1330 memcpy(d.d_name, "curproc", sizeof("curproc"));
1331 d.d_type = DT_LNK;
1332 break;
1333
1334 case 3:
1335 d.d_fileno = PROCFS_FILENO(0, PFSself, -1);
1336 d.d_namlen = sizeof("self") - 1;
1337 memcpy(d.d_name, "self", sizeof("self"));
1338 d.d_type = DT_LNK;
1339 break;
1340 }
1341
1342 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1343 break;
1344 nc++;
1345 if (cookies)
1346 *cookies++ = i + 1;
1347 }
1348 /* 4 ... are process entries. */
1349 ctx.uiop = uio;
1350 ctx.error = 0;
1351 ctx.off = 4;
1352 ctx.startoff = i;
1353 ctx.cookies = cookies;
1354 ctx.ncookies = nc;
1355 proclist_foreach_call(&allproc,
1356 procfs_root_readdir_callback, &ctx);
1357 cookies = ctx.cookies;
1358 nc = ctx.ncookies;
1359 error = ctx.error;
1360 if (error)
1361 break;
1362
1363 /* misc entries. */
1364 if (i < ctx.off)
1365 i = ctx.off;
1366 if (i >= ctx.off + nproc_root_targets)
1367 break;
1368 for (pt = &proc_root_targets[i - ctx.off];
1369 uio->uio_resid >= UIO_MX &&
1370 pt < &proc_root_targets[nproc_root_targets];
1371 pt++, i++) {
1372 if (pt->pt_valid &&
1373 (*pt->pt_valid)(NULL, vp->v_mount) == 0)
1374 continue;
1375 d.d_fileno = PROCFS_FILENO(0, pt->pt_pfstype, -1);
1376 d.d_namlen = pt->pt_namlen;
1377 memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1);
1378 d.d_type = pt->pt_type;
1379
1380 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1381 break;
1382 nc++;
1383 if (cookies)
1384 *cookies++ = i + 1;
1385 }
1386
1387 ncookies = nc;
1388 break;
1389 }
1390
1391 default:
1392 error = ENOTDIR;
1393 break;
1394 }
1395
1396 if (ap->a_ncookies) {
1397 if (error) {
1398 if (cookies)
1399 free(*ap->a_cookies, M_TEMP);
1400 *ap->a_ncookies = 0;
1401 *ap->a_cookies = NULL;
1402 } else
1403 *ap->a_ncookies = ncookies;
1404 }
1405 uio->uio_offset = i;
1406 return (error);
1407 }
1408
1409 /*
1410 * readlink reads the link of `curproc' and others
1411 */
1412 int
1413 procfs_readlink(v)
1414 void *v;
1415 {
1416 struct vop_readlink_args *ap = v;
1417 char bf[16]; /* should be enough */
1418 char *bp = bf;
1419 char *path = NULL;
1420 int len;
1421 int error = 0;
1422 struct pfsnode *pfs = VTOPFS(ap->a_vp);
1423 struct proc *pown;
1424
1425 if (pfs->pfs_fileno == PROCFS_FILENO(0, PFScurproc, -1))
1426 len = snprintf(bf, sizeof(bf), "%ld", (long)curproc->p_pid);
1427 else if (pfs->pfs_fileno == PROCFS_FILENO(0, PFSself, -1))
1428 len = snprintf(bf, sizeof(bf), "%s", "curproc");
1429 else if (pfs->pfs_fileno == PROCFS_FILENO(pfs->pfs_pid, PFScwd, -1) ||
1430 pfs->pfs_fileno == PROCFS_FILENO(pfs->pfs_pid, PFSchroot, -1) ||
1431 pfs->pfs_fileno == PROCFS_FILENO(pfs->pfs_pid, PFSexe, -1)) {
1432 pown = PFIND(pfs->pfs_pid);
1433 if (pown == NULL)
1434 return (ESRCH);
1435 MALLOC(path, char *, MAXPATHLEN + 4, M_TEMP,
1436 M_WAITOK|M_CANFAIL);
1437 if (path == NULL)
1438 return (ENOMEM);
1439 bp = path + MAXPATHLEN;
1440 *--bp = '\0';
1441 (void)procfs_dir(PROCFS_TYPE(pfs->pfs_fileno), curlwp, pown,
1442 &bp, path, MAXPATHLEN);
1443 len = strlen(bp);
1444 } else {
1445 struct file *fp;
1446 struct vnode *vxp, *vp;
1447
1448 if ((error = procfs_getfp(pfs, &pown, &fp)) != 0)
1449 return error;
1450 FILE_USE(fp);
1451 switch (fp->f_type) {
1452 case DTYPE_VNODE:
1453 vxp = (struct vnode *)fp->f_data;
1454 if (vxp->v_type != VDIR) {
1455 FILE_UNUSE(fp, proc_representative_lwp(pown));
1456 return EINVAL;
1457 }
1458 if ((path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK))
1459 == NULL) {
1460 FILE_UNUSE(fp, proc_representative_lwp(pown));
1461 return ENOMEM;
1462 }
1463 bp = path + MAXPATHLEN;
1464 *--bp = '\0';
1465
1466 /*
1467 * XXX: kludge to avoid locking against ourselves
1468 * in getcwd()
1469 */
1470 if (vxp->v_tag == VT_PROCFS) {
1471 *--bp = '/';
1472 } else {
1473 vp = curproc->p_cwdi->cwdi_rdir; /* XXXSMP */
1474 if (vp == NULL)
1475 vp = rootvnode;
1476 error = getcwd_common(vxp, vp, &bp, path,
1477 MAXPATHLEN / 2, 0, curlwp);
1478 }
1479 FILE_UNUSE(fp, proc_representative_lwp(pown));
1480 if (error) {
1481 free(path, M_TEMP);
1482 return error;
1483 }
1484 len = strlen(bp);
1485 break;
1486
1487 case DTYPE_MISC:
1488 len = snprintf(bf, sizeof(bf), "%s", "[misc]");
1489 break;
1490
1491 case DTYPE_KQUEUE:
1492 len = snprintf(bf, sizeof(bf), "%s", "[kqueue]");
1493 break;
1494
1495 default:
1496 return EINVAL;
1497 }
1498 }
1499
1500 error = uiomove(bp, len, ap->a_uio);
1501 if (path)
1502 free(path, M_TEMP);
1503 return error;
1504 }
1505
1506 /*
1507 * convert decimal ascii to int
1508 */
1509 static int
1510 atoi(b, len)
1511 const char *b;
1512 size_t len;
1513 {
1514 int p = 0;
1515
1516 while (len--) {
1517 char c = *b++;
1518 if (c < '0' || c > '9')
1519 return -1;
1520 p = 10 * p + (c - '0');
1521 }
1522
1523 return p;
1524 }
1525