1 /* $NetBSD: procfs_vnops.c,v 1.176 2009/07/03 21:17:42 elad Exp $ */
4 * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Copyright (c) 1993, 1995
34 * The Regents of the University of California. All rights reserved.
36 * This code is derived from software contributed to Berkeley by
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
67 * Copyright (c) 1993 Jan-Simon Pendry
69 * This code is derived from software contributed to Berkeley by
72 * Redistribution and use in source and binary forms, with or without
73 * modification, are permitted provided that the following conditions
75 * 1. Redistributions of source code must retain the above copyright
76 * notice, this list of conditions and the following disclaimer.
77 * 2. Redistributions in binary form must reproduce the above copyright
78 * notice, this list of conditions and the following disclaimer in the
79 * documentation and/or other materials provided with the distribution.
80 * 3. All advertising materials mentioning features or use of this software
81 * must display the following acknowledgement:
82 * This product includes software developed by the University of
83 * California, Berkeley and its contributors.
84 * 4. Neither the name of the University nor the names of its contributors
85 * may be used to endorse or promote products derived from this software
86 * without specific prior written permission.
88 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
89 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
90 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
91 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
92 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
93 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
94 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
95 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
96 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
97 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
100 * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
104 * procfs vnode interface
107 #include <sys/cdefs.h>
108 __KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.176 2009/07/03 21:17:42 elad Exp $");
110 #include <sys/param.h>
111 #include <sys/systm.h>
112 #include <sys/time.h>
113 #include <sys/kernel.h>
114 #include <sys/file.h>
115 #include <sys/filedesc.h>
116 #include <sys/proc.h>
117 #include <sys/vnode.h>
118 #include <sys/namei.h>
119 #include <sys/malloc.h>
120 #include <sys/mount.h>
121 #include <sys/dirent.h>
122 #include <sys/resourcevar.h>
123 #include <sys/stat.h>
124 #include <sys/ptrace.h>
125 #include <sys/kauth.h>
127 #include <uvm/uvm_extern.h> /* for PAGE_SIZE */
129 #include <machine/reg.h>
131 #include <miscfs/genfs/genfs.h>
132 #include <miscfs/procfs/procfs.h>
139 static int procfs_validfile_linux(struct lwp
*, struct mount
*);
140 static int procfs_root_readdir_callback(struct proc
*, void *);
141 static void procfs_dir(pfstype
, struct lwp
*, struct proc
*, char **, char *,
145 * This is a list of the valid names in the
146 * process-specific sub-directories. It is
147 * used in procfs_lookup and procfs_readdir
149 static const struct proc_target
{
154 int (*pt_valid
)(struct lwp
*, struct mount
*);
156 #define N(s) sizeof(s)-1, s
157 /* name type validp */
158 { DT_DIR
, N("."), PFSproc
, NULL
},
159 { DT_DIR
, N(".."), PFSroot
, NULL
},
160 { DT_DIR
, N("fd"), PFSfd
, NULL
},
161 { DT_REG
, N("file"), PFSfile
, procfs_validfile
},
162 { DT_REG
, N("mem"), PFSmem
, NULL
},
163 { DT_REG
, N("regs"), PFSregs
, procfs_validregs
},
164 { DT_REG
, N("fpregs"), PFSfpregs
, procfs_validfpregs
},
165 { DT_REG
, N("ctl"), PFSctl
, NULL
},
166 { DT_REG
, N("stat"), PFSstat
, procfs_validfile_linux
},
167 { DT_REG
, N("status"), PFSstatus
, NULL
},
168 { DT_REG
, N("note"), PFSnote
, NULL
},
169 { DT_REG
, N("notepg"), PFSnotepg
, NULL
},
170 { DT_REG
, N("map"), PFSmap
, procfs_validmap
},
171 { DT_REG
, N("maps"), PFSmaps
, procfs_validmap
},
172 { DT_REG
, N("cmdline"), PFScmdline
, NULL
},
173 { DT_REG
, N("exe"), PFSexe
, procfs_validfile
},
174 { DT_LNK
, N("cwd"), PFScwd
, NULL
},
175 { DT_LNK
, N("root"), PFSchroot
, NULL
},
176 { DT_LNK
, N("emul"), PFSemul
, NULL
},
177 { DT_REG
, N("statm"), PFSstatm
, procfs_validfile_linux
},
178 #ifdef __HAVE_PROCFS_MACHDEP
179 PROCFS_MACHDEP_NODETYPE_DEFNS
183 static const int nproc_targets
= sizeof(proc_targets
) / sizeof(proc_targets
[0]);
186 * List of files in the root directory. Note: the validate function will
187 * be called with p == NULL for these ones.
189 static const struct proc_target proc_root_targets
[] = {
190 #define N(s) sizeof(s)-1, s
191 /* name type validp */
192 { DT_REG
, N("meminfo"), PFSmeminfo
, procfs_validfile_linux
},
193 { DT_REG
, N("cpuinfo"), PFScpuinfo
, procfs_validfile_linux
},
194 { DT_REG
, N("uptime"), PFSuptime
, procfs_validfile_linux
},
195 { DT_REG
, N("mounts"), PFSmounts
, procfs_validfile_linux
},
196 { DT_REG
, N("devices"), PFSdevices
, procfs_validfile_linux
},
197 { DT_REG
, N("stat"), PFScpustat
, procfs_validfile_linux
},
198 { DT_REG
, N("loadavg"), PFSloadavg
, procfs_validfile_linux
},
201 static const int nproc_root_targets
=
202 sizeof(proc_root_targets
) / sizeof(proc_root_targets
[0]);
204 int procfs_lookup(void *);
205 #define procfs_create genfs_eopnotsupp
206 #define procfs_mknod genfs_eopnotsupp
207 int procfs_open(void *);
208 int procfs_close(void *);
209 int procfs_access(void *);
210 int procfs_getattr(void *);
211 int procfs_setattr(void *);
212 #define procfs_read procfs_rw
213 #define procfs_write procfs_rw
214 #define procfs_fcntl genfs_fcntl
215 #define procfs_ioctl genfs_enoioctl
216 #define procfs_poll genfs_poll
217 #define procfs_revoke genfs_revoke
218 #define procfs_fsync genfs_nullop
219 #define procfs_seek genfs_nullop
220 #define procfs_remove genfs_eopnotsupp
221 int procfs_link(void *);
222 #define procfs_rename genfs_eopnotsupp
223 #define procfs_mkdir genfs_eopnotsupp
224 #define procfs_rmdir genfs_eopnotsupp
225 int procfs_symlink(void *);
226 int procfs_readdir(void *);
227 int procfs_readlink(void *);
228 #define procfs_abortop genfs_abortop
229 int procfs_inactive(void *);
230 int procfs_reclaim(void *);
231 #define procfs_lock genfs_lock
232 #define procfs_unlock genfs_unlock
233 #define procfs_bmap genfs_badop
234 #define procfs_strategy genfs_badop
235 int procfs_print(void *);
236 int procfs_pathconf(void *);
237 #define procfs_islocked genfs_islocked
238 #define procfs_advlock genfs_einval
239 #define procfs_bwrite genfs_eopnotsupp
240 #define procfs_putpages genfs_null_putpages
242 static int atoi(const char *, size_t);
245 * procfs vnode operations.
247 int (**procfs_vnodeop_p
)(void *);
248 const struct vnodeopv_entry_desc procfs_vnodeop_entries
[] = {
249 { &vop_default_desc
, vn_default_error
},
250 { &vop_lookup_desc
, procfs_lookup
}, /* lookup */
251 { &vop_create_desc
, procfs_create
}, /* create */
252 { &vop_mknod_desc
, procfs_mknod
}, /* mknod */
253 { &vop_open_desc
, procfs_open
}, /* open */
254 { &vop_close_desc
, procfs_close
}, /* close */
255 { &vop_access_desc
, procfs_access
}, /* access */
256 { &vop_getattr_desc
, procfs_getattr
}, /* getattr */
257 { &vop_setattr_desc
, procfs_setattr
}, /* setattr */
258 { &vop_read_desc
, procfs_read
}, /* read */
259 { &vop_write_desc
, procfs_write
}, /* write */
260 { &vop_fcntl_desc
, procfs_fcntl
}, /* fcntl */
261 { &vop_ioctl_desc
, procfs_ioctl
}, /* ioctl */
262 { &vop_poll_desc
, procfs_poll
}, /* poll */
263 { &vop_revoke_desc
, procfs_revoke
}, /* revoke */
264 { &vop_fsync_desc
, procfs_fsync
}, /* fsync */
265 { &vop_seek_desc
, procfs_seek
}, /* seek */
266 { &vop_remove_desc
, procfs_remove
}, /* remove */
267 { &vop_link_desc
, procfs_link
}, /* link */
268 { &vop_rename_desc
, procfs_rename
}, /* rename */
269 { &vop_mkdir_desc
, procfs_mkdir
}, /* mkdir */
270 { &vop_rmdir_desc
, procfs_rmdir
}, /* rmdir */
271 { &vop_symlink_desc
, procfs_symlink
}, /* symlink */
272 { &vop_readdir_desc
, procfs_readdir
}, /* readdir */
273 { &vop_readlink_desc
, procfs_readlink
}, /* readlink */
274 { &vop_abortop_desc
, procfs_abortop
}, /* abortop */
275 { &vop_inactive_desc
, procfs_inactive
}, /* inactive */
276 { &vop_reclaim_desc
, procfs_reclaim
}, /* reclaim */
277 { &vop_lock_desc
, procfs_lock
}, /* lock */
278 { &vop_unlock_desc
, procfs_unlock
}, /* unlock */
279 { &vop_bmap_desc
, procfs_bmap
}, /* bmap */
280 { &vop_strategy_desc
, procfs_strategy
}, /* strategy */
281 { &vop_print_desc
, procfs_print
}, /* print */
282 { &vop_islocked_desc
, procfs_islocked
}, /* islocked */
283 { &vop_pathconf_desc
, procfs_pathconf
}, /* pathconf */
284 { &vop_advlock_desc
, procfs_advlock
}, /* advlock */
285 { &vop_putpages_desc
, procfs_putpages
}, /* putpages */
288 const struct vnodeopv_desc procfs_vnodeop_opv_desc
=
289 { &procfs_vnodeop_p
, procfs_vnodeop_entries
};
291 * set things up for doing i/o on
292 * the pfsnode (vp). (vp) is locked
293 * on entry, and should be left locked
296 * for procfs we don't need to do anything
297 * in particular for i/o. all that is done
298 * is to support exclusive open on process
304 struct vop_open_args
/* {
309 struct pfsnode
*pfs
= VTOPFS(ap
->a_vp
);
314 if ((error
= procfs_proc_lock(pfs
->pfs_pid
, &p2
, ENOENT
)) != 0)
317 l1
= curlwp
; /* tracer */
319 #define M2K(m) (((m) & FREAD) && ((m) & FWRITE) ? \
320 KAUTH_REQ_PROCESS_PROCFS_RW : \
321 (m) & FWRITE ? KAUTH_REQ_PROCESS_PROCFS_WRITE : \
322 KAUTH_REQ_PROCESS_PROCFS_READ)
324 mutex_enter(p2
->p_lock
);
325 error
= kauth_authorize_process(l1
->l_cred
, KAUTH_PROCESS_PROCFS
,
326 p2
, pfs
, KAUTH_ARG(M2K(ap
->a_mode
)), NULL
);
327 mutex_exit(p2
->p_lock
);
329 procfs_proc_unlock(p2
);
335 switch (pfs
->pfs_type
) {
337 if (((pfs
->pfs_flags
& FWRITE
) && (ap
->a_mode
& O_EXCL
)) ||
338 ((pfs
->pfs_flags
& O_EXCL
) && (ap
->a_mode
& FWRITE
))) {
343 if (!proc_isunder(p2
, l1
)) {
348 if (ap
->a_mode
& FWRITE
)
349 pfs
->pfs_flags
= ap
->a_mode
& (FWRITE
|O_EXCL
);
355 if (!proc_isunder(p2
, l1
)) {
365 procfs_proc_unlock(p2
);
370 * close the pfsnode (vp) after doing i/o.
371 * (vp) is not locked on entry or exit.
373 * nothing to do for procfs other than undo
374 * any exclusive open flag (see _open above).
377 procfs_close(void *v
)
379 struct vop_close_args
/* {
384 struct pfsnode
*pfs
= VTOPFS(ap
->a_vp
);
386 switch (pfs
->pfs_type
) {
388 if ((ap
->a_fflag
& FWRITE
) && (pfs
->pfs_flags
& O_EXCL
))
389 pfs
->pfs_flags
&= ~(FWRITE
|O_EXCL
);
400 * _inactive is called when the pfsnode
401 * is vrele'd and the reference count goes
402 * to zero. (vp) will be on the vnode free
403 * list, so to get it back vget() must be
406 * (vp) is locked on entry, but must be unlocked on exit.
409 procfs_inactive(void *v
)
411 struct vop_inactive_args
/* {
415 struct vnode
*vp
= ap
->a_vp
;
416 struct pfsnode
*pfs
= VTOPFS(vp
);
418 mutex_enter(proc_lock
);
419 *ap
->a_recycle
= (p_find(pfs
->pfs_pid
, PFIND_LOCKED
) == NULL
);
420 mutex_exit(proc_lock
);
428 * _reclaim is called when getnewvnode()
429 * wants to make use of an entry on the vnode
430 * free list. at this time the filesystem needs
431 * to free any private data and remove the node
432 * from any private lists.
435 procfs_reclaim(void *v
)
437 struct vop_reclaim_args
/* {
441 return (procfs_freevp(ap
->a_vp
));
445 * Return POSIX pathconf information applicable to special devices.
448 procfs_pathconf(void *v
)
450 struct vop_pathconf_args
/* {
453 register_t *a_retval;
456 switch (ap
->a_name
) {
458 *ap
->a_retval
= LINK_MAX
;
461 *ap
->a_retval
= MAX_CANON
;
464 *ap
->a_retval
= MAX_INPUT
;
467 *ap
->a_retval
= PIPE_BUF
;
469 case _PC_CHOWN_RESTRICTED
:
473 *ap
->a_retval
= _POSIX_VDISABLE
;
485 * _print is used for debugging.
486 * just print a readable description
490 procfs_print(void *v
)
492 struct vop_print_args
/* {
495 struct pfsnode
*pfs
= VTOPFS(ap
->a_vp
);
497 printf("tag VT_PROCFS, type %d, pid %d, mode %x, flags %lx\n",
498 pfs
->pfs_type
, pfs
->pfs_pid
, pfs
->pfs_mode
, pfs
->pfs_flags
);
505 struct vop_link_args
/* {
508 struct componentname *a_cnp;
511 VOP_ABORTOP(ap
->a_dvp
, ap
->a_cnp
);
517 procfs_symlink(void *v
)
519 struct vop_symlink_args
/* {
521 struct vnode **a_vpp;
522 struct componentname *a_cnp;
527 VOP_ABORTOP(ap
->a_dvp
, ap
->a_cnp
);
533 * Works out the path to (and vnode of) the target process's current
534 * working directory or chroot. If the caller is in a chroot and
535 * can't "reach" the target's cwd or root (or some other error
536 * occurs), a "/" is returned for the path and a NULL pointer is
537 * returned for the vnode.
540 procfs_dir(pfstype t
, struct lwp
*caller
, struct proc
*target
, char **bpp
,
541 char *path
, size_t len
)
543 struct cwdinfo
*cwdi
;
544 struct vnode
*vp
, *rvp
;
547 cwdi
= caller
->l_proc
->p_cwdi
;
548 rw_enter(&cwdi
->cwdi_lock
, RW_READER
);
550 rvp
= cwdi
->cwdi_rdir
;
551 bp
= bpp
? *bpp
: NULL
;
555 vp
= target
->p_cwdi
->cwdi_cdir
;
558 vp
= target
->p_cwdi
->cwdi_rdir
;
561 vp
= target
->p_textvp
;
564 rw_exit(&cwdi
->cwdi_lock
);
569 * XXX: this horrible kludge avoids locking panics when
570 * attempting to lookup links that point to within procfs
572 if (vp
!= NULL
&& vp
->v_tag
== VT_PROCFS
) {
577 rw_exit(&cwdi
->cwdi_lock
);
583 if (vp
== NULL
|| getcwd_common(vp
, rvp
, bp
? &bp
: NULL
, path
,
584 len
/ 2, 0, caller
) != 0) {
589 snprintf(path, len, "%s/%d/file"
590 mp->mnt_stat.f_mntonname, pfs->pfs_pid);
601 rw_exit(&cwdi
->cwdi_lock
);
605 * Invent attributes for pfsnode (vp) and store
607 * Directories lengths are returned as zero since
608 * any real length would require the genuine size
609 * to be computed, and nothing cares anyway.
611 * this is relatively minimal for procfs.
614 procfs_getattr(void *v
)
616 struct vop_getattr_args
/* {
621 struct pfsnode
*pfs
= VTOPFS(ap
->a_vp
);
622 struct vattr
*vap
= ap
->a_vap
;
627 /* first check the process still exists */
628 switch (pfs
->pfs_type
) {
636 error
= procfs_proc_lock(pfs
->pfs_pid
, &procp
, ENOENT
);
642 switch (pfs
->pfs_type
) {
646 path
= malloc(MAXPATHLEN
+ 4, M_TEMP
, M_WAITOK
|M_CANFAIL
);
647 if (path
== NULL
&& procp
!= NULL
) {
648 procfs_proc_unlock(procp
);
659 mutex_enter(procp
->p_lock
);
660 error
= kauth_authorize_process(kauth_cred_get(),
661 KAUTH_PROCESS_CANSEE
, procp
,
662 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY
), NULL
, NULL
);
663 mutex_exit(procp
->p_lock
);
665 procfs_proc_unlock(procp
);
674 /* start by zeroing out the attributes */
677 /* next do all the common fields */
678 vap
->va_type
= ap
->a_vp
->v_type
;
679 vap
->va_mode
= pfs
->pfs_mode
;
680 vap
->va_fileid
= pfs
->pfs_fileno
;
682 vap
->va_blocksize
= PAGE_SIZE
;
685 * Make all times be current TOD.
687 * It would be possible to get the process start
688 * time from the p_stats structure, but there's
689 * no "file creation" time stamp anyway, and the
690 * p_stats structure is not addressable if u. gets
691 * swapped out for that process.
693 getnanotime(&vap
->va_ctime
);
694 vap
->va_atime
= vap
->va_mtime
= vap
->va_ctime
;
696 TIMEVAL_TO_TIMESPEC(&procp
->p_stats
->p_start
,
699 getnanotime(&vap
->va_birthtime
);
701 switch (pfs
->pfs_type
) {
705 #if defined(__HAVE_PROCFS_MACHDEP) && defined(PROCFS_MACHDEP_PROTECT_CASES)
706 PROCFS_MACHDEP_PROTECT_CASES
709 * If the process has exercised some setuid or setgid
710 * privilege, then rip away read/write permission so
711 * that only root can gain access.
713 if (procp
->p_flag
& PK_SUGID
)
714 vap
->va_mode
&= ~(S_IRUSR
|S_IWUSR
);
727 vap
->va_uid
= kauth_cred_geteuid(procp
->p_cred
);
728 vap
->va_gid
= kauth_cred_getegid(procp
->p_cred
);
738 vap
->va_uid
= vap
->va_gid
= 0;
746 * now do the object specific fields
748 * The size could be set from struct reg, but it's hardly
749 * worth the trouble, and it puts some (potentially) machine
750 * dependent data into this machine-independent code. If it
751 * becomes important then this function should break out into
752 * a per-file stat function in the corresponding .c file.
755 switch (pfs
->pfs_type
) {
758 * Set nlink to 1 to tell fts(3) we don't actually know.
763 vap
->va_bytes
= vap
->va_size
= DEV_BSIZE
;
768 char bf
[16]; /* should be enough */
772 vap
->va_bytes
= vap
->va_size
=
773 snprintf(bf
, sizeof(bf
), "%ld", (long)curproc
->p_pid
);
778 if (pfs
->pfs_fd
!= -1) {
781 fp
= fd_getfile2(procp
, pfs
->pfs_fd
);
787 vap
->va_uid
= kauth_cred_geteuid(fp
->f_cred
);
788 vap
->va_gid
= kauth_cred_getegid(fp
->f_cred
);
789 switch (fp
->f_type
) {
791 vap
->va_bytes
= vap
->va_size
=
792 ((struct vnode
*)fp
->f_data
)->v_size
;
795 vap
->va_bytes
= vap
->va_size
= 0;
804 vap
->va_uid
= kauth_cred_geteuid(procp
->p_cred
);
805 vap
->va_gid
= kauth_cred_getegid(procp
->p_cred
);
806 vap
->va_bytes
= vap
->va_size
= DEV_BSIZE
;
814 vap
->va_bytes
= vap
->va_size
=
815 ctob(procp
->p_vmspace
->vm_tsize
+
816 procp
->p_vmspace
->vm_dsize
+
817 procp
->p_vmspace
->vm_ssize
);
820 #if defined(PT_GETREGS) || defined(PT_SETREGS)
822 vap
->va_bytes
= vap
->va_size
= sizeof(struct reg
);
826 #if defined(PT_GETFPREGS) || defined(PT_SETFPREGS)
828 vap
->va_bytes
= vap
->va_size
= sizeof(struct fpreg
);
846 vap
->va_bytes
= vap
->va_size
= 0;
851 * Advise a larger blocksize for the map files, so that
852 * they may be read in one pass.
854 vap
->va_blocksize
= 4 * PAGE_SIZE
;
855 vap
->va_bytes
= vap
->va_size
= 0;
866 bp
= path
+ MAXPATHLEN
;
868 procfs_dir(pfs
->pfs_type
, curlwp
, procp
, &bp
, path
,
870 vap
->va_bytes
= vap
->va_size
= strlen(bp
);
875 vap
->va_bytes
= vap
->va_size
= strlen(procp
->p_emul
->e_name
);
878 #ifdef __HAVE_PROCFS_MACHDEP
879 PROCFS_MACHDEP_NODETYPE_CASES
880 error
= procfs_machdep_getattr(ap
->a_vp
, vap
, procp
);
885 panic("procfs_getattr");
889 procfs_proc_unlock(procp
);
898 procfs_setattr(void *v
)
901 * just fake out attribute setting
902 * it's not good to generate an error
903 * return, otherwise things like creat()
904 * will fail when they try to set the
905 * file length to 0. worse, this means
906 * that echo $note > /proc/$pid/note will fail.
913 procfs_check_possible(struct vnode
*vp
, mode_t mode
)
920 procfs_check_permitted(struct vattr
*va
, mode_t mode
, kauth_cred_t cred
)
923 return genfs_can_access(va
->va_type
, va
->va_mode
,
924 va
->va_uid
, va
->va_gid
, mode
, cred
);
928 * implement access checking.
930 * actually, the check for super-user is slightly
931 * broken since it will allow read access to write-only
932 * objects. this doesn't cause any particular trouble
933 * but does mean that the i/o entry points need to check
934 * that the operation really does make sense.
937 procfs_access(void *v
)
939 struct vop_access_args
/* {
947 if ((error
= VOP_GETATTR(ap
->a_vp
, &va
, ap
->a_cred
)) != 0)
950 error
= procfs_check_possible(ap
->a_vp
, ap
->a_mode
);
954 error
= procfs_check_permitted(&va
, ap
->a_mode
, ap
->a_cred
);
960 * lookup. this is incredibly complicated in the
961 * general case, however for most pseudo-filesystems
962 * very little needs to be done.
964 * Locking isn't hard here, just poorly documented.
966 * If we're looking up ".", just vref the parent & return it.
968 * If we're looking up "..", unlock the parent, and lock "..". If everything
969 * went ok, and we're on the last component and the caller requested the
970 * parent locked, try to re-lock the parent. We do this to prevent lock
973 * For anything else, get the needed node. Then unlock the parent if not
974 * the last component or not LOCKPARENT (i.e. if we wouldn't re-lock the
975 * parent in the .. case).
977 * We try to exit with the parent locked in error cases.
980 procfs_lookup(void *v
)
982 struct vop_lookup_args
/* {
983 struct vnode * a_dvp;
984 struct vnode ** a_vpp;
985 struct componentname * a_cnp;
987 struct componentname
*cnp
= ap
->a_cnp
;
988 struct vnode
**vpp
= ap
->a_vpp
;
989 struct vnode
*dvp
= ap
->a_dvp
;
990 const char *pname
= cnp
->cn_nameptr
;
991 const struct proc_target
*pt
= NULL
;
995 struct proc
*p
= NULL
;
1002 if (cnp
->cn_nameiop
== DELETE
|| cnp
->cn_nameiop
== RENAME
)
1005 if (cnp
->cn_namelen
== 1 && *pname
== '.') {
1012 switch (pfs
->pfs_type
) {
1015 * Shouldn't get here with .. in the root node.
1017 if (cnp
->cn_flags
& ISDOTDOT
)
1020 for (i
= 0; i
< nproc_root_targets
; i
++) {
1021 pt
= &proc_root_targets
[i
];
1023 * check for node match. proc is always NULL here,
1024 * so call pt_valid with constant NULL lwp.
1026 if (cnp
->cn_namelen
== pt
->pt_namlen
&&
1027 memcmp(pt
->pt_name
, pname
, cnp
->cn_namelen
) == 0 &&
1028 (pt
->pt_valid
== NULL
||
1029 (*pt
->pt_valid
)(NULL
, dvp
->v_mount
)))
1033 if (i
!= nproc_root_targets
) {
1034 error
= procfs_allocvp(dvp
->v_mount
, vpp
, 0,
1035 pt
->pt_pfstype
, -1, NULL
);
1039 if (CNEQ(cnp
, "curproc", 7)) {
1040 pid
= curproc
->p_pid
;
1043 } else if (CNEQ(cnp
, "self", 4)) {
1044 pid
= curproc
->p_pid
;
1048 pid
= (pid_t
)atoi(pname
, cnp
->cn_namelen
);
1053 if (procfs_proc_lock(pid
, &p
, ESRCH
) != 0)
1055 error
= procfs_allocvp(dvp
->v_mount
, vpp
, vnpid
, type
, -1, p
);
1056 procfs_proc_unlock(p
);
1061 * do the .. dance. We unlock the directory, and then
1062 * get the root dir. That will automatically return ..
1063 * locked. Then if the caller wanted dvp locked, we
1066 if (cnp
->cn_flags
& ISDOTDOT
) {
1068 error
= procfs_root(dvp
->v_mount
, vpp
);
1069 vn_lock(dvp
, LK_EXCLUSIVE
| LK_RETRY
);
1073 if (procfs_proc_lock(pfs
->pfs_pid
, &p
, ESRCH
) != 0)
1076 mutex_enter(p
->p_lock
);
1077 LIST_FOREACH(plwp
, &p
->p_lwps
, l_sibling
) {
1078 if (plwp
->l_stat
!= LSZOMB
)
1081 /* Process is exiting if no-LWPS or all LWPs are LSZOMB */
1083 mutex_exit(p
->p_lock
);
1084 procfs_proc_unlock(p
);
1089 mutex_exit(p
->p_lock
);
1091 for (pt
= proc_targets
, i
= 0; i
< nproc_targets
; pt
++, i
++) {
1094 found
= cnp
->cn_namelen
== pt
->pt_namlen
&&
1095 memcmp(pt
->pt_name
, pname
, cnp
->cn_namelen
) == 0 &&
1096 (pt
->pt_valid
== NULL
1097 || (*pt
->pt_valid
)(plwp
, dvp
->v_mount
));
1103 if (i
== nproc_targets
) {
1104 procfs_proc_unlock(p
);
1107 if (pt
->pt_pfstype
== PFSfile
) {
1109 /* We already checked that it exists. */
1111 procfs_proc_unlock(p
);
1112 vn_lock(fvp
, LK_EXCLUSIVE
| LK_RETRY
);
1117 error
= procfs_allocvp(dvp
->v_mount
, vpp
, pfs
->pfs_pid
,
1118 pt
->pt_pfstype
, -1, p
);
1119 procfs_proc_unlock(p
);
1126 if ((error
= procfs_proc_lock(pfs
->pfs_pid
, &p
, ENOENT
)) != 0)
1130 * do the .. dance. We unlock the directory, and then
1131 * get the proc dir. That will automatically return ..
1132 * locked. Then re-lock the directory.
1134 if (cnp
->cn_flags
& ISDOTDOT
) {
1136 error
= procfs_allocvp(dvp
->v_mount
, vpp
, pfs
->pfs_pid
,
1138 procfs_proc_unlock(p
);
1139 vn_lock(dvp
, LK_EXCLUSIVE
| LK_RETRY
);
1142 fd
= atoi(pname
, cnp
->cn_namelen
);
1144 fp
= fd_getfile2(p
, fd
);
1146 procfs_proc_unlock(p
);
1151 /* Don't show directories */
1152 if (fp
->f_type
== DTYPE_VNODE
&& fvp
->v_type
!= VDIR
) {
1155 procfs_proc_unlock(p
);
1156 vn_lock(fvp
, LK_EXCLUSIVE
| LK_RETRY
|
1157 (p
== curproc
? LK_CANRECURSE
: 0));
1163 error
= procfs_allocvp(dvp
->v_mount
, vpp
, pfs
->pfs_pid
,
1165 procfs_proc_unlock(p
);
1172 return (cnp
->cn_nameiop
== LOOKUP
? ENOENT
: EROFS
);
1176 procfs_validfile(struct lwp
*l
, struct mount
*mp
)
1178 return l
!= NULL
&& l
->l_proc
!= NULL
&& l
->l_proc
->p_textvp
!= NULL
;
1182 procfs_validfile_linux(struct lwp
*l
, struct mount
*mp
)
1186 flags
= VFSTOPROC(mp
)->pmnt_flags
;
1187 return (flags
& PROCFSMNT_LINUXCOMPAT
) &&
1188 (l
== NULL
|| l
->l_proc
== NULL
|| procfs_validfile(l
, mp
));
1191 struct procfs_root_readdir_ctx
{
1201 procfs_root_readdir_callback(struct proc
*p
, void *arg
)
1203 struct procfs_root_readdir_ctx
*ctxp
= arg
;
1209 if (uiop
->uio_resid
< UIO_MX
)
1210 return -1; /* no space */
1212 if (ctxp
->off
< ctxp
->startoff
) {
1217 if (kauth_authorize_process(kauth_cred_get(),
1218 KAUTH_PROCESS_CANSEE
, p
,
1219 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY
), NULL
, NULL
) != 0)
1222 memset(&d
, 0, UIO_MX
);
1223 d
.d_reclen
= UIO_MX
;
1224 d
.d_fileno
= PROCFS_FILENO(p
->p_pid
, PFSproc
, -1);
1225 d
.d_namlen
= snprintf(d
.d_name
,
1226 UIO_MX
- offsetof(struct dirent
, d_name
), "%ld", (long)p
->p_pid
);
1229 mutex_exit(proc_lock
);
1230 error
= uiomove(&d
, UIO_MX
, uiop
);
1231 mutex_enter(proc_lock
);
1233 ctxp
->error
= error
;
1239 *(ctxp
->cookies
)++ = ctxp
->off
+ 1;
1246 * readdir returns directory entries from pfsnode (vp).
1248 * the strategy here with procfs is to generate a single
1249 * directory entry at a time (struct dirent) and then
1250 * copy that out to userland using uiomove. a more efficent
1251 * though more complex implementation, would try to minimize
1252 * the number of calls to uiomove(). for procfs, this is
1253 * hardly worth the added code complexity.
1255 * this should just be done through read()
1258 procfs_readdir(void *v
)
1260 struct vop_readdir_args
/* {
1263 kauth_cred_t a_cred;
1268 struct uio
*uio
= ap
->a_uio
;
1270 struct pfsnode
*pfs
;
1273 off_t
*cookies
= NULL
;
1276 const struct proc_target
*pt
;
1277 struct procfs_root_readdir_ctx ctx
;
1284 if (uio
->uio_resid
< UIO_MX
)
1286 if (uio
->uio_offset
< 0)
1290 i
= uio
->uio_offset
;
1291 memset(&d
, 0, UIO_MX
);
1292 d
.d_reclen
= UIO_MX
;
1293 ncookies
= uio
->uio_resid
/ UIO_MX
;
1295 switch (pfs
->pfs_type
) {
1297 * this is for the process-specific sub-directories.
1298 * all that is needed to is copy out all the entries
1299 * from the procent[] table (top of this file).
1304 if (i
>= nproc_targets
)
1307 if (procfs_proc_lock(pfs
->pfs_pid
, &p
, ESRCH
) != 0)
1310 if (ap
->a_ncookies
) {
1311 ncookies
= min(ncookies
, (nproc_targets
- i
));
1312 cookies
= malloc(ncookies
* sizeof (off_t
),
1314 *ap
->a_cookies
= cookies
;
1317 for (pt
= &proc_targets
[i
];
1318 uio
->uio_resid
>= UIO_MX
&& i
< nproc_targets
; pt
++, i
++) {
1320 /* XXXSMP LWP can disappear */
1321 mutex_enter(p
->p_lock
);
1322 l
= LIST_FIRST(&p
->p_lwps
);
1324 mutex_exit(p
->p_lock
);
1325 if ((*pt
->pt_valid
)(l
, vp
->v_mount
) == 0)
1329 d
.d_fileno
= PROCFS_FILENO(pfs
->pfs_pid
,
1330 pt
->pt_pfstype
, -1);
1331 d
.d_namlen
= pt
->pt_namlen
;
1332 memcpy(d
.d_name
, pt
->pt_name
, pt
->pt_namlen
+ 1);
1333 d
.d_type
= pt
->pt_type
;
1335 if ((error
= uiomove(&d
, UIO_MX
, uio
)) != 0)
1341 procfs_proc_unlock(p
);
1349 if ((error
= procfs_proc_lock(pfs
->pfs_pid
, &p
, ESRCH
)) != 0)
1352 /* XXX Should this be by file as well? */
1353 if (kauth_authorize_process(kauth_cred_get(),
1354 KAUTH_PROCESS_CANSEE
, p
,
1355 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_OPENFILES
), NULL
,
1357 procfs_proc_unlock(p
);
1361 nfd
= p
->p_fd
->fd_dt
->dt_nfiles
;
1363 lim
= min((int)p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
, maxfiles
);
1365 procfs_proc_unlock(p
);
1369 if (ap
->a_ncookies
) {
1370 ncookies
= min(ncookies
, (nfd
+ 2 - i
));
1371 cookies
= malloc(ncookies
* sizeof (off_t
),
1373 *ap
->a_cookies
= cookies
;
1376 for (; i
< 2 && uio
->uio_resid
>= UIO_MX
; i
++) {
1377 pt
= &proc_targets
[i
];
1378 d
.d_namlen
= pt
->pt_namlen
;
1379 d
.d_fileno
= PROCFS_FILENO(pfs
->pfs_pid
,
1380 pt
->pt_pfstype
, -1);
1381 (void)memcpy(d
.d_name
, pt
->pt_name
, pt
->pt_namlen
+ 1);
1382 d
.d_type
= pt
->pt_type
;
1383 if ((error
= uiomove(&d
, UIO_MX
, uio
)) != 0)
1393 for (; uio
->uio_resid
>= UIO_MX
&& i
< nfd
; i
++) {
1394 /* check the descriptor exists */
1395 if ((fp
= fd_getfile2(p
, i
- 2)) == NULL
)
1399 d
.d_fileno
= PROCFS_FILENO(pfs
->pfs_pid
, PFSfd
, i
- 2);
1400 d
.d_namlen
= snprintf(d
.d_name
, sizeof(d
.d_name
),
1401 "%lld", (long long)(i
- 2));
1403 if ((error
= uiomove(&d
, UIO_MX
, uio
)) != 0)
1410 procfs_proc_unlock(p
);
1415 * this is for the root of the procfs filesystem
1416 * what is needed are special entries for "curproc"
1417 * and "self" followed by an entry for each process
1424 if (ap
->a_ncookies
) {
1426 * XXX Potentially allocating too much space here,
1427 * but I'm lazy. This loop needs some work.
1429 cookies
= malloc(ncookies
* sizeof (off_t
),
1431 *ap
->a_cookies
= cookies
;
1434 /* 0 ... 3 are static entries. */
1435 for (; i
<= 3 && uio
->uio_resid
>= UIO_MX
; i
++) {
1439 d
.d_fileno
= PROCFS_FILENO(0, PFSroot
, -1);
1441 memcpy(d
.d_name
, "..", d
.d_namlen
);
1442 d
.d_name
[i
+ 1] = '\0';
1447 d
.d_fileno
= PROCFS_FILENO(0, PFScurproc
, -1);
1448 d
.d_namlen
= sizeof("curproc") - 1;
1449 memcpy(d
.d_name
, "curproc", sizeof("curproc"));
1454 d
.d_fileno
= PROCFS_FILENO(0, PFSself
, -1);
1455 d
.d_namlen
= sizeof("self") - 1;
1456 memcpy(d
.d_name
, "self", sizeof("self"));
1461 if ((error
= uiomove(&d
, UIO_MX
, uio
)) != 0)
1467 /* 4 ... are process entries. */
1472 ctx
.cookies
= cookies
;
1474 proclist_foreach_call(&allproc
,
1475 procfs_root_readdir_callback
, &ctx
);
1476 cookies
= ctx
.cookies
;
1485 if (i
>= ctx
.off
+ nproc_root_targets
)
1487 for (pt
= &proc_root_targets
[i
- ctx
.off
];
1488 uio
->uio_resid
>= UIO_MX
&&
1489 pt
< &proc_root_targets
[nproc_root_targets
];
1492 (*pt
->pt_valid
)(NULL
, vp
->v_mount
) == 0)
1494 d
.d_fileno
= PROCFS_FILENO(0, pt
->pt_pfstype
, -1);
1495 d
.d_namlen
= pt
->pt_namlen
;
1496 memcpy(d
.d_name
, pt
->pt_name
, pt
->pt_namlen
+ 1);
1497 d
.d_type
= pt
->pt_type
;
1499 if ((error
= uiomove(&d
, UIO_MX
, uio
)) != 0)
1515 if (ap
->a_ncookies
) {
1518 free(*ap
->a_cookies
, M_TEMP
);
1519 *ap
->a_ncookies
= 0;
1520 *ap
->a_cookies
= NULL
;
1522 *ap
->a_ncookies
= ncookies
;
1524 uio
->uio_offset
= i
;
1529 * readlink reads the link of `curproc' and others
1532 procfs_readlink(void *v
)
1534 struct vop_readlink_args
*ap
= v
;
1535 char bf
[16]; /* should be enough */
1540 struct pfsnode
*pfs
= VTOPFS(ap
->a_vp
);
1543 if (pfs
->pfs_fileno
== PROCFS_FILENO(0, PFScurproc
, -1))
1544 len
= snprintf(bf
, sizeof(bf
), "%ld", (long)curproc
->p_pid
);
1545 else if (pfs
->pfs_fileno
== PROCFS_FILENO(0, PFSself
, -1))
1546 len
= snprintf(bf
, sizeof(bf
), "%s", "curproc");
1547 else if (pfs
->pfs_fileno
== PROCFS_FILENO(pfs
->pfs_pid
, PFScwd
, -1) ||
1548 pfs
->pfs_fileno
== PROCFS_FILENO(pfs
->pfs_pid
, PFSchroot
, -1) ||
1549 pfs
->pfs_fileno
== PROCFS_FILENO(pfs
->pfs_pid
, PFSexe
, -1)) {
1550 if ((error
= procfs_proc_lock(pfs
->pfs_pid
, &pown
, ESRCH
)) != 0)
1552 path
= malloc(MAXPATHLEN
+ 4, M_TEMP
, M_WAITOK
|M_CANFAIL
);
1554 procfs_proc_unlock(pown
);
1557 bp
= path
+ MAXPATHLEN
;
1559 procfs_dir(PROCFS_TYPE(pfs
->pfs_fileno
), curlwp
, pown
,
1560 &bp
, path
, MAXPATHLEN
);
1561 procfs_proc_unlock(pown
);
1565 struct vnode
*vxp
, *vp
;
1567 if ((error
= procfs_proc_lock(pfs
->pfs_pid
, &pown
, ESRCH
)) != 0)
1570 fp
= fd_getfile2(pown
, pfs
->pfs_fd
);
1572 procfs_proc_unlock(pown
);
1576 switch (fp
->f_type
) {
1578 vxp
= (struct vnode
*)fp
->f_data
;
1579 if (vxp
->v_type
!= VDIR
) {
1583 if ((path
= malloc(MAXPATHLEN
, M_TEMP
, M_WAITOK
))
1588 bp
= path
+ MAXPATHLEN
;
1592 * XXX: kludge to avoid locking against ourselves
1595 if (vxp
->v_tag
== VT_PROCFS
) {
1598 rw_enter(&curproc
->p_cwdi
->cwdi_lock
, RW_READER
);
1599 vp
= curproc
->p_cwdi
->cwdi_rdir
;
1602 error
= getcwd_common(vxp
, vp
, &bp
, path
,
1603 MAXPATHLEN
/ 2, 0, curlwp
);
1604 rw_exit(&curproc
->p_cwdi
->cwdi_lock
);
1612 len
= snprintf(bf
, sizeof(bf
), "%s", "[misc]");
1616 len
= snprintf(bf
, sizeof(bf
), "%s", "[kqueue]");
1624 procfs_proc_unlock(pown
);
1628 error
= uiomove(bp
, len
, ap
->a_uio
);
1635 * convert decimal ascii to int
1638 atoi(const char *b
, size_t len
)
1644 if (c
< '0' || c
> '9')
1646 p
= 10 * p
+ (c
- '0');