Index: sys/compat/linux/linux_misc.c =================================================================== --- sys/compat/linux/linux_misc.c +++ sys/compat/linux/linux_misc.c @@ -2033,11 +2033,13 @@ linux_sched_getaffinity(struct thread *td, struct linux_sched_getaffinity_args *args) { - int error; struct thread *tdt; + int error; + size_t size; - if (args->len < sizeof(cpuset_t)) - return (EINVAL); + size = args->len; + if (args->len > sizeof(cpuset_t)) + size = sizeof(cpuset_t); tdt = linux_tdfind(td, args->pid, -1); if (tdt == NULL) @@ -2046,9 +2048,11 @@ PROC_UNLOCK(tdt->td_proc); error = kern_cpuset_getaffinity(td, CPU_LEVEL_WHICH, CPU_WHICH_TID, - tdt->td_tid, sizeof(cpuset_t), (cpuset_t *)args->user_mask_ptr); + tdt->td_tid, size, (cpuset_t *)args->user_mask_ptr); if (error == 0) - td->td_retval[0] = sizeof(cpuset_t); + td->td_retval[0] = size; + else if (error == ERANGE) + error = EINVAL; return (error); } @@ -2061,18 +2065,21 @@ struct linux_sched_setaffinity_args *args) { struct thread *tdt; + int error; - if (args->len < sizeof(cpuset_t)) - return (EINVAL); - tdt = linux_tdfind(td, args->pid, -1); if (tdt == NULL) return (ESRCH); PROC_UNLOCK(tdt->td_proc); - return (kern_cpuset_setaffinity(td, CPU_LEVEL_WHICH, CPU_WHICH_TID, - tdt->td_tid, sizeof(cpuset_t), (cpuset_t *) args->user_mask_ptr)); + error = kern_cpuset_setaffinity(td, CPU_LEVEL_WHICH, CPU_WHICH_TID, + tdt->td_tid, args->len, (cpuset_t *)args->user_mask_ptr); + + if (error == ERANGE) + error = EINVAL; + + return (error); } struct linux_rlimit64 { Index: sys/kern/kern_cpuset.c =================================================================== --- sys/kern/kern_cpuset.c +++ sys/kern/kern_cpuset.c @@ -1758,12 +1758,12 @@ int error; size_t size; - if (cpusetsize < sizeof(cpuset_t) || cpusetsize > CPU_MAXSIZE / NBBY) + if (cpusetsize <= 0 || cpusetsize > CPU_MAXSIZE / NBBY) return (ERANGE); error = cpuset_check_capabilities(td, level, which, id); if (error != 0) return (error); - size = cpusetsize; + size = cpusetsize >= sizeof(cpuset_t) ? cpusetsize : sizeof(cpuset_t); mask = malloc(size, M_TEMP, M_WAITOK | M_ZERO); error = cpuset_which(which, id, &p, &ttd, &set); if (error) @@ -1834,8 +1834,12 @@ cpuset_rel(set); if (p) PROC_UNLOCK(p); + if (error == 0) { + if (roundup2(CPU_FLS(mask), NBBY) > cpusetsize * NBBY) + error = ERANGE; + } if (error == 0) - error = copyout(mask, maskp, size); + error = copyout(mask, maskp, cpusetsize); out: free(mask, M_TEMP); return (error); @@ -1868,13 +1872,15 @@ struct proc *p; cpuset_t *mask; int error; + size_t size; - if (cpusetsize < sizeof(cpuset_t) || cpusetsize > CPU_MAXSIZE / NBBY) + if (cpusetsize <= 0 || cpusetsize > CPU_MAXSIZE / NBBY) return (ERANGE); error = cpuset_check_capabilities(td, level, which, id); if (error != 0) return (error); - mask = malloc(cpusetsize, M_TEMP, M_WAITOK | M_ZERO); + size = cpusetsize >= sizeof(cpuset_t) ? cpusetsize : sizeof(cpuset_t); + mask = malloc(size, M_TEMP, M_WAITOK | M_ZERO); error = copyin(maskp, mask, cpusetsize); if (error) goto out; Index: sys/sys/cpuset.h =================================================================== --- sys/sys/cpuset.h +++ sys/sys/cpuset.h @@ -65,6 +65,7 @@ #define CPU_OR_ATOMIC(d, s) BIT_OR_ATOMIC(CPU_SETSIZE, d, s) #define CPU_COPY_STORE_REL(f, t) BIT_COPY_STORE_REL(CPU_SETSIZE, f, t) #define CPU_FFS(p) BIT_FFS(CPU_SETSIZE, p) +#define CPU_FLS(p) BIT_FLS(CPU_SETSIZE, p) #define CPU_COUNT(p) BIT_COUNT(CPU_SETSIZE, p) #define CPUSET_FSET BITSET_FSET(_NCPUWORDS) #define CPUSET_T_INITIALIZER BITSET_T_INITIALIZER