diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index b78f552dbff5..0326242ecd2e 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -1203,25 +1203,21 @@ freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap) if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) return (EINVAL); - - error = copyin(uap->name, &name, uap->namelen * sizeof(int)); + error = copyin(uap->name, name, uap->namelen * sizeof(int)); if (error) return (error); - mtx_lock(&Giant); - if (uap->oldlenp) oldlen = fuword32(uap->oldlenp); else oldlen = 0; error = userland_sysctl(td, name, uap->namelen, uap->old, &oldlen, 1, - uap->new, uap->newlen, &j); + uap->new, uap->newlen, &j, SCTL_MASK32); if (error && error != ENOMEM) goto done2; - if (uap->oldlenp) { + if (uap->oldlenp) suword32(uap->oldlenp, j); - } done2: mtx_unlock(&Giant); return (error); diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index d23683207999..06cbc6817109 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -104,8 +104,8 @@ sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS) int error; p = curproc; -#if defined(__amd64__) || defined(__ia64__) - if (req->oldlen == sizeof(unsigned int)) { +#ifdef SCTL_MASK32 + if (req->flags & SCTL_MASK32) { unsigned int val; val = (unsigned int)p->p_sysent->sv_psstrings; error = SYSCTL_OUT(req, &val, sizeof(val)); @@ -123,8 +123,8 @@ sysctl_kern_usrstack(SYSCTL_HANDLER_ARGS) int error; p = curproc; -#if defined(__amd64__) || defined(__ia64__) - if (req->oldlen == sizeof(unsigned int)) { +#ifdef SCTL_MASK32 + if (req->flags & SCTL_MASK32) { unsigned int val; val = (unsigned int)p->p_sysent->sv_usrstack; error = SYSCTL_OUT(req, &val, sizeof(val)); diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index eda6810605ff..af0dda4d792b 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -828,20 +828,35 @@ int sysctl_handle_long(SYSCTL_HANDLER_ARGS) { int error = 0; - long tmpout; + long tmplong; +#ifdef SCTL_MASK32 + int tmpint; +#endif /* * Attempt to get a coherent snapshot by making a copy of the data. */ if (!arg1) return (EINVAL); - tmpout = *(long *)arg1; - error = SYSCTL_OUT(req, &tmpout, sizeof(long)); + tmplong = *(long *)arg1; +#ifdef SCTL_MASK32 + if (req->flags & SCTL_MASK32) { + tmpint = tmplong; + error = SYSCTL_OUT(req, &tmpint, sizeof(int)); + } else +#endif + error = SYSCTL_OUT(req, &tmplong, sizeof(long)); if (error || !req->newptr) return (error); - error = SYSCTL_IN(req, arg1, sizeof(long)); +#ifdef SCTL_MASK32 + if (req->flags & SCTL_MASK32) { + error = SYSCTL_IN(req, &tmpint, sizeof(int)); + *(long *)arg1 = (long)tmpint; + } else +#endif + error = SYSCTL_IN(req, arg1, sizeof(long)); return (error); } @@ -965,7 +980,7 @@ sysctl_new_kernel(struct sysctl_req *req, void *p, size_t l) int kernel_sysctl(struct thread *td, int *name, u_int namelen, void *old, - size_t *oldlenp, void *new, size_t newlen, size_t *retval) + size_t *oldlenp, void *new, size_t newlen, size_t *retval, int flags) { int error = 0; struct sysctl_req req; @@ -973,6 +988,7 @@ kernel_sysctl(struct thread *td, int *name, u_int namelen, void *old, bzero(&req, sizeof req); req.td = td; + req.flags = flags; if (oldlenp) { req.oldlen = *oldlenp; @@ -1015,7 +1031,7 @@ kernel_sysctl(struct thread *td, int *name, u_int namelen, void *old, int kernel_sysctlbyname(struct thread *td, char *name, void *old, size_t *oldlenp, - void *new, size_t newlen, size_t *retval) + void *new, size_t newlen, size_t *retval, int flags) { int oid[CTL_MAXNAME]; size_t oidlen, plen; @@ -1026,12 +1042,12 @@ kernel_sysctlbyname(struct thread *td, char *name, void *old, size_t *oldlenp, oidlen = sizeof(oid); error = kernel_sysctl(td, oid, 2, oid, &oidlen, - (void *)name, strlen(name), &plen); + (void *)name, strlen(name), &plen, flags); if (error) return (error); error = kernel_sysctl(td, oid, plen / sizeof(int), old, oldlenp, - new, newlen, retval); + new, newlen, retval, flags); return (error); } @@ -1256,7 +1272,7 @@ __sysctl(struct thread *td, struct sysctl_args *uap) error = userland_sysctl(td, name, uap->namelen, uap->old, uap->oldlenp, 0, - uap->new, uap->newlen, &j); + uap->new, uap->newlen, &j, 0); if (error && error != ENOMEM) goto done2; if (uap->oldlenp) { @@ -1275,7 +1291,8 @@ __sysctl(struct thread *td, struct sysctl_args *uap) */ int userland_sysctl(struct thread *td, int *name, u_int namelen, void *old, - size_t *oldlenp, int inkernel, void *new, size_t newlen, size_t *retval) + size_t *oldlenp, int inkernel, void *new, size_t newlen, size_t *retval, + int flags) { int error = 0; struct sysctl_req req; @@ -1283,6 +1300,7 @@ userland_sysctl(struct thread *td, int *name, u_int namelen, void *old, bzero(&req, sizeof req); req.td = td; + req.flags = flags; if (oldlenp) { if (inkernel) { diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c index 984d237ec91e..4567dde2c070 100644 --- a/sys/kern/kern_tc.c +++ b/sys/kern/kern_tc.c @@ -92,8 +92,9 @@ time_t time_uptime = 0; static struct bintime boottimebin; struct timeval boottime; -SYSCTL_STRUCT(_kern, KERN_BOOTTIME, boottime, CTLFLAG_RD, - &boottime, timeval, "System boottime"); +static int sysctl_kern_boottime(SYSCTL_HANDLER_ARGS); +SYSCTL_PROC(_kern, KERN_BOOTTIME, boottime, CTLTYPE_STRUCT|CTLFLAG_RD, + NULL, 0, sysctl_kern_boottime, "S,timeval", "System boottime"); SYSCTL_NODE(_kern, OID_AUTO, timecounter, CTLFLAG_RW, 0, ""); @@ -116,6 +117,20 @@ TC_STATS(nsetclock); static void tc_windup(void); +static int +sysctl_kern_boottime(SYSCTL_HANDLER_ARGS) +{ +#ifdef SCTL_MASK32 + int tv[2]; + + if (req->flags & SCTL_MASK32) { + tv[0] = boottime.tv_sec; + tv[1] = boottime.tv_usec; + return SYSCTL_OUT(req, tv, sizeof(tv)); + } else +#endif + return SYSCTL_OUT(req, &boottime, sizeof(boottime)); +} /* * Return the difference between the timehands' counter value now and what * was when we copied it to the timehands' offset_count. diff --git a/sys/kern/kern_xxx.c b/sys/kern/kern_xxx.c index 6840e6411063..fdf6e27c398a 100644 --- a/sys/kern/kern_xxx.c +++ b/sys/kern/kern_xxx.c @@ -192,7 +192,7 @@ uname(td, uap) len = sizeof (uap->name->sysname); mtx_lock(&Giant); error = userland_sysctl(td, name, 2, uap->name->sysname, &len, - 1, 0, 0, 0); + 1, 0, 0, 0, 0); if (error) goto done2; subyte( uap->name->sysname + sizeof(uap->name->sysname) - 1, 0); @@ -200,7 +200,7 @@ uname(td, uap) name[1] = KERN_HOSTNAME; len = sizeof uap->name->nodename; error = userland_sysctl(td, name, 2, uap->name->nodename, &len, - 1, 0, 0, 0); + 1, 0, 0, 0, 0); if (error) goto done2; subyte( uap->name->nodename + sizeof(uap->name->nodename) - 1, 0); @@ -208,7 +208,7 @@ uname(td, uap) name[1] = KERN_OSRELEASE; len = sizeof uap->name->release; error = userland_sysctl(td, name, 2, uap->name->release, &len, - 1, 0, 0, 0); + 1, 0, 0, 0, 0); if (error) goto done2; subyte( uap->name->release + sizeof(uap->name->release) - 1, 0); @@ -217,7 +217,7 @@ uname(td, uap) name = KERN_VERSION; len = sizeof uap->name->version; error = userland_sysctl(td, name, 2, uap->name->version, &len, - 1, 0, 0, 0); + 1, 0, 0, 0, 0); if (error) goto done2; subyte( uap->name->version + sizeof(uap->name->version) - 1, 0); @@ -241,7 +241,7 @@ uname(td, uap) name[1] = HW_MACHINE; len = sizeof uap->name->machine; error = userland_sysctl(td, name, 2, uap->name->machine, &len, - 1, 0, 0, 0); + 1, 0, 0, 0, 0); if (error) goto done2; subyte( uap->name->machine + sizeof(uap->name->machine) - 1, 0); diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index 1431f64ec467..bea64dd56df9 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -120,6 +120,11 @@ struct ctlname { #define REQ_LOCKED 1 /* locked and not wired */ #define REQ_WIRED 2 /* locked and wired */ +/* definitions for sysctl_req 'flags' member */ +#if defined(__amd64__) || defined(__ia64__) +#define SCTL_MASK32 1 /* 32 bit emulation */ +#endif + /* * This describes the access space for a sysctl request. This is needed * so that we can use the interface from the kernel or from user-space. @@ -136,6 +141,7 @@ struct sysctl_req { size_t newidx; int (*newfunc)(struct sysctl_req *, void *, size_t); size_t validlen; + int flags; }; SLIST_HEAD(sysctl_oid_list, sysctl_oid); @@ -617,13 +623,13 @@ int sysctl_ctx_entry_del(struct sysctl_ctx_list *clist, int kernel_sysctl(struct thread *td, int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen, - size_t *retval); + size_t *retval, int flags); int kernel_sysctlbyname(struct thread *td, char *name, void *old, size_t *oldlenp, void *new, size_t newlen, - size_t *retval); + size_t *retval, int flags); int userland_sysctl(struct thread *td, int *name, u_int namelen, void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen, - size_t *retval); + size_t *retval, int flags); int sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid, int *nindx, struct sysctl_req *req); int sysctl_wire_old_buffer(struct sysctl_req *req, size_t len); diff --git a/sys/vm/vm_meter.c b/sys/vm/vm_meter.c index 4c09acd0eb71..4c3d60b3452e 100644 --- a/sys/vm/vm_meter.c +++ b/sys/vm/vm_meter.c @@ -85,8 +85,24 @@ SYSCTL_UINT(_vm, VM_V_PAGEOUT_FREE_MIN, v_pageout_free_min, SYSCTL_UINT(_vm, OID_AUTO, v_free_severe, CTLFLAG_RW, &cnt.v_free_severe, 0, ""); -SYSCTL_STRUCT(_vm, VM_LOADAVG, loadavg, CTLFLAG_RD, - &averunnable, loadavg, "Machine loadaverage history"); +static int +sysctl_vm_loadavg(SYSCTL_HANDLER_ARGS) +{ +#ifdef SCTL_MASK32 + u_int32_t la[4]; + + if (req->flags & SCTL_MASK32) { + la[0] = averunnable.ldavg[0]; + la[1] = averunnable.ldavg[1]; + la[2] = averunnable.ldavg[2]; + la[3] = averunnable.fscale; + return SYSCTL_OUT(req, la, sizeof(la)); + } else +#endif + return SYSCTL_OUT(req, &averunnable, sizeof(averunnable)); +} +SYSCTL_PROC(_vm, VM_LOADAVG, loadavg, CTLTYPE_STRUCT|CTLFLAG_RD, + NULL, 0, sysctl_vm_loadavg, "S,loadavg", "Machine loadaverage history"); static int vmtotal(SYSCTL_HANDLER_ARGS)