Index: sys/kern/kern_cpuset.c =================================================================== --- sys/kern/kern_cpuset.c +++ sys/kern/kern_cpuset.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -1742,6 +1743,59 @@ return (0); } +static int +copyin_set(struct thread *td, const void *u, void *k, size_t size) +{ + int rv; + rv = copyin(u, k, size); + + if (rv != 0) + return (rv); +#if defined(__LP64__) && defined(COMPAT_FREEBSD32) && \ + (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + struct bitset *kb = k; + if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) { + /* Loop through swapping words. */ + int *p = (int *)kb->__bits; + /* `size' is in bytes, we need bits. */ + for (int i = 0; i < __bitset_words(size * 8); i++) { + int tmp = p[0]; + p[0] = p[1]; + p[1] = tmp; + p += 2; + } + } +#endif + return (rv); +} + +static int +copyout_set(struct thread *td, const void *k, void *u, size_t size) +{ +#if defined(__LP64__) && defined(COMPAT_FREEBSD32) && \ + (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + const struct bitset *kb = k; + struct bitset *ub = u; + const int *kp = (const int *)kb->__bits; + int *up = (int *)ub->__bits; + int rv; + + for (int i = 0; i < __bitset_words(CPU_SETSIZE); i++) { + /* `size' is in bytes, we need bits. */ + for (int i = 0; i < __bitset_words(size * 8); i++) { + rv = suword32(up, kp[1]); + if (rv == 0) + rv = suword32(up + 1, kp[0]); + if (rv != 0) + return (rv); + } + } + return (0); +#else + return (copyout(k, u, size)); +#endif +} + #ifndef _SYS_SYSPROTO_H_ struct cpuset_args { cpusetid_t *setid; @@ -1977,7 +2031,7 @@ goto out; } size = min(cpusetsize, sizeof(cpuset_t)); - error = copyout(mask, maskp, size); + error = copyout_set(td, mask, maskp, size); if (error != 0) goto out; if (cpusetsize > size) { @@ -2117,7 +2171,7 @@ size = min(cpusetsize, sizeof(cpuset_t)); mask = malloc(sizeof(cpuset_t), M_TEMP, M_WAITOK | M_ZERO); - error = copyin(maskp, mask, size); + error = copyin_set(td, maskp, mask, size); if (error) goto out; /* @@ -2268,7 +2322,7 @@ } DOMAINSET_COPY(&outset.ds_mask, mask); if (error == 0) - error = copyout(mask, maskp, domainsetsize); + error = copyout_set(td, mask, maskp, domainsetsize); if (error == 0) if (suword32(policyp, outset.ds_policy) != 0) error = EFAULT; @@ -2318,7 +2372,7 @@ return (error); memset(&domain, 0, sizeof(domain)); mask = malloc(domainsetsize, M_TEMP, M_WAITOK | M_ZERO); - error = copyin(maskp, mask, domainsetsize); + error = copyin_set(td, maskp, mask, domainsetsize); if (error) goto out; /*