Implement copyout packing more along the lines of what I had in mind.
Create a temporary duplicate implementation of old filedesc struct for pre-7.1 libgtop package. Todo: specific fd or addr request
This commit is contained in:
parent
83dc2280ce
commit
343bde9706
@ -2509,13 +2509,24 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS)
|
||||
SYSCTL_PROC(_kern, KERN_FILE, file, CTLTYPE_OPAQUE|CTLFLAG_RD,
|
||||
0, 0, sysctl_kern_file, "S,xfile", "Entire file table");
|
||||
|
||||
#ifdef KINFO_FILE_SIZE
|
||||
CTASSERT(sizeof(struct kinfo_file) == KINFO_FILE_SIZE);
|
||||
|
||||
/*
|
||||
* Sadly, the libgtop port has already been compiled for 7.1, but the code
|
||||
* does not do enough error checking and bad things might happen. Even
|
||||
* though we've not made a release with this stuff in it, the packages have
|
||||
* apparently been built.
|
||||
*
|
||||
* This should be deleted shortly after 7.1 is released and we go back to
|
||||
* 7-stable again. If the libgtop port can be rebuilt, then this can get
|
||||
* deleted before release.
|
||||
*/
|
||||
#ifdef KINFO_OFILE_SIZE
|
||||
CTASSERT(sizeof(struct kinfo_ofile) == KINFO_OFILE_SIZE);
|
||||
#endif
|
||||
|
||||
static int
|
||||
export_vnode_for_sysctl(struct vnode *vp, int type,
|
||||
struct kinfo_file *kif, struct filedesc *fdp, struct sysctl_req *req)
|
||||
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;
|
||||
@ -2528,7 +2539,7 @@ export_vnode_for_sysctl(struct vnode *vp, int type,
|
||||
kif->kf_fd = type;
|
||||
kif->kf_type = KF_TYPE_VNODE;
|
||||
/* This function only handles directories. */
|
||||
KASSERT(vp->v_type == VDIR, ("export_vnode_for_sysctl: vnode not directory"));
|
||||
KASSERT(vp->v_type == VDIR, ("export_vnode_for_osysctl: vnode not directory"));
|
||||
kif->kf_vnode_type = KF_VTYPE_VDIR;
|
||||
|
||||
/*
|
||||
@ -2557,10 +2568,10 @@ export_vnode_for_sysctl(struct vnode *vp, int type,
|
||||
* Get per-process file descriptors for use by procstat(1), et al.
|
||||
*/
|
||||
static int
|
||||
sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
|
||||
sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
char *fullpath, *freepath;
|
||||
struct kinfo_file *kif;
|
||||
struct kinfo_ofile *kif;
|
||||
struct filedesc *fdp;
|
||||
int error, i, *name;
|
||||
struct socket *so;
|
||||
@ -2584,13 +2595,13 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
|
||||
kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK);
|
||||
FILEDESC_SLOCK(fdp);
|
||||
if (fdp->fd_cdir != NULL)
|
||||
export_vnode_for_sysctl(fdp->fd_cdir, KF_FD_TYPE_CWD, kif,
|
||||
export_vnode_for_osysctl(fdp->fd_cdir, KF_FD_TYPE_CWD, kif,
|
||||
fdp, req);
|
||||
if (fdp->fd_rdir != NULL)
|
||||
export_vnode_for_sysctl(fdp->fd_rdir, KF_FD_TYPE_ROOT, kif,
|
||||
export_vnode_for_osysctl(fdp->fd_rdir, KF_FD_TYPE_ROOT, kif,
|
||||
fdp, req);
|
||||
if (fdp->fd_jdir != NULL)
|
||||
export_vnode_for_sysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL, kif,
|
||||
export_vnode_for_osysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL, kif,
|
||||
fdp, req);
|
||||
for (i = 0; i < fdp->fd_nfiles; i++) {
|
||||
if ((fp = fdp->fd_ofiles[i]) == NULL)
|
||||
@ -2753,6 +2764,259 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static SYSCTL_NODE(_kern_proc, KERN_PROC_OFILEDESC, ofiledesc, CTLFLAG_RD,
|
||||
sysctl_kern_proc_ofiledesc, "Process ofiledesc entries");
|
||||
|
||||
|
||||
#ifdef KINFO_FILE_SIZE
|
||||
CTASSERT(sizeof(struct kinfo_file) == KINFO_FILE_SIZE);
|
||||
#endif
|
||||
|
||||
static int
|
||||
export_vnode_for_sysctl(struct vnode *vp, int type,
|
||||
struct kinfo_file *kif, struct filedesc *fdp, struct sysctl_req *req)
|
||||
{
|
||||
int error;
|
||||
char *fullpath, *freepath;
|
||||
int vfslocked;
|
||||
|
||||
bzero(kif, sizeof(*kif));
|
||||
|
||||
vref(vp);
|
||||
kif->kf_fd = type;
|
||||
kif->kf_type = KF_TYPE_VNODE;
|
||||
/* This function only handles directories. */
|
||||
KASSERT(vp->v_type == VDIR, ("export_vnode_for_sysctl: vnode not directory"));
|
||||
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);
|
||||
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
|
||||
vrele(vp);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path));
|
||||
if (freepath != NULL)
|
||||
free(freepath, M_TEMP);
|
||||
kif->kf_structsize = offsetof(struct kinfo_file, kf_path) +
|
||||
strlen(kif->kf_path) + 1;
|
||||
kif->kf_structsize = roundup(kif->kf_structsize, sizeof(uint64_t));
|
||||
error = SYSCTL_OUT(req, kif, kif->kf_structsize);
|
||||
FILEDESC_SLOCK(fdp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get per-process file descriptors for use by procstat(1), et al.
|
||||
*/
|
||||
static int
|
||||
sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
char *fullpath, *freepath;
|
||||
struct kinfo_file *kif;
|
||||
struct filedesc *fdp;
|
||||
int error, i, *name;
|
||||
struct socket *so;
|
||||
struct vnode *vp;
|
||||
struct file *fp;
|
||||
struct proc *p;
|
||||
struct tty *tp;
|
||||
int vfslocked;
|
||||
|
||||
name = (int *)arg1;
|
||||
if ((p = pfind((pid_t)name[0])) == NULL)
|
||||
return (ESRCH);
|
||||
if ((error = p_candebug(curthread, p))) {
|
||||
PROC_UNLOCK(p);
|
||||
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_sysctl(fdp->fd_cdir, KF_FD_TYPE_CWD, kif,
|
||||
fdp, req);
|
||||
if (fdp->fd_rdir != NULL)
|
||||
export_vnode_for_sysctl(fdp->fd_rdir, KF_FD_TYPE_ROOT, kif,
|
||||
fdp, req);
|
||||
if (fdp->fd_jdir != NULL)
|
||||
export_vnode_for_sysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL, kif,
|
||||
fdp, req);
|
||||
for (i = 0; i < fdp->fd_nfiles; i++) {
|
||||
if ((fp = fdp->fd_ofiles[i]) == NULL)
|
||||
continue;
|
||||
bzero(kif, sizeof(*kif));
|
||||
vp = NULL;
|
||||
so = NULL;
|
||||
tp = 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;
|
||||
vref(vp);
|
||||
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;
|
||||
break;
|
||||
|
||||
case DTYPE_SEM:
|
||||
kif->kf_type = KF_TYPE_SEM;
|
||||
break;
|
||||
|
||||
case DTYPE_PTS:
|
||||
kif->kf_type = KF_TYPE_PTS;
|
||||
tp = fp->f_data;
|
||||
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 = fp->f_offset;
|
||||
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);
|
||||
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
|
||||
vrele(vp);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
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)
|
||||
== 00 && 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));
|
||||
}
|
||||
kif->kf_structsize = offsetof(struct kinfo_file, kf_path) +
|
||||
strlen(kif->kf_path) + 1;
|
||||
kif->kf_structsize = roundup(kif->kf_structsize,
|
||||
sizeof(uint64_t));
|
||||
error = SYSCTL_OUT(req, kif, kif->kf_structsize);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
fddrop(fdp);
|
||||
free(kif, M_TEMP);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static SYSCTL_NODE(_kern_proc, KERN_PROC_FILEDESC, filedesc, CTLFLAG_RD,
|
||||
sysctl_kern_proc_filedesc, "Process filedesc entries");
|
||||
|
||||
|
@ -541,12 +541,13 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry);
|
||||
#define KERN_PROC_GID 11 /* by effective group id */
|
||||
#define KERN_PROC_PATHNAME 12 /* path to executable */
|
||||
#define KERN_PROC_VMMAP 13 /* VM map entries for process */
|
||||
#define KERN_PROC_FILEDESC 14 /* File descriptors for process */
|
||||
#define KERN_PROC_OFILEDESC 14 /* Old file descriptors for process */
|
||||
#define KERN_PROC_KSTACK 15 /* Kernel stacks for process */
|
||||
#define KERN_PROC_INC_THREAD 0x10 /*
|
||||
* modifier for pid, pgrp, tty,
|
||||
* uid, ruid, gid, rgid and proc
|
||||
*/
|
||||
#define KERN_PROC_FILEDESC 32 /* File descriptors for process */
|
||||
|
||||
/*
|
||||
* KERN_IPC identifiers
|
||||
|
@ -236,9 +236,6 @@ struct user {
|
||||
struct kinfo_proc u_kproc; /* eproc */
|
||||
};
|
||||
|
||||
/* When exporting paths via sysctl, give a short version */
|
||||
#define KPROC_PATH_MAX 256
|
||||
|
||||
/*
|
||||
* The KERN_PROC_FILE sysctl allows a process to dump the file descriptor
|
||||
* array of another process.
|
||||
@ -280,8 +277,36 @@ struct user {
|
||||
#define KF_FLAG_DIRECT 0x00000040
|
||||
#define KF_FLAG_HASLOCK 0x00000080
|
||||
|
||||
/*
|
||||
* Old format. Has variable hidden padding due to alignment.
|
||||
* This is a compatability hack for pre-build 7.1 packages.
|
||||
*/
|
||||
#if defined(__amd64__)
|
||||
#define KINFO_OFILE_SIZE 1328
|
||||
#endif
|
||||
#if defined(__i386__)
|
||||
#define KINFO_OFILE_SIZE 1324
|
||||
#endif
|
||||
|
||||
struct kinfo_ofile {
|
||||
int kf_structsize; /* Size of kinfo_file. */
|
||||
int kf_type; /* Descriptor type. */
|
||||
int kf_fd; /* Array index. */
|
||||
int kf_ref_count; /* Reference count. */
|
||||
int kf_flags; /* Flags. */
|
||||
/* XXX Hidden alignment padding here on amd64 */
|
||||
off_t kf_offset; /* Seek location. */
|
||||
int kf_vnode_type; /* Vnode type. */
|
||||
int kf_sock_domain; /* Socket domain. */
|
||||
int kf_sock_type; /* Socket type. */
|
||||
int kf_sock_protocol; /* Socket protocol. */
|
||||
char kf_path[PATH_MAX]; /* Path to file, if any. */
|
||||
struct sockaddr_storage kf_sa_local; /* Socket address. */
|
||||
struct sockaddr_storage kf_sa_peer; /* Peer address. */
|
||||
};
|
||||
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
#define KINFO_FILE_SIZE 560
|
||||
#define KINFO_FILE_SIZE 1392
|
||||
#endif
|
||||
|
||||
struct kinfo_file {
|
||||
@ -290,7 +315,7 @@ struct kinfo_file {
|
||||
int kf_fd; /* Array index. */
|
||||
int kf_ref_count; /* Reference count. */
|
||||
int kf_flags; /* Flags. */
|
||||
int _kf_pad0; /* Alignment */
|
||||
int _kf_pad0; /* Round to 64 bit alignment */
|
||||
uint64_t kf_offset; /* Seek location. */
|
||||
int kf_vnode_type; /* Vnode type. */
|
||||
int kf_sock_domain; /* Socket domain. */
|
||||
@ -298,7 +323,9 @@ struct kinfo_file {
|
||||
int kf_sock_protocol; /* Socket protocol. */
|
||||
struct sockaddr_storage kf_sa_local; /* Socket address. */
|
||||
struct sockaddr_storage kf_sa_peer; /* Peer address. */
|
||||
char kf_path[KPROC_PATH_MAX]; /* Path to file, if any. */
|
||||
int _kf_ispare[16]; /* Space for more stuff. */
|
||||
/* Truncated before copyout in sysctl */
|
||||
char kf_path[PATH_MAX]; /* Path to file, if any. */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -322,7 +349,7 @@ struct kinfo_file {
|
||||
#define KVME_FLAG_NEEDS_COPY 0x00000002
|
||||
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
#define KINFO_VMENTRY_SIZE 384
|
||||
#define KINFO_VMENTRY_SIZE 1160
|
||||
#endif
|
||||
|
||||
struct kinfo_vmentry {
|
||||
@ -339,8 +366,10 @@ struct kinfo_vmentry {
|
||||
int kve_protection; /* Protection bitmask. */
|
||||
int kve_ref_count; /* VM obj ref count. */
|
||||
int kve_shadow_count; /* VM obj shadow count. */
|
||||
int _kve_ispare[15]; /* Space for more stuff. */
|
||||
char kve_path[KPROC_PATH_MAX]; /* Path to VM obj, if any. */
|
||||
int _kve_pad0; /* 64bit align next field */
|
||||
int _kve_ispare[16]; /* Space for more stuff. */
|
||||
/* Truncated before copyout in sysctl */
|
||||
char kve_path[PATH_MAX]; /* Path to VM obj, if any. */
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user