Skip to content

Commit 6015b1a

Browse files
committed
sched_getaffinity: don't assume 'cpumask_size()' is fully initialized
The getaffinity() system call uses 'cpumask_size()' to decide how big the CPU mask is - so far so good. It is indeed the allocation size of a cpumask. But the code also assumes that the whole allocation is initialized without actually doing so itself. That's wrong, because we might have fixed-size allocations (making copying and clearing more efficient), but not all of it is then necessarily used if 'nr_cpu_ids' is smaller. Having checked other users of 'cpumask_size()', they all seem to be ok, either using it purely for the allocation size, or explicitly zeroing the cpumask before using the size in bytes to copy it. See for example the ublk_ctrl_get_queue_affinity() function that uses the proper 'zalloc_cpumask_var()' to make sure that the whole mask is cleared, whether the storage is on the stack or if it was an external allocation. Fix this by just zeroing the allocation before using it. Do the same for the compat version of sched_getaffinity(), which had the same logic. Also, for consistency, make sched_getaffinity() use 'cpumask_bits()' to access the bits. For a cpumask_var_t, it ends up being a pointer to the same data either way, but it's just a good idea to treat it like you would a 'cpumask_t'. The compat case already did that. Reported-by: Ryan Roberts <[email protected]> Link: https://lore.kernel.org/lkml/[email protected]/ Cc: Yury Norov <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 26e2878 commit 6015b1a

File tree

2 files changed

+3
-3
lines changed

2 files changed

+3
-3
lines changed

kernel/compat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ COMPAT_SYSCALL_DEFINE3(sched_getaffinity, compat_pid_t, pid, unsigned int, len,
152152
if (len & (sizeof(compat_ulong_t)-1))
153153
return -EINVAL;
154154

155-
if (!alloc_cpumask_var(&mask, GFP_KERNEL))
155+
if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
156156
return -ENOMEM;
157157

158158
ret = sched_getaffinity(pid, mask);

kernel/sched/core.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8414,14 +8414,14 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
84148414
if (len & (sizeof(unsigned long)-1))
84158415
return -EINVAL;
84168416

8417-
if (!alloc_cpumask_var(&mask, GFP_KERNEL))
8417+
if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
84188418
return -ENOMEM;
84198419

84208420
ret = sched_getaffinity(pid, mask);
84218421
if (ret == 0) {
84228422
unsigned int retlen = min(len, cpumask_size());
84238423

8424-
if (copy_to_user(user_mask_ptr, mask, retlen))
8424+
if (copy_to_user(user_mask_ptr, cpumask_bits(mask), retlen))
84258425
ret = -EFAULT;
84268426
else
84278427
ret = retlen;

0 commit comments

Comments
 (0)