diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/fs/devfs/devfs_vnops.c | 1 | ||||
-rw-r--r-- | sys/kern/kern_descrip.c | 829 | ||||
-rw-r--r-- | sys/kern/kern_event.c | 11 | ||||
-rw-r--r-- | sys/kern/sys_pipe.c | 18 | ||||
-rw-r--r-- | sys/kern/sys_procdesc.c | 14 | ||||
-rw-r--r-- | sys/kern/sys_socket.c | 65 | ||||
-rw-r--r-- | sys/kern/tty_pts.c | 14 | ||||
-rw-r--r-- | sys/kern/uipc_mqueue.c | 10 | ||||
-rw-r--r-- | sys/kern/uipc_sem.c | 39 | ||||
-rw-r--r-- | sys/kern/uipc_shm.c | 29 | ||||
-rw-r--r-- | sys/kern/vfs_vnops.c | 60 | ||||
-rw-r--r-- | sys/ofed/include/linux/linux_compat.c | 9 | ||||
-rw-r--r-- | sys/opencrypto/cryptodev.c | 11 | ||||
-rw-r--r-- | sys/sys/file.h | 14 | ||||
-rw-r--r-- | sys/sys/ksem.h | 5 | ||||
-rw-r--r-- | sys/sys/mman.h | 1 |
16 files changed, 498 insertions, 632 deletions
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c index 1e3f5e8..d0aabef 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 b6fcc76..4564eb8 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 36ec19e..7488652 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 1d12c8f..b39c4fe 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 9bdca9a..948595f 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 4af12e0..47cedfe 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 16cbb3c..58cbc52 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 24d5ada..154c1e7 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 593c2a3..63b1cec 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 9a558be..7829620 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 98823f3..617bda0 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 f670391..c2fb4d7 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 778a670..472a902 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 92f125f..e593d43 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 c11c865..b337a2b 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 a13e3d1..f0e01b6 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 */ |