aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/fs/devfs/devfs_vnops.c1
-rw-r--r--sys/kern/kern_descrip.c829
-rw-r--r--sys/kern/kern_event.c11
-rw-r--r--sys/kern/sys_pipe.c18
-rw-r--r--sys/kern/sys_procdesc.c14
-rw-r--r--sys/kern/sys_socket.c65
-rw-r--r--sys/kern/tty_pts.c14
-rw-r--r--sys/kern/uipc_mqueue.c10
-rw-r--r--sys/kern/uipc_sem.c39
-rw-r--r--sys/kern/uipc_shm.c29
-rw-r--r--sys/kern/vfs_vnops.c60
-rw-r--r--sys/ofed/include/linux/linux_compat.c9
-rw-r--r--sys/opencrypto/cryptodev.c11
-rw-r--r--sys/sys/file.h14
-rw-r--r--sys/sys/ksem.h5
-rw-r--r--sys/sys/mman.h1
16 files changed, 498 insertions, 632 deletions
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index 1e3f5e844864..d0aabefe80a9 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -1700,6 +1700,7 @@ static struct fileops devfs_ops_f = {
.fo_chown = vn_chown,
.fo_sendfile = vn_sendfile,
.fo_seek = vn_seek,
+ .fo_fill_kinfo = vn_fill_kinfo,
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
};
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index b6fcc7636705..4564eb87fea9 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -47,27 +47,21 @@ __FBSDID("$FreeBSD$");
#include <sys/capsicum.h>
#include <sys/conf.h>
-#include <sys/domain.h>
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/filio.h>
#include <sys/jail.h>
#include <sys/kernel.h>
-#include <sys/ksem.h>
#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/malloc.h>
-#include <sys/mman.h>
#include <sys/mount.h>
-#include <sys/mqueue.h>
#include <sys/mutex.h>
#include <sys/namei.h>
#include <sys/selinfo.h>
-#include <sys/pipe.h>
#include <sys/priv.h>
#include <sys/proc.h>
-#include <sys/procdesc.h>
#include <sys/protosw.h>
#include <sys/racct.h>
#include <sys/resourcevar.h>
@@ -79,10 +73,7 @@ __FBSDID("$FreeBSD$");
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/sysproto.h>
-#include <sys/tty.h>
#include <sys/unistd.h>
-#include <sys/un.h>
-#include <sys/unpcb.h>
#include <sys/user.h>
#include <sys/vnode.h>
#ifdef KTRACE
@@ -91,9 +82,6 @@ __FBSDID("$FreeBSD$");
#include <net/vnet.h>
-#include <netinet/in.h>
-#include <netinet/in_pcb.h>
-
#include <security/audit/audit.h>
#include <vm/uma.h>
@@ -111,8 +99,6 @@ MALLOC_DECLARE(M_FADVISE);
static uma_zone_t file_zone;
-void (*ksem_info)(struct ksem *ks, char *path, size_t size, uint32_t *value);
-
static int closefp(struct filedesc *fdp, int fd, struct file *fp,
struct thread *td, int holdleaders);
static int fd_first_free(struct filedesc *fdp, int low, int size);
@@ -121,14 +107,6 @@ static void fdgrowtable(struct filedesc *fdp, int nfd);
static void fdgrowtable_exp(struct filedesc *fdp, int nfd);
static void fdunused(struct filedesc *fdp, int fd);
static void fdused(struct filedesc *fdp, int fd);
-static int fill_pipe_info(struct pipe *pi, struct kinfo_file *kif);
-static int fill_procdesc_info(struct procdesc *pdp,
- struct kinfo_file *kif);
-static int fill_pts_info(struct tty *tp, struct kinfo_file *kif);
-static int fill_sem_info(struct file *fp, struct kinfo_file *kif);
-static int fill_shm_info(struct file *fp, struct kinfo_file *kif);
-static int fill_socket_info(struct socket *so, struct kinfo_file *kif);
-static int fill_vnode_info(struct vnode *vp, struct kinfo_file *kif);
static int getmaxfd(struct proc *p);
/*
@@ -2945,280 +2923,14 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS)
SYSCTL_PROC(_kern, KERN_FILE, file, CTLTYPE_OPAQUE|CTLFLAG_RD|CTLFLAG_MPSAFE,
0, 0, sysctl_kern_file, "S,xfile", "Entire file table");
-#ifdef KINFO_OFILE_SIZE
-CTASSERT(sizeof(struct kinfo_ofile) == KINFO_OFILE_SIZE);
-#endif
-
-#ifdef COMPAT_FREEBSD7
-static int
-export_vnode_for_osysctl(struct vnode *vp, int type,
- struct kinfo_ofile *kif, struct filedesc *fdp, struct sysctl_req *req)
-{
- int error;
- char *fullpath, *freepath;
-
- bzero(kif, sizeof(*kif));
- kif->kf_structsize = sizeof(*kif);
-
- vref(vp);
- kif->kf_fd = type;
- kif->kf_type = KF_TYPE_VNODE;
- /* This function only handles directories. */
- if (vp->v_type != VDIR) {
- vrele(vp);
- return (ENOTDIR);
- }
- kif->kf_vnode_type = KF_VTYPE_VDIR;
-
- /*
- * This is not a true file descriptor, so we set a bogus refcount
- * and offset to indicate these fields should be ignored.
- */
- kif->kf_ref_count = -1;
- kif->kf_offset = -1;
-
- freepath = NULL;
- fullpath = "-";
- FILEDESC_SUNLOCK(fdp);
- vn_fullpath(curthread, vp, &fullpath, &freepath);
- vrele(vp);
- strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path));
- if (freepath != NULL)
- free(freepath, M_TEMP);
- error = SYSCTL_OUT(req, kif, sizeof(*kif));
- FILEDESC_SLOCK(fdp);
- return (error);
-}
-
-/*
- * Get per-process file descriptors for use by procstat(1), et al.
- */
-static int
-sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
-{
- char *fullpath, *freepath;
- struct kinfo_ofile *kif;
- struct filedesc *fdp;
- int error, i, *name;
- struct shmfd *shmfd;
- struct socket *so;
- struct vnode *vp;
- struct ksem *ks;
- struct file *fp;
- struct proc *p;
- struct tty *tp;
-
- name = (int *)arg1;
- error = pget((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p);
- if (error != 0)
- return (error);
- fdp = fdhold(p);
- PROC_UNLOCK(p);
- if (fdp == NULL)
- return (ENOENT);
- kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK);
- FILEDESC_SLOCK(fdp);
- if (fdp->fd_cdir != NULL)
- export_vnode_for_osysctl(fdp->fd_cdir, KF_FD_TYPE_CWD, kif,
- fdp, req);
- if (fdp->fd_rdir != NULL)
- export_vnode_for_osysctl(fdp->fd_rdir, KF_FD_TYPE_ROOT, kif,
- fdp, req);
- if (fdp->fd_jdir != NULL)
- export_vnode_for_osysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL, kif,
- fdp, req);
- for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) {
- if ((fp = fdp->fd_ofiles[i].fde_file) == NULL)
- continue;
- bzero(kif, sizeof(*kif));
- kif->kf_structsize = sizeof(*kif);
- ks = NULL;
- vp = NULL;
- so = NULL;
- tp = NULL;
- shmfd = NULL;
- kif->kf_fd = i;
-
- switch (fp->f_type) {
- case DTYPE_VNODE:
- kif->kf_type = KF_TYPE_VNODE;
- vp = fp->f_vnode;
- break;
-
- case DTYPE_SOCKET:
- kif->kf_type = KF_TYPE_SOCKET;
- so = fp->f_data;
- break;
-
- case DTYPE_PIPE:
- kif->kf_type = KF_TYPE_PIPE;
- break;
-
- case DTYPE_FIFO:
- kif->kf_type = KF_TYPE_FIFO;
- vp = fp->f_vnode;
- break;
-
- case DTYPE_KQUEUE:
- kif->kf_type = KF_TYPE_KQUEUE;
- break;
-
- case DTYPE_CRYPTO:
- kif->kf_type = KF_TYPE_CRYPTO;
- break;
-
- case DTYPE_MQUEUE:
- kif->kf_type = KF_TYPE_MQUEUE;
- break;
-
- case DTYPE_SHM:
- kif->kf_type = KF_TYPE_SHM;
- shmfd = fp->f_data;
- break;
-
- case DTYPE_SEM:
- kif->kf_type = KF_TYPE_SEM;
- ks = fp->f_data;
- break;
-
- case DTYPE_PTS:
- kif->kf_type = KF_TYPE_PTS;
- tp = fp->f_data;
- break;
-
- case DTYPE_PROCDESC:
- kif->kf_type = KF_TYPE_PROCDESC;
- break;
-
- default:
- kif->kf_type = KF_TYPE_UNKNOWN;
- break;
- }
- kif->kf_ref_count = fp->f_count;
- if (fp->f_flag & FREAD)
- kif->kf_flags |= KF_FLAG_READ;
- if (fp->f_flag & FWRITE)
- kif->kf_flags |= KF_FLAG_WRITE;
- if (fp->f_flag & FAPPEND)
- kif->kf_flags |= KF_FLAG_APPEND;
- if (fp->f_flag & FASYNC)
- kif->kf_flags |= KF_FLAG_ASYNC;
- if (fp->f_flag & FFSYNC)
- kif->kf_flags |= KF_FLAG_FSYNC;
- if (fp->f_flag & FNONBLOCK)
- kif->kf_flags |= KF_FLAG_NONBLOCK;
- if (fp->f_flag & O_DIRECT)
- kif->kf_flags |= KF_FLAG_DIRECT;
- if (fp->f_flag & FHASLOCK)
- kif->kf_flags |= KF_FLAG_HASLOCK;
- kif->kf_offset = foffset_get(fp);
- if (vp != NULL) {
- vref(vp);
- switch (vp->v_type) {
- case VNON:
- kif->kf_vnode_type = KF_VTYPE_VNON;
- break;
- case VREG:
- kif->kf_vnode_type = KF_VTYPE_VREG;
- break;
- case VDIR:
- kif->kf_vnode_type = KF_VTYPE_VDIR;
- break;
- case VBLK:
- kif->kf_vnode_type = KF_VTYPE_VBLK;
- break;
- case VCHR:
- kif->kf_vnode_type = KF_VTYPE_VCHR;
- break;
- case VLNK:
- kif->kf_vnode_type = KF_VTYPE_VLNK;
- break;
- case VSOCK:
- kif->kf_vnode_type = KF_VTYPE_VSOCK;
- break;
- case VFIFO:
- kif->kf_vnode_type = KF_VTYPE_VFIFO;
- break;
- case VBAD:
- kif->kf_vnode_type = KF_VTYPE_VBAD;
- break;
- default:
- kif->kf_vnode_type = KF_VTYPE_UNKNOWN;
- break;
- }
- /*
- * It is OK to drop the filedesc lock here as we will
- * re-validate and re-evaluate its properties when
- * the loop continues.
- */
- freepath = NULL;
- fullpath = "-";
- FILEDESC_SUNLOCK(fdp);
- vn_fullpath(curthread, vp, &fullpath, &freepath);
- vrele(vp);
- strlcpy(kif->kf_path, fullpath,
- sizeof(kif->kf_path));
- if (freepath != NULL)
- free(freepath, M_TEMP);
- FILEDESC_SLOCK(fdp);
- }
- if (so != NULL) {
- struct sockaddr *sa;
-
- if (so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa)
- == 0 && sa->sa_len <= sizeof(kif->kf_sa_local)) {
- bcopy(sa, &kif->kf_sa_local, sa->sa_len);
- free(sa, M_SONAME);
- }
- if (so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa)
- == 0 && sa->sa_len <= sizeof(kif->kf_sa_peer)) {
- bcopy(sa, &kif->kf_sa_peer, sa->sa_len);
- free(sa, M_SONAME);
- }
- kif->kf_sock_domain =
- so->so_proto->pr_domain->dom_family;
- kif->kf_sock_type = so->so_type;
- kif->kf_sock_protocol = so->so_proto->pr_protocol;
- }
- if (tp != NULL) {
- strlcpy(kif->kf_path, tty_devname(tp),
- sizeof(kif->kf_path));
- }
- if (shmfd != NULL)
- shm_path(shmfd, kif->kf_path, sizeof(kif->kf_path));
- if (ks != NULL && ksem_info != NULL)
- ksem_info(ks, kif->kf_path, sizeof(kif->kf_path), NULL);
- error = SYSCTL_OUT(req, kif, sizeof(*kif));
- if (error)
- break;
- }
- FILEDESC_SUNLOCK(fdp);
- fddrop(fdp);
- free(kif, M_TEMP);
- return (0);
-}
-
-static SYSCTL_NODE(_kern_proc, KERN_PROC_OFILEDESC, ofiledesc,
- CTLFLAG_RD||CTLFLAG_MPSAFE, sysctl_kern_proc_ofiledesc,
- "Process ofiledesc entries");
-#endif /* COMPAT_FREEBSD7 */
-
#ifdef KINFO_FILE_SIZE
CTASSERT(sizeof(struct kinfo_file) == KINFO_FILE_SIZE);
#endif
-struct export_fd_buf {
- struct filedesc *fdp;
- struct sbuf *sb;
- ssize_t remainder;
- struct kinfo_file kif;
-};
-
static int
-export_fd_to_sb(void *data, int type, int fd, int fflags, int refcnt,
- int64_t offset, cap_rights_t *rightsp, struct export_fd_buf *efbuf)
+xlate_fflags(int fflags)
{
- struct {
+ static const struct {
int fflag;
int kf_fflag;
} fflags_table[] = {
@@ -3238,83 +2950,126 @@ export_fd_to_sb(void *data, int type, int fd, int fflags, int refcnt,
{ O_SHLOCK, KF_FLAG_SHLOCK },
{ O_TRUNC, KF_FLAG_TRUNC }
};
-#define NFFLAGS (sizeof(fflags_table) / sizeof(*fflags_table))
- struct kinfo_file *kif;
- struct vnode *vp;
- int error, locked;
unsigned int i;
+ int kflags;
+
+ kflags = 0;
+ for (i = 0; i < nitems(fflags_table); i++)
+ if (fflags & fflags_table[i].fflag)
+ kflags |= fflags_table[i].kf_fflag;
+ return (kflags);
+}
+
+/* Trim unused data from kf_path by truncating the structure size. */
+static void
+pack_kinfo(struct kinfo_file *kif)
+{
+
+ kif->kf_structsize = offsetof(struct kinfo_file, kf_path) +
+ strlen(kif->kf_path) + 1;
+ kif->kf_structsize = roundup(kif->kf_structsize, sizeof(uint64_t));
+}
+
+static void
+export_file_to_kinfo(struct file *fp, int fd, cap_rights_t *rightsp,
+ struct kinfo_file *kif, struct filedesc *fdp)
+{
+ int error;
- if (efbuf->remainder == 0)
- return (0);
- kif = &efbuf->kif;
bzero(kif, sizeof(*kif));
- locked = efbuf->fdp != NULL;
- switch (type) {
- case KF_TYPE_FIFO:
- case KF_TYPE_VNODE:
- if (locked) {
- FILEDESC_SUNLOCK(efbuf->fdp);
- locked = 0;
- }
- vp = (struct vnode *)data;
- error = fill_vnode_info(vp, kif);
- vrele(vp);
- break;
- case KF_TYPE_SOCKET:
- error = fill_socket_info((struct socket *)data, kif);
- break;
- case KF_TYPE_PIPE:
- error = fill_pipe_info((struct pipe *)data, kif);
- break;
- case KF_TYPE_PTS:
- error = fill_pts_info((struct tty *)data, kif);
- break;
- case KF_TYPE_PROCDESC:
- error = fill_procdesc_info((struct procdesc *)data, kif);
- break;
- case KF_TYPE_SEM:
- error = fill_sem_info((struct file *)data, kif);
- break;
- case KF_TYPE_SHM:
- error = fill_shm_info((struct file *)data, kif);
- break;
- default:
- error = 0;
- }
- if (error == 0)
- kif->kf_status |= KF_ATTR_VALID;
- /*
- * Translate file access flags.
- */
- for (i = 0; i < NFFLAGS; i++)
- if (fflags & fflags_table[i].fflag)
- kif->kf_flags |= fflags_table[i].kf_fflag;
+ /* Set a default type to allow for empty fill_kinfo() methods. */
+ kif->kf_type = KF_TYPE_UNKNOWN;
+ kif->kf_flags = xlate_fflags(fp->f_flag);
if (rightsp != NULL)
kif->kf_cap_rights = *rightsp;
else
cap_rights_init(&kif->kf_cap_rights);
kif->kf_fd = fd;
- kif->kf_type = type;
- kif->kf_ref_count = refcnt;
- kif->kf_offset = offset;
- /* Pack record size down */
- kif->kf_structsize = offsetof(struct kinfo_file, kf_path) +
- strlen(kif->kf_path) + 1;
- kif->kf_structsize = roundup(kif->kf_structsize, sizeof(uint64_t));
+ kif->kf_ref_count = fp->f_count;
+ kif->kf_offset = foffset_get(fp);
+
+ /*
+ * This may drop the filedesc lock, so the 'fp' cannot be
+ * accessed after this call.
+ */
+ error = fo_fill_kinfo(fp, kif, fdp);
+ if (error == 0)
+ kif->kf_status |= KF_ATTR_VALID;
+ pack_kinfo(kif);
+}
+
+static void
+export_vnode_to_kinfo(struct vnode *vp, int fd, int fflags,
+ struct kinfo_file *kif)
+{
+ int error;
+
+ bzero(kif, sizeof(*kif));
+
+ kif->kf_type = KF_TYPE_VNODE;
+ error = vn_fill_kinfo_vnode(vp, kif);
+ if (error == 0)
+ kif->kf_status |= KF_ATTR_VALID;
+ kif->kf_flags = xlate_fflags(fflags);
+ kif->kf_fd = fd;
+ kif->kf_ref_count = -1;
+ kif->kf_offset = -1;
+ pack_kinfo(kif);
+ vrele(vp);
+}
+
+struct export_fd_buf {
+ struct filedesc *fdp;
+ struct sbuf *sb;
+ ssize_t remainder;
+ struct kinfo_file kif;
+};
+
+static int
+export_kinfo_to_sb(struct export_fd_buf *efbuf)
+{
+ struct kinfo_file *kif;
+
+ kif = &efbuf->kif;
if (efbuf->remainder != -1) {
if (efbuf->remainder < kif->kf_structsize) {
/* Terminate export. */
efbuf->remainder = 0;
- if (efbuf->fdp != NULL && !locked)
- FILEDESC_SLOCK(efbuf->fdp);
return (0);
}
efbuf->remainder -= kif->kf_structsize;
}
- if (locked)
+ return (sbuf_bcat(efbuf->sb, kif, kif->kf_structsize));
+}
+
+static int
+export_file_to_sb(struct file *fp, int fd, cap_rights_t *rightsp,
+ struct export_fd_buf *efbuf)
+{
+ int error;
+
+ if (efbuf->remainder == 0)
+ return (0);
+ export_file_to_kinfo(fp, fd, rightsp, &efbuf->kif, efbuf->fdp);
+ FILEDESC_SUNLOCK(efbuf->fdp);
+ error = export_kinfo_to_sb(efbuf);
+ FILEDESC_SLOCK(efbuf->fdp);
+ return (error);
+}
+
+static int
+export_vnode_to_sb(struct vnode *vp, int fd, int fflags,
+ struct export_fd_buf *efbuf)
+{
+ int error;
+
+ if (efbuf->remainder == 0)
+ return (0);
+ if (efbuf->fdp != NULL)
FILEDESC_SUNLOCK(efbuf->fdp);
- error = sbuf_bcat(efbuf->sb, kif, kif->kf_structsize);
+ export_vnode_to_kinfo(vp, fd, fflags, &efbuf->kif);
+ error = export_kinfo_to_sb(efbuf);
if (efbuf->fdp != NULL)
FILEDESC_SLOCK(efbuf->fdp);
return (error);
@@ -3328,16 +3083,15 @@ export_fd_to_sb(void *data, int type, int fd, int fflags, int refcnt,
int
kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
{
+ struct thread *td;
struct file *fp;
struct filedesc *fdp;
struct export_fd_buf *efbuf;
struct vnode *cttyvp, *textvp, *tracevp;
- int64_t offset;
- void *data;
int error, i;
- int type, refcnt, fflags;
cap_rights_t rights;
+ td = curthread;
PROC_LOCK_ASSERT(p, MA_OWNED);
/* ktrace vnode */
@@ -3362,14 +3116,13 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
efbuf->sb = sb;
efbuf->remainder = maxlen;
if (tracevp != NULL)
- export_fd_to_sb(tracevp, KF_TYPE_VNODE, KF_FD_TYPE_TRACE,
- FREAD | FWRITE, -1, -1, NULL, efbuf);
+ export_vnode_to_sb(tracevp, KF_FD_TYPE_TRACE, FREAD | FWRITE,
+ efbuf);
if (textvp != NULL)
- export_fd_to_sb(textvp, KF_TYPE_VNODE, KF_FD_TYPE_TEXT,
- FREAD, -1, -1, NULL, efbuf);
+ export_vnode_to_sb(textvp, KF_FD_TYPE_TEXT, FREAD, efbuf);
if (cttyvp != NULL)
- export_fd_to_sb(cttyvp, KF_TYPE_VNODE, KF_FD_TYPE_CTTY,
- FREAD | FWRITE, -1, -1, NULL, efbuf);
+ export_vnode_to_sb(cttyvp, KF_FD_TYPE_CTTY, FREAD | FWRITE,
+ efbuf);
error = 0;
if (fdp == NULL)
goto fail;
@@ -3378,105 +3131,34 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
/* working directory */
if (fdp->fd_cdir != NULL) {
vref(fdp->fd_cdir);
- data = fdp->fd_cdir;
- export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_CWD,
- FREAD, -1, -1, NULL, efbuf);
+ export_vnode_to_sb(fdp->fd_cdir, KF_FD_TYPE_CWD, FREAD, efbuf);
}
/* root directory */
if (fdp->fd_rdir != NULL) {
vref(fdp->fd_rdir);
- data = fdp->fd_rdir;
- export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_ROOT,
- FREAD, -1, -1, NULL, efbuf);
+ export_vnode_to_sb(fdp->fd_rdir, KF_FD_TYPE_ROOT, FREAD, efbuf);
}
/* jail directory */
if (fdp->fd_jdir != NULL) {
vref(fdp->fd_jdir);
- data = fdp->fd_jdir;
- export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_JAIL,
- FREAD, -1, -1, NULL, efbuf);
+ export_vnode_to_sb(fdp->fd_jdir, KF_FD_TYPE_JAIL, FREAD, efbuf);
}
for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) {
if ((fp = fdp->fd_ofiles[i].fde_file) == NULL)
continue;
- data = NULL;
#ifdef CAPABILITIES
rights = *cap_rights(fdp, i);
#else /* !CAPABILITIES */
cap_rights_init(&rights);
#endif
- switch (fp->f_type) {
- case DTYPE_VNODE:
- type = KF_TYPE_VNODE;
- vref(fp->f_vnode);
- data = fp->f_vnode;
- break;
-
- case DTYPE_SOCKET:
- type = KF_TYPE_SOCKET;
- data = fp->f_data;
- break;
-
- case DTYPE_PIPE:
- type = KF_TYPE_PIPE;
- data = fp->f_data;
- break;
-
- case DTYPE_FIFO:
- type = KF_TYPE_FIFO;
- vref(fp->f_vnode);
- data = fp->f_vnode;
- break;
-
- case DTYPE_KQUEUE:
- type = KF_TYPE_KQUEUE;
- break;
-
- case DTYPE_CRYPTO:
- type = KF_TYPE_CRYPTO;
- break;
-
- case DTYPE_MQUEUE:
- type = KF_TYPE_MQUEUE;
- break;
-
- case DTYPE_SHM:
- type = KF_TYPE_SHM;
- data = fp;
- break;
-
- case DTYPE_SEM:
- type = KF_TYPE_SEM;
- data = fp;
- break;
-
- case DTYPE_PTS:
- type = KF_TYPE_PTS;
- data = fp->f_data;
- break;
-
- case DTYPE_PROCDESC:
- type = KF_TYPE_PROCDESC;
- data = fp->f_data;
- break;
-
- default:
- type = KF_TYPE_UNKNOWN;
- break;
- }
- refcnt = fp->f_count;
- fflags = fp->f_flag;
- offset = foffset_get(fp);
-
/*
- * Create sysctl entry.
- * It is OK to drop the filedesc lock here as we will
- * re-validate and re-evaluate its properties when
- * the loop continues.
+ * Create sysctl entry. It is OK to drop the filedesc
+ * lock inside of export_file_to_sb() as we will
+ * re-validate and re-evaluate its properties when the
+ * loop continues.
*/
- error = export_fd_to_sb(data, type, i, fflags, refcnt,
- offset, &rights, efbuf);
- if (error != 0)
+ error = export_file_to_sb(fp, i, &rights, efbuf);
+ if (error != 0 || efbuf->remainder == 0)
break;
}
FILEDESC_SUNLOCK(fdp);
@@ -3514,6 +3196,105 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
return (error != 0 ? error : error2);
}
+#ifdef KINFO_OFILE_SIZE
+CTASSERT(sizeof(struct kinfo_ofile) == KINFO_OFILE_SIZE);
+#endif
+
+#ifdef COMPAT_FREEBSD7
+static void
+kinfo_to_okinfo(struct kinfo_file *kif, struct kinfo_ofile *okif)
+{
+
+ okif->kf_structsize = sizeof(*okif);
+ okif->kf_type = kif->kf_type;
+ okif->kf_fd = kif->kf_fd;
+ okif->kf_ref_count = kif->kf_ref_count;
+ okif->kf_flags = kif->kf_flags & (KF_FLAG_READ | KF_FLAG_WRITE |
+ KF_FLAG_APPEND | KF_FLAG_ASYNC | KF_FLAG_FSYNC | KF_FLAG_NONBLOCK |
+ KF_FLAG_DIRECT | KF_FLAG_HASLOCK);
+ okif->kf_offset = kif->kf_offset;
+ okif->kf_vnode_type = kif->kf_vnode_type;
+ okif->kf_sock_domain = kif->kf_sock_domain;
+ okif->kf_sock_type = kif->kf_sock_type;
+ okif->kf_sock_protocol = kif->kf_sock_protocol;
+ strlcpy(okif->kf_path, kif->kf_path, sizeof(okif->kf_path));
+ okif->kf_sa_local = kif->kf_sa_local;
+ okif->kf_sa_peer = kif->kf_sa_peer;
+}
+
+static int
+export_vnode_for_osysctl(struct vnode *vp, int type, struct kinfo_file *kif,
+ struct kinfo_ofile *okif, struct filedesc *fdp, struct sysctl_req *req)
+{
+ int error;
+
+ vref(vp);
+ FILEDESC_SUNLOCK(fdp);
+ export_vnode_to_kinfo(vp, type, 0, kif);
+ kinfo_to_okinfo(kif, okif);
+ error = SYSCTL_OUT(req, okif, sizeof(*okif));
+ FILEDESC_SLOCK(fdp);
+ return (error);
+}
+
+/*
+ * Get per-process file descriptors for use by procstat(1), et al.
+ */
+static int
+sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
+{
+ struct kinfo_ofile *okif;
+ struct kinfo_file *kif;
+ struct filedesc *fdp;
+ struct thread *td;
+ int error, i, *name;
+ struct file *fp;
+ struct proc *p;
+
+ td = curthread;
+ name = (int *)arg1;
+ error = pget((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p);
+ if (error != 0)
+ return (error);
+ fdp = fdhold(p);
+ PROC_UNLOCK(p);
+ if (fdp == NULL)
+ return (ENOENT);
+ kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK);
+ okif = malloc(sizeof(*okif), M_TEMP, M_WAITOK);
+ FILEDESC_SLOCK(fdp);
+ if (fdp->fd_cdir != NULL)
+ export_vnode_for_osysctl(fdp->fd_cdir, KF_FD_TYPE_CWD, kif,
+ okif, fdp, req);
+ if (fdp->fd_rdir != NULL)
+ export_vnode_for_osysctl(fdp->fd_rdir, KF_FD_TYPE_ROOT, kif,
+ okif, fdp, req);
+ if (fdp->fd_jdir != NULL)
+ export_vnode_for_osysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL, kif,
+ okif, fdp, req);
+ for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) {
+ if ((fp = fdp->fd_ofiles[i].fde_file) == NULL)
+ continue;
+ export_file_to_kinfo(fp, i, NULL, kif, fdp);
+ FILEDESC_SUNLOCK(fdp);
+ kinfo_to_okinfo(kif, okif);
+ error = SYSCTL_OUT(req, okif, sizeof(*okif));
+ FILEDESC_SLOCK(fdp);
+ if (error)
+ break;
+ }
+ FILEDESC_SUNLOCK(fdp);
+ fddrop(fdp);
+ free(kif, M_TEMP);
+ free(okif, M_TEMP);
+ return (0);
+}
+
+static SYSCTL_NODE(_kern_proc, KERN_PROC_OFILEDESC, ofiledesc,
+ CTLFLAG_RD||CTLFLAG_MPSAFE, sysctl_kern_proc_ofiledesc,
+ "Process ofiledesc entries");
+#endif /* COMPAT_FREEBSD7 */
+
int
vntype_to_kinfo(int vtype)
{
@@ -3543,170 +3324,6 @@ vntype_to_kinfo(int vtype)
return (KF_VTYPE_UNKNOWN);
}
-static int
-fill_vnode_info(struct vnode *vp, struct kinfo_file *kif)
-{
- struct vattr va;
- char *fullpath, *freepath;
- int error;
-
- if (vp == NULL)
- return (1);
- kif->kf_vnode_type = vntype_to_kinfo(vp->v_type);
- freepath = NULL;
- fullpath = "-";
- error = vn_fullpath(curthread, vp, &fullpath, &freepath);
- if (error == 0) {
- strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path));
- }
- if (freepath != NULL)
- free(freepath, M_TEMP);
-
- /*
- * Retrieve vnode attributes.
- */
- va.va_fsid = VNOVAL;
- va.va_rdev = NODEV;
- vn_lock(vp, LK_SHARED | LK_RETRY);
- error = VOP_GETATTR(vp, &va, curthread->td_ucred);
- VOP_UNLOCK(vp, 0);
- if (error != 0)
- return (error);
- if (va.va_fsid != VNOVAL)
- kif->kf_un.kf_file.kf_file_fsid = va.va_fsid;
- else
- kif->kf_un.kf_file.kf_file_fsid =
- vp->v_mount->mnt_stat.f_fsid.val[0];
- kif->kf_un.kf_file.kf_file_fileid = va.va_fileid;
- kif->kf_un.kf_file.kf_file_mode = MAKEIMODE(va.va_type, va.va_mode);
- kif->kf_un.kf_file.kf_file_size = va.va_size;
- kif->kf_un.kf_file.kf_file_rdev = va.va_rdev;
- return (0);
-}
-
-static int
-fill_socket_info(struct socket *so, struct kinfo_file *kif)
-{
- struct sockaddr *sa;
- struct inpcb *inpcb;
- struct unpcb *unpcb;
- int error;
-
- if (so == NULL)
- return (1);
- kif->kf_sock_domain = so->so_proto->pr_domain->dom_family;
- kif->kf_sock_type = so->so_type;
- kif->kf_sock_protocol = so->so_proto->pr_protocol;
- kif->kf_un.kf_sock.kf_sock_pcb = (uintptr_t)so->so_pcb;
- switch(kif->kf_sock_domain) {
- case AF_INET:
- case AF_INET6:
- if (kif->kf_sock_protocol == IPPROTO_TCP) {
- if (so->so_pcb != NULL) {
- inpcb = (struct inpcb *)(so->so_pcb);
- kif->kf_un.kf_sock.kf_sock_inpcb =
- (uintptr_t)inpcb->inp_ppcb;
- }
- }
- break;
- case AF_UNIX:
- if (so->so_pcb != NULL) {
- unpcb = (struct unpcb *)(so->so_pcb);
- if (unpcb->unp_conn) {
- kif->kf_un.kf_sock.kf_sock_unpconn =
- (uintptr_t)unpcb->unp_conn;
- kif->kf_un.kf_sock.kf_sock_rcv_sb_state =
- so->so_rcv.sb_state;
- kif->kf_un.kf_sock.kf_sock_snd_sb_state =
- so->so_snd.sb_state;
- }
- }
- break;
- }
- error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
- if (error == 0 && sa->sa_len <= sizeof(kif->kf_sa_local)) {
- bcopy(sa, &kif->kf_sa_local, sa->sa_len);
- free(sa, M_SONAME);
- }
- error = so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa);
- if (error == 0 && sa->sa_len <= sizeof(kif->kf_sa_peer)) {
- bcopy(sa, &kif->kf_sa_peer, sa->sa_len);
- free(sa, M_SONAME);
- }
- strncpy(kif->kf_path, so->so_proto->pr_domain->dom_name,
- sizeof(kif->kf_path));
- return (0);
-}
-
-static int
-fill_pts_info(struct tty *tp, struct kinfo_file *kif)
-{
-
- if (tp == NULL)
- return (1);
- kif->kf_un.kf_pts.kf_pts_dev = tty_udev(tp);
- strlcpy(kif->kf_path, tty_devname(tp), sizeof(kif->kf_path));
- return (0);
-}
-
-static int
-fill_pipe_info(struct pipe *pi, struct kinfo_file *kif)
-{
-
- if (pi == NULL)
- return (1);
- kif->kf_un.kf_pipe.kf_pipe_addr = (uintptr_t)pi;
- kif->kf_un.kf_pipe.kf_pipe_peer = (uintptr_t)pi->pipe_peer;
- kif->kf_un.kf_pipe.kf_pipe_buffer_cnt = pi->pipe_buffer.cnt;
- return (0);
-}
-
-static int
-fill_procdesc_info(struct procdesc *pdp, struct kinfo_file *kif)
-{
-
- if (pdp == NULL)
- return (1);
- kif->kf_un.kf_proc.kf_pid = pdp->pd_pid;
- return (0);
-}
-
-static int
-fill_sem_info(struct file *fp, struct kinfo_file *kif)
-{
- struct thread *td;
- struct stat sb;
-
- td = curthread;
- if (fp->f_data == NULL)
- return (1);
- if (fo_stat(fp, &sb, td->td_ucred, td) != 0)
- return (1);
- if (ksem_info == NULL)
- return (1);
- ksem_info(fp->f_data, kif->kf_path, sizeof(kif->kf_path),
- &kif->kf_un.kf_sem.kf_sem_value);
- kif->kf_un.kf_sem.kf_sem_mode = sb.st_mode;
- return (0);
-}
-
-static int
-fill_shm_info(struct file *fp, struct kinfo_file *kif)
-{
- struct thread *td;
- struct stat sb;
-
- td = curthread;
- if (fp->f_data == NULL)
- return (1);
- if (fo_stat(fp, &sb, td->td_ucred, td) != 0)
- return (1);
- shm_path(fp->f_data, kif->kf_path, sizeof(kif->kf_path));
- kif->kf_un.kf_file.kf_file_mode = sb.st_mode;
- kif->kf_un.kf_file.kf_file_size = sb.st_size;
- return (0);
-}
-
static SYSCTL_NODE(_kern_proc, KERN_PROC_FILEDESC, filedesc,
CTLFLAG_RD|CTLFLAG_MPSAFE, sysctl_kern_proc_filedesc,
"Process filedesc entries");
@@ -3926,6 +3543,13 @@ badfo_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
return (EBADF);
}
+static int
+badfo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+
+ return (0);
+}
+
struct fileops badfileops = {
.fo_read = badfo_readwrite,
.fo_write = badfo_readwrite,
@@ -3938,6 +3562,7 @@ struct fileops badfileops = {
.fo_chmod = badfo_chmod,
.fo_chown = badfo_chown,
.fo_sendfile = badfo_sendfile,
+ .fo_fill_kinfo = badfo_fill_kinfo,
};
int
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 36ec19ed815c..7488652c20de 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include <sys/syscallsubr.h>
#include <sys/taskqueue.h>
#include <sys/uio.h>
+#include <sys/user.h>
#ifdef KTRACE
#include <sys/ktrace.h>
#endif
@@ -114,6 +115,7 @@ static fo_poll_t kqueue_poll;
static fo_kqfilter_t kqueue_kqfilter;
static fo_stat_t kqueue_stat;
static fo_close_t kqueue_close;
+static fo_fill_kinfo_t kqueue_fill_kinfo;
static struct fileops kqueueops = {
.fo_read = invfo_rdwr,
@@ -127,6 +129,7 @@ static struct fileops kqueueops = {
.fo_chmod = invfo_chmod,
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = kqueue_fill_kinfo,
};
static int knote_attach(struct knote *kn, struct kqueue *kq);
@@ -1802,6 +1805,14 @@ kqueue_close(struct file *fp, struct thread *td)
return (0);
}
+static int
+kqueue_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+
+ kif->kf_type = KF_TYPE_KQUEUE;
+ return (0);
+}
+
static void
kqueue_wakeup(struct kqueue *kq)
{
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index 1d12c8f630b5..b39c4fe2e247 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -115,6 +115,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/vnode.h>
#include <sys/uio.h>
+#include <sys/user.h>
#include <sys/event.h>
#include <security/mac/mac_framework.h>
@@ -152,6 +153,7 @@ static fo_stat_t pipe_stat;
static fo_close_t pipe_close;
static fo_chmod_t pipe_chmod;
static fo_chown_t pipe_chown;
+static fo_fill_kinfo_t pipe_fill_kinfo;
struct fileops pipeops = {
.fo_read = pipe_read,
@@ -165,6 +167,7 @@ struct fileops pipeops = {
.fo_chmod = pipe_chmod,
.fo_chown = pipe_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = pipe_fill_kinfo,
.fo_flags = DFLAG_PASSABLE
};
@@ -1607,6 +1610,21 @@ pipe_chown(fp, uid, gid, active_cred, td)
return (error);
}
+static int
+pipe_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+ struct pipe *pi;
+
+ if (fp->f_type == DTYPE_FIFO)
+ return (vn_fill_kinfo(fp, kif, fdp));
+ kif->kf_type = KF_TYPE_PIPE;
+ pi = fp->f_data;
+ kif->kf_un.kf_pipe.kf_pipe_addr = (uintptr_t)pi;
+ kif->kf_un.kf_pipe.kf_pipe_peer = (uintptr_t)pi->pipe_peer;
+ kif->kf_un.kf_pipe.kf_pipe_buffer_cnt = pi->pipe_buffer.cnt;
+ return (0);
+}
+
static void
pipe_free_kmem(cpipe)
struct pipe *cpipe;
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
index 9bdca9a1f6d5..948595f8751e 100644
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/ucred.h>
+#include <sys/user.h>
#include <security/audit/audit.h>
@@ -91,6 +92,7 @@ static fo_poll_t procdesc_poll;
static fo_kqfilter_t procdesc_kqfilter;
static fo_stat_t procdesc_stat;
static fo_close_t procdesc_close;
+static fo_fill_kinfo_t procdesc_fill_kinfo;
static struct fileops procdesc_ops = {
.fo_read = invfo_rdwr,
@@ -104,6 +106,7 @@ static struct fileops procdesc_ops = {
.fo_chmod = invfo_chmod,
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = procdesc_fill_kinfo,
.fo_flags = DFLAG_PASSABLE,
};
@@ -531,3 +534,14 @@ procdesc_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
return (0);
}
+static int
+procdesc_fill_kinfo(struct file *fp, struct kinfo_file *kif,
+ struct filedesc *fdp)
+{
+ struct procdesc *pdp;
+
+ kif->kf_type = KF_TYPE_PROCDESC;
+ pdp = fp->f_data;
+ kif->kf_un.kf_proc.kf_pid = pdp->pd_pid;
+ return (0);
+}
diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c
index 4af12e0be1e7..47cedfeab4b8 100644
--- a/sys/kern/sys_socket.c
+++ b/sys/kern/sys_socket.c
@@ -34,8 +34,10 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/domain.h>
#include <sys/file.h>
#include <sys/filedesc.h>
+#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/protosw.h>
#include <sys/sigio.h>
@@ -48,12 +50,18 @@ __FBSDID("$FreeBSD$");
#include <sys/stat.h>
#include <sys/uio.h>
#include <sys/ucred.h>
+#include <sys/un.h>
+#include <sys/unpcb.h>
+#include <sys/user.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/route.h>
#include <net/vnet.h>
+#include <netinet/in.h>
+#include <netinet/in_pcb.h>
+
#include <security/mac/mac_framework.h>
static fo_rdwr_t soo_read;
@@ -63,6 +71,7 @@ static fo_poll_t soo_poll;
extern fo_kqfilter_t soo_kqfilter;
static fo_stat_t soo_stat;
static fo_close_t soo_close;
+static fo_fill_kinfo_t soo_fill_kinfo;
struct fileops socketops = {
.fo_read = soo_read,
@@ -76,6 +85,7 @@ struct fileops socketops = {
.fo_chmod = invfo_chmod,
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = soo_fill_kinfo,
.fo_flags = DFLAG_PASSABLE
};
@@ -293,3 +303,58 @@ soo_close(struct file *fp, struct thread *td)
error = soclose(so);
return (error);
}
+
+static int
+soo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+ struct sockaddr *sa;
+ struct inpcb *inpcb;
+ struct unpcb *unpcb;
+ struct socket *so;
+ int error;
+
+ kif->kf_type = KF_TYPE_SOCKET;
+ so = fp->f_data;
+ kif->kf_sock_domain = so->so_proto->pr_domain->dom_family;
+ kif->kf_sock_type = so->so_type;
+ kif->kf_sock_protocol = so->so_proto->pr_protocol;
+ kif->kf_un.kf_sock.kf_sock_pcb = (uintptr_t)so->so_pcb;
+ switch (kif->kf_sock_domain) {
+ case AF_INET:
+ case AF_INET6:
+ if (kif->kf_sock_protocol == IPPROTO_TCP) {
+ if (so->so_pcb != NULL) {
+ inpcb = (struct inpcb *)(so->so_pcb);
+ kif->kf_un.kf_sock.kf_sock_inpcb =
+ (uintptr_t)inpcb->inp_ppcb;
+ }
+ }
+ break;
+ case AF_UNIX:
+ if (so->so_pcb != NULL) {
+ unpcb = (struct unpcb *)(so->so_pcb);
+ if (unpcb->unp_conn) {
+ kif->kf_un.kf_sock.kf_sock_unpconn =
+ (uintptr_t)unpcb->unp_conn;
+ kif->kf_un.kf_sock.kf_sock_rcv_sb_state =
+ so->so_rcv.sb_state;
+ kif->kf_un.kf_sock.kf_sock_snd_sb_state =
+ so->so_snd.sb_state;
+ }
+ }
+ break;
+ }
+ error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
+ if (error == 0 && sa->sa_len <= sizeof(kif->kf_sa_local)) {
+ bcopy(sa, &kif->kf_sa_local, sa->sa_len);
+ free(sa, M_SONAME);
+ }
+ error = so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa);
+ if (error == 0 && sa->sa_len <= sizeof(kif->kf_sa_peer)) {
+ bcopy(sa, &kif->kf_sa_peer, sa->sa_len);
+ free(sa, M_SONAME);
+ }
+ strncpy(kif->kf_path, so->so_proto->pr_domain->dom_name,
+ sizeof(kif->kf_path));
+ return (0);
+}
diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c
index 16cbb3c56f5f..58cbc526d273 100644
--- a/sys/kern/tty_pts.c
+++ b/sys/kern/tty_pts.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/tty.h>
#include <sys/ttycom.h>
+#include <sys/user.h>
#include <machine/stdarg.h>
@@ -580,6 +581,18 @@ ptsdev_close(struct file *fp, struct thread *td)
return (0);
}
+static int
+ptsdev_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+ struct tty *tp;
+
+ kif->kf_type = KF_TYPE_PTS;
+ tp = fp->f_data;
+ kif->kf_un.kf_pts.kf_pts_dev = tty_udev(tp);
+ strlcpy(kif->kf_path, tty_devname(tp), sizeof(kif->kf_path));
+ return (0);
+}
+
static struct fileops ptsdev_ops = {
.fo_read = ptsdev_read,
.fo_write = ptsdev_write,
@@ -592,6 +605,7 @@ static struct fileops ptsdev_ops = {
.fo_chmod = invfo_chmod,
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = ptsdev_fill_kinfo,
.fo_flags = DFLAG_PASSABLE,
};
diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c
index 24d5ada5f4f9..154c1e76613d 100644
--- a/sys/kern/uipc_mqueue.c
+++ b/sys/kern/uipc_mqueue.c
@@ -81,6 +81,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/taskqueue.h>
#include <sys/unistd.h>
+#include <sys/user.h>
#include <sys/vnode.h>
#include <machine/atomic.h>
@@ -2571,6 +2572,14 @@ filt_mqwrite(struct knote *kn, long hint)
return (mq->mq_curmsgs < mq->mq_maxmsg);
}
+static int
+mqf_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+
+ kif->kf_type = KF_TYPE_MQUEUE;
+ return (0);
+}
+
static struct fileops mqueueops = {
.fo_read = invfo_rdwr,
.fo_write = invfo_rdwr,
@@ -2583,6 +2592,7 @@ static struct fileops mqueueops = {
.fo_chmod = mqf_chmod,
.fo_chown = mqf_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = mqf_fill_kinfo,
};
static struct vop_vector mqfs_vnodeops = {
diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c
index 593c2a368e22..63b1cec0e036 100644
--- a/sys/kern/uipc_sem.c
+++ b/sys/kern/uipc_sem.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysproto.h>
#include <sys/systm.h>
#include <sys/sx.h>
+#include <sys/user.h>
#include <sys/vnode.h>
#include <security/mac/mac_framework.h>
@@ -130,6 +131,7 @@ static fo_stat_t ksem_stat;
static fo_close_t ksem_closef;
static fo_chmod_t ksem_chmod;
static fo_chown_t ksem_chown;
+static fo_fill_kinfo_t ksem_fill_kinfo;
/* File descriptor operations. */
static struct fileops ksem_ops = {
@@ -144,6 +146,7 @@ static struct fileops ksem_ops = {
.fo_chmod = ksem_chmod,
.fo_chown = ksem_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = ksem_fill_kinfo,
.fo_flags = DFLAG_PASSABLE
};
@@ -252,6 +255,26 @@ ksem_closef(struct file *fp, struct thread *td)
return (0);
}
+static int
+ksem_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+ struct ksem *ks;
+
+ kif->kf_type = KF_TYPE_SEM;
+ ks = fp->f_data;
+ mtx_lock(&sem_lock);
+ kif->kf_un.kf_sem.kf_sem_value = ks->ks_value;
+ kif->kf_un.kf_sem.kf_sem_mode = S_IFREG | ks->ks_mode; /* XXX */
+ mtx_unlock(&sem_lock);
+ if (ks->ks_path != NULL) {
+ sx_slock(&ksem_dict_lock);
+ if (ks->ks_path != NULL)
+ strlcpy(kif->kf_path, ks->ks_path, sizeof(kif->kf_path));
+ sx_sunlock(&ksem_dict_lock);
+ }
+ return (0);
+}
+
/*
* ksem object management including creation and reference counting
* routines.
@@ -388,20 +411,6 @@ ksem_remove(char *path, Fnv32_t fnv, struct ucred *ucred)
return (ENOENT);
}
-static void
-ksem_info_impl(struct ksem *ks, char *path, size_t size, uint32_t *value)
-{
-
- if (ks->ks_path == NULL)
- return;
- sx_slock(&ksem_dict_lock);
- if (ks->ks_path != NULL)
- strlcpy(path, ks->ks_path, size);
- if (value != NULL)
- *value = ks->ks_value;
- sx_sunlock(&ksem_dict_lock);
-}
-
static int
ksem_create_copyout_semid(struct thread *td, semid_t *semidp, int fd,
int compat32)
@@ -983,7 +992,6 @@ ksem_module_init(void)
p31b_setcfg(CTL_P1003_1B_SEMAPHORES, 200112L);
p31b_setcfg(CTL_P1003_1B_SEM_NSEMS_MAX, SEM_MAX);
p31b_setcfg(CTL_P1003_1B_SEM_VALUE_MAX, SEM_VALUE_MAX);
- ksem_info = ksem_info_impl;
error = syscall_helper_register(ksem_syscalls);
if (error)
@@ -1005,7 +1013,6 @@ ksem_module_destroy(void)
#endif
syscall_helper_unregister(ksem_syscalls);
- ksem_info = NULL;
p31b_setcfg(CTL_P1003_1B_SEMAPHORES, 0);
hashdestroy(ksem_dictionary, M_KSEM, ksem_hash);
sx_destroy(&ksem_dict_lock);
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c
index 9a558bec1fd8..7829620a7be6 100644
--- a/sys/kern/uipc_shm.c
+++ b/sys/kern/uipc_shm.c
@@ -75,6 +75,7 @@ __FBSDID("$FreeBSD$");
#include <sys/time.h>
#include <sys/vnode.h>
#include <sys/unistd.h>
+#include <sys/user.h>
#include <security/mac/mac_framework.h>
@@ -125,6 +126,7 @@ static fo_close_t shm_close;
static fo_chmod_t shm_chmod;
static fo_chown_t shm_chown;
static fo_seek_t shm_seek;
+static fo_fill_kinfo_t shm_fill_kinfo;
/* File descriptor operations. */
static struct fileops shm_ops = {
@@ -140,6 +142,7 @@ static struct fileops shm_ops = {
.fo_chown = shm_chown,
.fo_sendfile = vn_sendfile,
.fo_seek = shm_seek,
+ .fo_fill_kinfo = shm_fill_kinfo,
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
};
@@ -1022,14 +1025,24 @@ shm_unmap(struct file *fp, void *mem, size_t size)
return (0);
}
-void
-shm_path(struct shmfd *shmfd, char *path, size_t size)
+static int
+shm_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
{
+ struct shmfd *shmfd;
+
+ kif->kf_type = KF_TYPE_SHM;
+ shmfd = fp->f_data;
- if (shmfd->shm_path == NULL)
- return;
- sx_slock(&shm_dict_lock);
- if (shmfd->shm_path != NULL)
- strlcpy(path, shmfd->shm_path, size);
- sx_sunlock(&shm_dict_lock);
+ mtx_lock(&shm_timestamp_lock);
+ kif->kf_un.kf_file.kf_file_mode = S_IFREG | shmfd->shm_mode; /* XXX */
+ mtx_unlock(&shm_timestamp_lock);
+ kif->kf_un.kf_file.kf_file_size = shmfd->shm_size;
+ if (shmfd->shm_path != NULL) {
+ sx_slock(&shm_dict_lock);
+ if (shmfd->shm_path != NULL)
+ strlcpy(kif->kf_path, shmfd->shm_path,
+ sizeof(kif->kf_path));
+ sx_sunlock(&shm_dict_lock);
+ }
+ return (0);
}
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 98823f383433..617bda0d4ce6 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/syslog.h>
#include <sys/unistd.h>
+#include <sys/user.h>
#include <security/audit/audit.h>
#include <security/mac/mac_framework.h>
@@ -103,6 +104,7 @@ struct fileops vnops = {
.fo_chown = vn_chown,
.fo_sendfile = vn_sendfile,
.fo_seek = vn_seek,
+ .fo_fill_kinfo = vn_fill_kinfo,
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
};
@@ -2249,3 +2251,61 @@ vn_utimes_perm(struct vnode *vp, struct vattr *vap, struct ucred *cred,
error = VOP_ACCESS(vp, VWRITE, cred, td);
return (error);
}
+
+int
+vn_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+ struct vnode *vp;
+ int error;
+
+ if (fp->f_type == DTYPE_FIFO)
+ kif->kf_type = KF_TYPE_FIFO;
+ else
+ kif->kf_type = KF_TYPE_VNODE;
+ vp = fp->f_vnode;
+ vref(vp);
+ FILEDESC_SUNLOCK(fdp);
+ error = vn_fill_kinfo_vnode(vp, kif);
+ vrele(vp);
+ FILEDESC_SLOCK(fdp);
+ return (error);
+}
+
+int
+vn_fill_kinfo_vnode(struct vnode *vp, struct kinfo_file *kif)
+{
+ struct vattr va;
+ char *fullpath, *freepath;
+ int error;
+
+ kif->kf_vnode_type = vntype_to_kinfo(vp->v_type);
+ freepath = NULL;
+ fullpath = "-";
+ error = vn_fullpath(curthread, vp, &fullpath, &freepath);
+ if (error == 0) {
+ strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path));
+ }
+ if (freepath != NULL)
+ free(freepath, M_TEMP);
+
+ /*
+ * Retrieve vnode attributes.
+ */
+ va.va_fsid = VNOVAL;
+ va.va_rdev = NODEV;
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+ error = VOP_GETATTR(vp, &va, curthread->td_ucred);
+ VOP_UNLOCK(vp, 0);
+ if (error != 0)
+ return (error);
+ if (va.va_fsid != VNOVAL)
+ kif->kf_un.kf_file.kf_file_fsid = va.va_fsid;
+ else
+ kif->kf_un.kf_file.kf_file_fsid =
+ vp->v_mount->mnt_stat.f_fsid.val[0];
+ kif->kf_un.kf_file.kf_file_fileid = va.va_fileid;
+ kif->kf_un.kf_file.kf_file_mode = MAKEIMODE(va.va_type, va.va_mode);
+ kif->kf_un.kf_file.kf_file_size = va.va_size;
+ kif->kf_un.kf_file.kf_file_rdev = va.va_rdev;
+ return (0);
+}
diff --git a/sys/ofed/include/linux/linux_compat.c b/sys/ofed/include/linux/linux_compat.c
index f67039109a09..c2fb4d7d7abf 100644
--- a/sys/ofed/include/linux/linux_compat.c
+++ b/sys/ofed/include/linux/linux_compat.c
@@ -576,6 +576,14 @@ linux_file_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
return (EOPNOTSUPP);
}
+static int
+linux_file_fill_kinfo(struct file *fp, struct kinfo_file *kif,
+ struct filedesc *fdp)
+{
+
+ return (0);
+}
+
struct fileops linuxfileops = {
.fo_read = linux_file_read,
.fo_write = invfo_rdwr,
@@ -588,6 +596,7 @@ struct fileops linuxfileops = {
.fo_chmod = invfo_chmod,
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = linux_file_fill_kinfo,
};
/*
diff --git a/sys/opencrypto/cryptodev.c b/sys/opencrypto/cryptodev.c
index 778a6709cd43..472a90210508 100644
--- a/sys/opencrypto/cryptodev.c
+++ b/sys/opencrypto/cryptodev.c
@@ -286,6 +286,8 @@ static int cryptof_ioctl(struct file *, u_long, void *,
static int cryptof_stat(struct file *, struct stat *,
struct ucred *, struct thread *);
static int cryptof_close(struct file *, struct thread *);
+static int cryptof_fill_kinfo(struct file *, struct kinfo_file *,
+ struct filedesc *);
static struct fileops cryptofops = {
.fo_read = invfo_rdwr,
@@ -299,6 +301,7 @@ static struct fileops cryptofops = {
.fo_chmod = invfo_chmod,
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = cryptof_fill_kinfo,
};
static struct csession *csefind(struct fcrypt *, u_int);
@@ -958,6 +961,14 @@ cryptof_close(struct file *fp, struct thread *td)
return 0;
}
+static int
+cryptof_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+
+ kif->kf_type = KF_TYPE_CRYPTO;
+ return (0);
+}
+
static struct csession *
csefind(struct fcrypt *fcr, u_int ses)
{
diff --git a/sys/sys/file.h b/sys/sys/file.h
index 92f125f839a4..e593d4326240 100644
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -43,6 +43,7 @@
#include <sys/_lock.h>
#include <sys/_mutex.h>
+struct filedesc;
struct stat;
struct thread;
struct uio;
@@ -70,6 +71,7 @@ struct socket;
struct file;
struct filecaps;
+struct kinfo_file;
struct ucred;
#define FOF_OFFSET 0x01 /* Use the offset in uio argument */
@@ -114,6 +116,8 @@ typedef int fo_sendfile_t(struct file *fp, int sockfd, struct uio *hdr_uio,
struct sendfile_sync *sfs, struct thread *td);
typedef int fo_seek_t(struct file *fp, off_t offset, int whence,
struct thread *td);
+typedef int fo_fill_kinfo_t(struct file *fp, struct kinfo_file *kif,
+ struct filedesc *fdp);
typedef int fo_flags_t;
struct fileops {
@@ -129,6 +133,7 @@ struct fileops {
fo_chown_t *fo_chown;
fo_sendfile_t *fo_sendfile;
fo_seek_t *fo_seek;
+ fo_fill_kinfo_t *fo_fill_kinfo;
fo_flags_t fo_flags; /* DFLAG_* below */
};
@@ -242,6 +247,8 @@ fo_sendfile_t invfo_sendfile;
fo_sendfile_t vn_sendfile;
fo_seek_t vn_seek;
+fo_fill_kinfo_t vn_fill_kinfo;
+int vn_fill_kinfo_vnode(struct vnode *vp, struct kinfo_file *kif);
void finit(struct file *, u_int, short, void *, struct fileops *);
int fgetvp(struct thread *td, int fd, cap_rights_t *rightsp,
@@ -378,6 +385,13 @@ fo_seek(struct file *fp, off_t offset, int whence, struct thread *td)
return ((*fp->f_ops->fo_seek)(fp, offset, whence, td));
}
+static __inline int
+fo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+
+ return ((*fp->f_ops->fo_fill_kinfo)(fp, kif, fdp));
+}
+
#endif /* _KERNEL */
#endif /* !SYS_FILE_H */
diff --git a/sys/sys/ksem.h b/sys/sys/ksem.h
index c11c8656b64d..b337a2bfb6fb 100644
--- a/sys/sys/ksem.h
+++ b/sys/sys/ksem.h
@@ -63,9 +63,4 @@ struct ksem {
#define KS_ANONYMOUS 0x0001 /* Anonymous (unnamed) semaphore. */
#define KS_DEAD 0x0002 /* No new waiters allowed. */
-#ifdef _KERNEL
-extern void (*ksem_info)(struct ksem *ks, char *path, size_t size,
- uint32_t *value);
-#endif
-
#endif /* !_POSIX4_KSEM_H_ */
diff --git a/sys/sys/mman.h b/sys/sys/mman.h
index a13e3d1612d5..f0e01b696bb3 100644
--- a/sys/sys/mman.h
+++ b/sys/sys/mman.h
@@ -234,7 +234,6 @@ int shm_mmap(struct shmfd *shmfd, vm_size_t objsize, vm_ooffset_t foff,
vm_object_t *obj);
int shm_map(struct file *fp, size_t size, off_t offset, void **memp);
int shm_unmap(struct file *fp, void *mem, size_t size);
-void shm_path(struct shmfd *shmfd, char *path, size_t size);
#else /* !_KERNEL */