Patch "sched_getaffinity: don't assume 'cpumask_size()' is fully initialized" has been added to the 5.4-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    sched_getaffinity: don't assume 'cpumask_size()' is fully initialized

to the 5.4-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     sched_getaffinity-don-t-assume-cpumask_size-is-fully.patch
and it can be found in the queue-5.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 0de9b4c93a4167bade81a75eccece5ecf84abef8
Author: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
Date:   Tue Mar 14 19:32:38 2023 -0700

    sched_getaffinity: don't assume 'cpumask_size()' is fully initialized
    
    [ Upstream commit 6015b1aca1a233379625385feb01dd014aca60b5 ]
    
    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 <ryan.roberts@xxxxxxx>
    Link: https://lore.kernel.org/lkml/7d026744-6bd6-6827-0471-b5e8eae0be3f@xxxxxxx/
    Cc: Yury Norov <yury.norov@xxxxxxxxx>
    Signed-off-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/kernel/compat.c b/kernel/compat.c
index a2bc1d6ceb570..241516f326c04 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -240,7 +240,7 @@ COMPAT_SYSCALL_DEFINE3(sched_getaffinity, compat_pid_t,  pid, unsigned int, len,
 	if (len & (sizeof(compat_ulong_t)-1))
 		return -EINVAL;
 
-	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+	if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
 		return -ENOMEM;
 
 	ret = sched_getaffinity(pid, mask);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index d5765b7c92f79..51ac62637e4ed 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5661,14 +5661,14 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
 	if (len & (sizeof(unsigned long)-1))
 		return -EINVAL;
 
-	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+	if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
 		return -ENOMEM;
 
 	ret = sched_getaffinity(pid, mask);
 	if (ret == 0) {
 		unsigned int retlen = min(len, cpumask_size());
 
-		if (copy_to_user(user_mask_ptr, mask, retlen))
+		if (copy_to_user(user_mask_ptr, cpumask_bits(mask), retlen))
 			ret = -EFAULT;
 		else
 			ret = retlen;



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux