Page MenuHomeFreeBSD

D49372.diff
No OneTemporary

D49372.diff

diff --git a/lib/libprocstat/core.h b/lib/libprocstat/core.h
--- a/lib/libprocstat/core.h
+++ b/lib/libprocstat/core.h
@@ -31,7 +31,7 @@
#define _CORE_H
enum psc_type {
- PSC_TYPE_PROC,
+ PSC_TYPE_PROC = 0,
PSC_TYPE_FILES,
PSC_TYPE_VMMAP,
PSC_TYPE_GROUPS,
@@ -43,6 +43,7 @@
PSC_TYPE_ENVV,
PSC_TYPE_AUXV,
PSC_TYPE_PTLWPINFO,
+ PSC_TYPE_KQUEUES,
PSC_TYPE_MAX
};
diff --git a/lib/libprocstat/core.c b/lib/libprocstat/core.c
--- a/lib/libprocstat/core.c
+++ b/lib/libprocstat/core.c
@@ -57,22 +57,62 @@
GElf_Phdr pc_phdr;
};
-static struct psc_type_info {
+static const struct psc_type_info {
unsigned int n_type;
int structsize;
} psc_type_info[PSC_TYPE_MAX] = {
- { .n_type = NT_PROCSTAT_PROC, .structsize = sizeof(struct kinfo_proc) },
- { .n_type = NT_PROCSTAT_FILES, .structsize = sizeof(struct kinfo_file) },
- { .n_type = NT_PROCSTAT_VMMAP, .structsize = sizeof(struct kinfo_vmentry) },
- { .n_type = NT_PROCSTAT_GROUPS, .structsize = sizeof(gid_t) },
- { .n_type = NT_PROCSTAT_UMASK, .structsize = sizeof(u_short) },
- { .n_type = NT_PROCSTAT_RLIMIT, .structsize = sizeof(struct rlimit) * RLIM_NLIMITS },
- { .n_type = NT_PROCSTAT_OSREL, .structsize = sizeof(int) },
- { .n_type = NT_PROCSTAT_PSSTRINGS, .structsize = sizeof(vm_offset_t) },
- { .n_type = NT_PROCSTAT_PSSTRINGS, .structsize = sizeof(vm_offset_t) },
- { .n_type = NT_PROCSTAT_PSSTRINGS, .structsize = sizeof(vm_offset_t) },
- { .n_type = NT_PROCSTAT_AUXV, .structsize = sizeof(Elf_Auxinfo) },
- { .n_type = NT_PTLWPINFO, .structsize = sizeof(struct ptrace_lwpinfo) },
+ [PSC_TYPE_PROC] = {
+ .n_type = NT_PROCSTAT_PROC,
+ .structsize = sizeof(struct kinfo_proc)
+ },
+ [PSC_TYPE_FILES] = {
+ .n_type = NT_PROCSTAT_FILES,
+ .structsize = sizeof(struct kinfo_file)
+ },
+ [PSC_TYPE_VMMAP] = {
+ .n_type = NT_PROCSTAT_VMMAP,
+ .structsize = sizeof(struct kinfo_vmentry)
+ },
+ [PSC_TYPE_GROUPS] = {
+ .n_type = NT_PROCSTAT_GROUPS,
+ .structsize = sizeof(gid_t)
+ },
+ [PSC_TYPE_UMASK] = {
+ .n_type = NT_PROCSTAT_UMASK,
+ .structsize = sizeof(u_short)
+ },
+ [PSC_TYPE_RLIMIT] = {
+ .n_type = NT_PROCSTAT_RLIMIT,
+ .structsize = sizeof(struct rlimit) * RLIM_NLIMITS
+ },
+ [PSC_TYPE_OSREL] = {
+ .n_type = NT_PROCSTAT_OSREL,
+ .structsize = sizeof(int)
+ },
+ [PSC_TYPE_PSSTRINGS] = {
+ .n_type = NT_PROCSTAT_PSSTRINGS,
+ .structsize = sizeof(vm_offset_t)
+ },
+ [PSC_TYPE_ARGV] = {
+ .n_type = NT_PROCSTAT_PSSTRINGS,
+ .structsize = sizeof(vm_offset_t)
+ },
+ [PSC_TYPE_ENVV] = {
+ .n_type = NT_PROCSTAT_PSSTRINGS,
+ .structsize = sizeof(vm_offset_t)
+ },
+ [PSC_TYPE_AUXV] = {
+ .n_type = NT_PROCSTAT_AUXV,
+ .structsize = sizeof(Elf_Auxinfo)
+ },
+ [PSC_TYPE_PTLWPINFO] = {
+ .n_type = NT_PTLWPINFO,
+ .structsize = sizeof(struct ptrace_lwpinfo)
+ },
+ [PSC_TYPE_KQUEUES] = {
+ .n_type = NT_PROCSTAT_KQUEUES,
+ .structsize = sizeof(struct kinfo_knote)
+ },
};
static bool core_offset(struct procstat_core *core, off_t offset);
diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
--- a/lib/libprocstat/libprocstat.c
+++ b/lib/libprocstat/libprocstat.c
@@ -2862,6 +2862,9 @@
procstat_get_kqueue_info(struct procstat *procstat,
struct kinfo_proc *kp, int kqfd, unsigned int *count, char *errbuf)
{
+ struct kinfo_knote *kn, *k, *res, *rn;
+ size_t len, kqn;
+
switch (procstat->type) {
case PROCSTAT_KVM:
warnx("kvm method is not supported");
@@ -2870,8 +2873,34 @@
return (procstat_get_kqueue_info_sysctl(kp->ki_pid, kqfd,
count, errbuf));
case PROCSTAT_CORE:
- warnx("core method is not supported");
- return (NULL);
+ k = procstat_core_get(procstat->core, PSC_TYPE_KQUEUES,
+ NULL, &len);
+ if (k == NULL) {
+ snprintf(errbuf, _POSIX2_LINE_MAX,
+ "getting NT_PROCSTAT_KQUEUES note failed");
+ *count = 0;
+ return (NULL);
+ }
+ for (kqn = 0, kn = k; kn < k + len / sizeof(*kn); kn++) {
+ if (kn->knt_kq_fd == kqfd)
+ kqn++;
+ }
+ res = calloc(kqn, sizeof(*res));
+ if (res == NULL) {
+ free(k);
+ snprintf(errbuf, _POSIX2_LINE_MAX,
+ "no memory");
+ return (NULL);
+ }
+ for (kn = k, rn = res; kn < k + len / sizeof(*kn); kn++) {
+ if (kn->knt_kq_fd != kqfd)
+ continue;
+ *rn = *kn;
+ rn++;
+ }
+ *count = kqn;
+ free(k);
+ return (res);
default:
warnx("unknown access method: %d", procstat->type);
return (NULL);
diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h
--- a/sys/compat/freebsd32/freebsd32.h
+++ b/sys/compat/freebsd32/freebsd32.h
@@ -446,6 +446,25 @@
uint32_t kvm_spare[12];
};
+struct kinfo_knote32 {
+ int knt_kq_fd;
+ struct kevent32 knt_event;
+ int knt_status;
+ int knt_extdata;
+ uint32_t knt_spare0[8];
+ union {
+ struct {
+ int knt_vnode_type;
+ uint32_t knt_vnode_fsid[2];
+ uint32_t knt_vnode_fileid[2];
+ char knt_vnode_fullpath[PATH_MAX];
+ } knt_vnode;
+ struct {
+ uint32_t knt_pipe_ino[2];
+ } knt_pipe;
+ };
+};
+
struct kld_file_stat_1_32 {
int version; /* set to sizeof(struct kld_file_stat_1) */
char name[MAXPATHLEN];
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -679,6 +679,86 @@
return (error);
}
+static void
+freebsd32_kevent_to_kevent32(const struct kevent *kevp, struct kevent32 *ks32)
+{
+ uint64_t e;
+ int j;
+
+ CP(*kevp, *ks32, ident);
+ CP(*kevp, *ks32, filter);
+ CP(*kevp, *ks32, flags);
+ CP(*kevp, *ks32, fflags);
+#if BYTE_ORDER == LITTLE_ENDIAN
+ ks32->data1 = kevp->data;
+ ks32->data2 = kevp->data >> 32;
+#else
+ ks32->data1 = kevp->data >> 32;
+ ks32->data2 = kevp->data;
+#endif
+ PTROUT_CP(*kevp, *ks32, udata);
+ for (j = 0; j < nitems(kevp->ext); j++) {
+ e = kevp->ext[j];
+#if BYTE_ORDER == LITTLE_ENDIAN
+ ks32->ext64[2 * j] = e;
+ ks32->ext64[2 * j + 1] = e >> 32;
+#else
+ ks32->ext64[2 * j] = e >> 32;
+ ks32->ext64[2 * j + 1] = e;
+#endif
+ }
+}
+
+void
+freebsd32_kinfo_knote_to_32(const struct kinfo_knote *kin,
+ struct kinfo_knote32 *kin32)
+{
+ memset(kin32, 0, sizeof(*kin32));
+ CP(*kin, *kin32, knt_kq_fd);
+ freebsd32_kevent_to_kevent32(&kin->knt_event, &kin32->knt_event);
+ CP(*kin, *kin32, knt_status);
+ CP(*kin, *kin32, knt_extdata);
+ switch (kin->knt_extdata) {
+ case KNOTE_EXTDATA_NONE:
+ break;
+ case KNOTE_EXTDATA_VNODE:
+ CP(*kin, *kin32, knt_vnode.knt_vnode_type);
+#if BYTE_ORDER == LITTLE_ENDIAN
+ kin32->knt_vnode.knt_vnode_fsid[0] = kin->knt_vnode.
+ knt_vnode_fsid;
+ kin32->knt_vnode.knt_vnode_fsid[1] = kin->knt_vnode.
+ knt_vnode_fsid >> 32;
+ kin32->knt_vnode.knt_vnode_fileid[0] = kin->knt_vnode.
+ knt_vnode_fileid;
+ kin32->knt_vnode.knt_vnode_fileid[1] = kin->knt_vnode.
+ knt_vnode_fileid >> 32;
+#else
+ kin32->knt_vnode.knt_vnode_fsid[1] = kin->knt_vnode.
+ knt_vnode_fsid;
+ kin32->knt_vnode.knt_vnode_fsid[0] = kin->knt_vnode.
+ knt_vnode_fsid >> 32;
+ kin32->knt_vnode.knt_vnode_fileid[1] = kin->knt_vnode.
+ knt_vnode_fileid;
+ kin32->knt_vnode.knt_vnode_fileid[0] = kin->knt_vnode.
+ knt_vnode_fileid >> 32;
+#endif
+ memcpy(kin32->knt_vnode.knt_vnode_fullpath,
+ kin->knt_vnode.knt_vnode_fullpath, PATH_MAX);
+ break;
+ case KNOTE_EXTDATA_PIPE:
+#if BYTE_ORDER == LITTLE_ENDIAN
+ kin32->knt_pipe.knt_pipe_ino[0] = kin->knt_pipe.knt_pipe_ino;
+ kin32->knt_pipe.knt_pipe_ino[1] = kin->knt_pipe.
+ knt_pipe_ino >> 32;
+#else
+ kin32->knt_pipe.knt_pipe_ino[1] = kin->knt_pipe.knt_pipe_ino;
+ kin32->knt_pipe.knt_pipe_ino[0] = kin->knt_pipe.
+ knt_pipe_ino >> 32;
+#endif
+ break;
+ }
+}
+
/*
* Copy 'count' items into the destination list pointed to by uap->eventlist.
*/
@@ -687,36 +767,13 @@
{
struct freebsd32_kevent_args *uap;
struct kevent32 ks32[KQ_NEVENTS];
- uint64_t e;
- int i, j, error;
+ int i, error;
KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
uap = (struct freebsd32_kevent_args *)arg;
- for (i = 0; i < count; i++) {
- CP(kevp[i], ks32[i], ident);
- CP(kevp[i], ks32[i], filter);
- CP(kevp[i], ks32[i], flags);
- CP(kevp[i], ks32[i], fflags);
-#if BYTE_ORDER == LITTLE_ENDIAN
- ks32[i].data1 = kevp[i].data;
- ks32[i].data2 = kevp[i].data >> 32;
-#else
- ks32[i].data1 = kevp[i].data >> 32;
- ks32[i].data2 = kevp[i].data;
-#endif
- PTROUT_CP(kevp[i], ks32[i], udata);
- for (j = 0; j < nitems(kevp->ext); j++) {
- e = kevp[i].ext[j];
-#if BYTE_ORDER == LITTLE_ENDIAN
- ks32[i].ext64[2 * j] = e;
- ks32[i].ext64[2 * j + 1] = e >> 32;
-#else
- ks32[i].ext64[2 * j] = e >> 32;
- ks32[i].ext64[2 * j + 1] = e;
-#endif
- }
- }
+ for (i = 0; i < count; i++)
+ freebsd32_kevent_to_kevent32(&kevp[i], &ks32[i]);
error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
if (error == 0)
uap->eventlist += count;
diff --git a/sys/compat/freebsd32/freebsd32_util.h b/sys/compat/freebsd32/freebsd32_util.h
--- a/sys/compat/freebsd32/freebsd32_util.h
+++ b/sys/compat/freebsd32/freebsd32_util.h
@@ -122,6 +122,11 @@
int freebsd32_exec_copyin_args(struct image_args *args, const char *fname,
enum uio_seg segflg, uint32_t *argv, uint32_t *envv);
+struct kinfo_knote;
+struct kinfo_knote32;
+void freebsd32_kinfo_knote_to_32(const struct kinfo_knote *kin,
+ struct kinfo_knote32 *kin32);
+
extern int compat_freebsd_32bit;
#endif /* !_COMPAT_FREEBSD32_FREEBSD32_UTIL_H_ */
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -1574,6 +1574,7 @@
static void __elfN(note_procstat_auxv)(void *, struct sbuf *, size_t *);
static void __elfN(note_procstat_proc)(void *, struct sbuf *, size_t *);
static void __elfN(note_procstat_psstrings)(void *, struct sbuf *, size_t *);
+static void __elfN(note_procstat_kqueues)(void *, struct sbuf *, size_t *);
static void note_procstat_files(void *, struct sbuf *, size_t *);
static void note_procstat_groups(void *, struct sbuf *, size_t *);
static void note_procstat_osrel(void *, struct sbuf *, size_t *);
@@ -1899,6 +1900,8 @@
__elfN(note_procstat_psstrings), p);
size += __elfN(register_note)(td, list, NT_PROCSTAT_AUXV,
__elfN(note_procstat_auxv), p);
+ size += __elfN(register_note)(td, list, NT_PROCSTAT_KQUEUES,
+ __elfN(note_procstat_kqueues), p);
*sizep = size;
}
@@ -2719,6 +2722,54 @@
}
}
+static void
+__elfN(note_procstat_kqueues)(void *arg, struct sbuf *sb, size_t *sizep)
+{
+ struct proc *p;
+ size_t size, sect_sz, i;
+ ssize_t start_len, sect_len;
+ int structsize;
+ bool compat32;
+
+#if defined(COMPAT_FREEBSD32) && __ELF_WORD_SIZE == 32
+ compat32 = true;
+ structsize = sizeof(struct kinfo_knote32);
+#else
+ compat32 = false;
+ structsize = sizeof(struct kinfo_knote);
+#endif
+ p = arg;
+ if (sb == NULL) {
+ size = 0;
+ sb = sbuf_new(NULL, NULL, 128, SBUF_FIXEDLEN);
+ sbuf_set_drain(sb, sbuf_count_drain, &size);
+ sbuf_bcat(sb, &structsize, sizeof(structsize));
+ kern_proc_kqueues_out(p, sb, -1, compat32);
+ sbuf_finish(sb);
+ sbuf_delete(sb);
+ *sizep = size;
+ } else {
+ sbuf_start_section(sb, &start_len);
+
+ sbuf_bcat(sb, &structsize, sizeof(structsize));
+ kern_proc_kqueues_out(p, sb, *sizep - sizeof(structsize),
+ compat32);
+
+ sect_len = sbuf_end_section(sb, start_len, 0, 0);
+ if (sect_len < 0)
+ return;
+ sect_sz = sect_len;
+
+ KASSERT(sect_sz <= *sizep,
+ ("kern_proc_kqueue_out did not respect maxlen; "
+ "requested %zu, got %zu", *sizep - sizeof(structsize),
+ sect_sz - sizeof(structsize)));
+
+ for (i = 0; i < *sizep - sect_sz && sb->s_error == 0; i++)
+ sbuf_putc(sb, 0);
+ }
+}
+
#define MAX_NOTES_LOOP 4096
bool
__elfN(parse_notes)(const struct image_params *imgp, const Elf_Note *checknote,
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -34,14 +34,11 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
#include "opt_capsicum.h"
#include "opt_ddb.h"
#include "opt_ktrace.h"
-#include <sys/param.h>
#include <sys/systm.h>
-
#include <sys/capsicum.h>
#include <sys/conf.h>
#include <sys/fcntl.h>
@@ -2996,6 +2993,47 @@
return (error);
}
+int
+fget_remote_foreach(struct thread *td, struct proc *p,
+ int (*fn)(struct proc *, int, struct file *, void *), void *arg)
+{
+ struct filedesc *fdp;
+ struct fdescenttbl *fdt;
+ struct file *fp;
+ int error, error1, fd, highfd;
+
+ error = 0;
+ PROC_LOCK(p);
+ fdp = fdhold(p);
+ PROC_UNLOCK(p);
+ if (fdp == NULL)
+ return (ENOENT);
+
+ FILEDESC_SLOCK(fdp);
+ if (refcount_load(&fdp->fd_refcnt) != 0) {
+ fdt = atomic_load_ptr(&fdp->fd_files);
+ highfd = fdt->fdt_nfiles - 1;
+ FILEDESC_SUNLOCK(fdp);
+ } else {
+ error = ENOENT;
+ FILEDESC_SUNLOCK(fdp);
+ goto out;
+ }
+
+ for (fd = 0; fd <= highfd; fd++) {
+ error1 = fget_remote(td, p, fd, &fp);
+ if (error1 != 0)
+ continue;
+ error = fn(p, fd, fp, arg);
+ fdrop(fp, td);
+ if (error != 0)
+ break;
+ }
+out:
+ fddrop(fdp);
+ return (error);
+}
+
#ifdef CAPABILITIES
int
fgetvp_lookup_smr(struct nameidata *ndp, struct vnode **vpp, bool *fsearch)
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -58,6 +58,7 @@
#include <sys/poll.h>
#include <sys/protosw.h>
#include <sys/resourcevar.h>
+#include <sys/sbuf.h>
#include <sys/sigio.h>
#include <sys/signalvar.h>
#include <sys/socket.h>
@@ -74,6 +75,10 @@
#include <sys/ktrace.h>
#endif
#include <machine/atomic.h>
+#ifdef COMPAT_FREEBSD32
+#include <compat/freebsd32/freebsd32.h>
+#include <compat/freebsd32/freebsd32_util.h>
+#endif
#include <vm/uma.h>
@@ -2871,94 +2876,181 @@
}
static int
-sysctl_kern_proc_kqueue_report_one(struct proc *p, struct sysctl_req *req,
- struct kqueue *kq, struct knote *kn)
+kern_proc_kqueue_report_one(struct sbuf *s, struct proc *p,
+ int kq_fd, struct kqueue *kq, struct knote *kn, bool compat32 __unused)
{
struct kinfo_knote kin;
+#ifdef COMPAT_FREEBSD32
+ struct kinfo_knote32 kin32;
+#endif
int error;
if (kn->kn_status == KN_MARKER)
return (0);
memset(&kin, 0, sizeof(kin));
+ kin.knt_kq_fd = kq_fd;
memcpy(&kin.knt_event, &kn->kn_kevent, sizeof(struct kevent));
kin.knt_status = knote_status_export(kn->kn_status);
kn_enter_flux(kn);
KQ_UNLOCK_FLUX(kq);
if (kn->kn_fop->f_userdump != NULL)
(void)kn->kn_fop->f_userdump(p, kn, &kin);
- error = SYSCTL_OUT(req, &kin, sizeof(kin));
- maybe_yield();
+#ifdef COMPAT_FREEBSD32
+ if (compat32) {
+ freebsd32_kinfo_knote_to_32(&kin, &kin32);
+ error = sbuf_bcat(s, &kin32, sizeof(kin32));
+ } else
+#endif
+ error = sbuf_bcat(s, &kin, sizeof(kin));
KQ_LOCK(kq);
kn_leave_flux(kn);
return (error);
}
+static int
+kern_proc_kqueue_report(struct sbuf *s, struct proc *p, int kq_fd,
+ struct kqueue *kq, bool compat32)
+{
+ struct knote *kn;
+ int error, i;
+
+ error = 0;
+ KQ_LOCK(kq);
+ for (i = 0; i < kq->kq_knlistsize; i++) {
+ SLIST_FOREACH(kn, &kq->kq_knlist[i], kn_link) {
+ error = kern_proc_kqueue_report_one(s, p, kq_fd,
+ kq, kn, compat32);
+ if (error != 0)
+ goto out;
+ }
+ }
+ if (kq->kq_knhashmask == 0)
+ goto out;
+ for (i = 0; i <= kq->kq_knhashmask; i++) {
+ SLIST_FOREACH(kn, &kq->kq_knhash[i], kn_link) {
+ error = kern_proc_kqueue_report_one(s, p, kq_fd,
+ kq, kn, compat32);
+ if (error != 0)
+ goto out;
+ }
+ }
+out:
+ KQ_UNLOCK_FLUX(kq);
+ return (error);
+}
+
+struct kern_proc_kqueues_out1_cb_args {
+ struct sbuf *s;
+ bool compat32;
+};
+
+static int
+kern_proc_kqueues_out1_cb(struct proc *p, int fd, struct file *fp, void *arg)
+{
+ struct kqueue *kq;
+ struct kern_proc_kqueues_out1_cb_args *a;
+
+ if (fp->f_type != DTYPE_KQUEUE)
+ return (0);
+ a = arg;
+ kq = fp->f_data;
+ return (kern_proc_kqueue_report(a->s, p, fd, kq, a->compat32));
+}
+
+static int
+kern_proc_kqueues_out1(struct thread *td, struct proc *p, struct sbuf *s,
+ bool compat32)
+{
+ struct kern_proc_kqueues_out1_cb_args a;
+
+ a.s = s;
+ a.compat32 = compat32;
+ return (fget_remote_foreach(td, p, kern_proc_kqueues_out1_cb, &a));
+}
+
+int
+kern_proc_kqueues_out(struct proc *p, struct sbuf *sb, size_t maxlen,
+ bool compat32)
+{
+ struct sbuf *s, sm;
+ int error;
+
+ s = sbuf_new(&sm, NULL, maxlen, SBUF_FIXEDLEN);
+ error = kern_proc_kqueues_out1(curthread, p, s, compat32);
+ sbuf_finish(s);
+ if (error == 0)
+ sbuf_bcat(sb, sbuf_data(s), MIN(sbuf_len(s), maxlen));
+ sbuf_delete(s);
+ return (error);
+}
+
+static int
+sysctl_kern_proc_kqueue_one(struct thread *td, struct sbuf *s, struct proc *p,
+ int kq_fd, bool compat32)
+{
+ struct file *fp;
+ struct kqueue *kq;
+ int error;
+
+ error = fget_remote(td, p, kq_fd, &fp);
+ if (error == 0) {
+ if (fp->f_type != DTYPE_KQUEUE) {
+ error = EINVAL;
+ } else {
+ kq = fp->f_data;
+ error = kern_proc_kqueue_report(s, p, kq_fd, kq,
+ compat32);
+ }
+ fdrop(fp, td);
+ }
+ return (error);
+}
+
static int
sysctl_kern_proc_kqueue(SYSCTL_HANDLER_ARGS)
{
struct thread *td;
struct proc *p;
- struct file *fp;
- struct kqueue *kq;
- struct knote *kn;
- int error, i, *name;
+ struct sbuf *s, sm;
+ int error, error1, *name;
+ bool compat32;
name = (int *)arg1;
- if ((u_int)arg2 != 2)
+ if ((u_int)arg2 > 2 || (u_int)arg2 == 0)
return (EINVAL);
error = pget((pid_t)name[0], PGET_HOLD | PGET_CANDEBUG, &p);
if (error != 0)
return (error);
-#ifdef COMPAT_FREEBSD32
- if (SV_CURPROC_FLAG(SV_ILP32)) {
- /* XXXKIB */
- error = EOPNOTSUPP;
- goto out1;
- }
-#endif
td = curthread;
- error = fget_remote(td, p, name[1] /* kqfd */, &fp);
- if (error != 0)
- goto out1;
- if (fp->f_type != DTYPE_KQUEUE) {
- error = EINVAL;
- goto out2;
+#ifdef FREEBSD_COMPAT32
+ compat32 = SV_CURPROC_FLAG(SV_ILP32);
+#else
+ compat32 = false;
+#endif
+
+ s = sbuf_new_for_sysctl(&sm, NULL, 0, req);
+ if (s == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+ sbuf_clear_flags(s, SBUF_INCLUDENUL);
+
+ if ((u_int)arg2 == 1) {
+ error = kern_proc_kqueues_out1(td, p, s, compat32);
+ } else {
+ error = sysctl_kern_proc_kqueue_one(td, s, p,
+ name[1] /* kq_fd */, compat32);
}
- kq = fp->f_data;
- if (req->oldptr == NULL) {
- error = SYSCTL_OUT(req, NULL, sizeof(struct kinfo_knote) *
- kq->kq_knlistsize * 11 / 10);
- goto out2;
- }
+ error1 = sbuf_finish(s);
+ if (error == 0)
+ error = error1;
+ sbuf_delete(s);
- KQ_LOCK(kq);
- for (i = 0; i < kq->kq_knlistsize; i++) {
- SLIST_FOREACH(kn, &kq->kq_knlist[i], kn_link) {
- error = sysctl_kern_proc_kqueue_report_one(p, req,
- kq, kn);
- if (error != 0)
- goto out3;
- }
- }
- if (kq->kq_knhashmask == 0)
- goto out3;
- for (i = 0; i <= kq->kq_knhashmask; i++) {
- SLIST_FOREACH(kn, &kq->kq_knhash[i], kn_link) {
- error = sysctl_kern_proc_kqueue_report_one(p, req,
- kq, kn);
- if (error != 0)
- goto out3;
- }
- }
-out3:
- KQ_UNLOCK_FLUX(kq);
-out2:
- fdrop(fp, td);
-out1:
+out:
PRELE(p);
return (error);
}
diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h
--- a/sys/sys/elf_common.h
+++ b/sys/sys/elf_common.h
@@ -840,6 +840,7 @@
#define NT_PROCSTAT_PSSTRINGS 15 /* Procstat ps_strings data. */
#define NT_PROCSTAT_AUXV 16 /* Procstat auxv data. */
#define NT_PTLWPINFO 17 /* Thread ptrace miscellaneous info. */
+#define NT_PROCSTAT_KQUEUES 18 /* Procstat kqueues events. */
#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */
#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */
#define NT_X86_SEGBASES 0x200 /* x86 FS/GS base addresses. */
diff --git a/sys/sys/file.h b/sys/sys/file.h
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -267,6 +267,8 @@
int needfcntl, struct file **fpp);
int _fdrop(struct file *fp, struct thread *td);
int fget_remote(struct thread *td, struct proc *p, int fd, struct file **fpp);
+int fget_remote_foreach(struct thread *td, struct proc *p,
+ int (*fn)(struct proc *, int, struct file *, void *), void *arg);
fo_rdwr_t invfo_rdwr;
fo_truncate_t invfo_truncate;
diff --git a/sys/sys/user.h b/sys/sys/user.h
--- a/sys/sys/user.h
+++ b/sys/sys/user.h
@@ -677,9 +677,11 @@
#define KNOTE_EXTDATA_PIPE 2
struct kinfo_knote {
+ int knt_kq_fd;
struct kevent knt_event;
int knt_status;
int knt_extdata;
+ uint64_t knt_spare0[4];
union {
struct {
int knt_vnode_type;
@@ -720,6 +722,8 @@
int kern_proc_out(struct proc *p, struct sbuf *sb, int flags);
int kern_proc_vmmap_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
int flags);
+int kern_proc_kqueues_out(struct proc *p, struct sbuf *s, size_t maxlen,
+ bool compat32);
int vntype_to_kinfo(int vtype);
void pack_kinfo(struct kinfo_file *kif);
diff --git a/usr.bin/gcore/elfcore.c b/usr.bin/gcore/elfcore.c
--- a/usr.bin/gcore/elfcore.c
+++ b/usr.bin/gcore/elfcore.c
@@ -105,6 +105,7 @@
static void *elf_note_procstat_auxv(void *, size_t *);
static void *elf_note_procstat_files(void *, size_t *);
static void *elf_note_procstat_groups(void *, size_t *);
+static void *elf_note_procstat_kqueues(void *, size_t *);
static void *elf_note_procstat_osrel(void *, size_t *);
static void *elf_note_procstat_proc(void *, size_t *);
static void *elf_note_procstat_psstrings(void *, size_t *);
@@ -388,6 +389,7 @@
elf_putnote(NT_PROCSTAT_PSSTRINGS, elf_note_procstat_psstrings, &pid,
sb);
elf_putnote(NT_PROCSTAT_AUXV, elf_note_procstat_auxv, &pid, sb);
+ elf_putnote(NT_PROCSTAT_KQUEUES, elf_note_procstat_kqueues, &pid, sb);
#endif
size = sbuf_end_section(sb, old_len, 1, 0);
@@ -756,7 +758,7 @@
{
size_t len;
pid_t pid;
- int name[4], structsize;
+ int name[5], structsize;
void *buf, *p;
pid = *(pid_t *)arg;
@@ -841,6 +843,14 @@
sizeof(Elf_Auxinfo), sizep));
}
+static void *
+elf_note_procstat_kqueues(void *arg, size_t *sizep)
+{
+
+ return (procstat_sysctl(arg, KERN_PROC_KQUEUE,
+ sizeof(struct kinfo_knote), sizep));
+}
+
static void *
elf_note_procstat_rlimit(void *arg, size_t *sizep)
{

File Metadata

Mime Type
text/plain
Expires
Thu, Mar 20, 6:43 AM (21 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17227549
Default Alt Text
D49372.diff (21 KB)

Event Timeline