Add a new fo_fill_kinfo fileops method to add type-specific information to

struct kinfo_file.
- Move the various fill_*_info() methods out of kern_descrip.c and into the
  various file type implementations.
- Rework the support for kinfo_ofile to generate a suitable kinfo_file object
  for each file and then convert that to a kinfo_ofile structure rather than
  keeping a second, different set of code that directly manipulates
  type-specific file information.
- Remove the shm_path() and ksem_info() layering violations.

Differential Revision:	https://reviews.freebsd.org/D775
Reviewed by:	kib, glebius (earlier version)
This commit is contained in:
John Baldwin 2014-09-22 16:20:47 +00:00
parent 447666f08b
commit 9696feebe2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=271976
16 changed files with 499 additions and 633 deletions

View File

@ -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
};

View File

@ -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;
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++)
kflags = 0;
for (i = 0; i < nitems(fflags_table); i++)
if (fflags & fflags_table[i].fflag)
kif->kf_flags |= fflags_table[i].kf_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;
bzero(kif, sizeof(*kif));
/* 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

View File

@ -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)
{

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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,
};

View File

@ -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 = {

View File

@ -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);

View File

@ -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;
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);
kif->kf_type = KF_TYPE_SHM;
shmfd = fp->f_data;
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);
}

View File

@ -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);
}

View File

@ -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,
};
/*

View File

@ -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)
{

View File

@ -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 */

View File

@ -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_ */

View File

@ -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 */