sysctl KERN_PROC_KQUEUE: implement compat32

Reviewed by:	markj
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D49372
This commit is contained in:
Konstantin Belousov 2025-03-14 01:05:21 +02:00
parent 6534c17326
commit fa8fdd80df
4 changed files with 98 additions and 13 deletions

View file

@ -446,6 +446,24 @@ struct kinfo_vm_layout32 {
uint32_t kvm_spare[12];
};
struct kinfo_knote32 {
int knt_kq_fd;
struct kevent32 knt_event;
int knt_status;
int knt_extdata;
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];

View file

@ -709,6 +709,56 @@ freebsd32_kevent_to_kevent32(const struct kevent *kevp, struct kevent32 *ks32)
}
}
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.
*/

View file

@ -122,6 +122,11 @@ struct image_args;
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_ */

View file

@ -75,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>
@ -2873,9 +2877,12 @@ knote_status_export(int kn_status)
static int
kern_proc_kqueue_report_one(struct sbuf *s, struct proc *p,
int kq_fd, struct kqueue *kq, struct knote *kn)
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)
@ -2889,7 +2896,13 @@ kern_proc_kqueue_report_one(struct sbuf *s, struct proc *p,
KQ_UNLOCK_FLUX(kq);
if (kn->kn_fop->f_userdump != NULL)
(void)kn->kn_fop->f_userdump(p, kn, &kin);
error = sbuf_bcat(s, &kin, sizeof(kin));
#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);
@ -2897,7 +2910,7 @@ kern_proc_kqueue_report_one(struct sbuf *s, struct proc *p,
static int
kern_proc_kqueue_report(struct sbuf *s, struct proc *p, int kq_fd,
struct kqueue *kq)
struct kqueue *kq, bool compat32)
{
struct knote *kn;
int error, i;
@ -2907,7 +2920,7 @@ kern_proc_kqueue_report(struct sbuf *s, struct proc *p, int kq_fd,
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);
kq, kn, compat32);
if (error != 0)
goto out;
}
@ -2917,7 +2930,7 @@ kern_proc_kqueue_report(struct sbuf *s, struct proc *p, int kq_fd,
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);
kq, kn, compat32);
if (error != 0)
goto out;
}
@ -2936,6 +2949,7 @@ sysctl_kern_proc_kqueue(SYSCTL_HANDLER_ARGS)
struct kqueue *kq;
struct sbuf *s, sm;
int error, error1, kq_fd, *name;
bool compat32;
name = (int *)arg1;
if ((u_int)arg2 != 2)
@ -2944,13 +2958,6 @@ sysctl_kern_proc_kqueue(SYSCTL_HANDLER_ARGS)
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;
kq_fd = name[1];
@ -2968,9 +2975,14 @@ sysctl_kern_proc_kqueue(SYSCTL_HANDLER_ARGS)
goto out2;
}
sbuf_clear_flags(s, SBUF_INCLUDENUL);
#ifdef FREEBSD_COMPAT32
compat32 = SV_CURPROC_FLAG(SV_ILP32);
#else
compat32 = false;
#endif
kq = fp->f_data;
error = kern_proc_kqueue_report(s, p, kq_fd, kq);
error = kern_proc_kqueue_report(s, p, kq_fd, kq, compat32);
error1 = sbuf_finish(s);
if (error == 0)
error = error1;