Skip to content

Commit d8d5b7b

Browse files
Denis ArefevFrederic Weisbecker
authored andcommitted
srcu: Fix srcu_struct node grpmask overflow on 64-bit systems
The value of a bitwise expression 1 << (cpu - sdp->mynode->grplo) is subject to overflow due to a failure to cast operands to a larger data type before performing the bitwise operation. The maximum result of this subtraction is defined by the RCU_FANOUT_LEAF Kconfig option, which on 64-bit systems defaults to 16 (resulting in a maximum shift of 15), but which can be set up as high as 64 (resulting in a maximum shift of 63). A value of 31 can result in sign extension, resulting in 0xffffffff80000000 instead of the desired 0x80000000. A value of 32 or greater triggers undefined behavior per the C standard. This bug has not been known to cause issues because almost all kernels take the default CONFIG_RCU_FANOUT_LEAF=16. Furthermore, as long as a given compiler gives a deterministic non-zero result for 1<<N for N>=32, the code correctly invokes all SRCU callbacks, albeit wasting CPU time along the way. This commit therefore substitutes the correct 1UL for the buggy 1. Found by Linux Verification Center (linuxtesting.org) with SVACE. Signed-off-by: Denis Arefev <[email protected]> Reviewed-by: Mathieu Desnoyers <[email protected]> Reviewed-by: Joel Fernandes (Google) <[email protected]> Cc: David Laight <[email protected]> Signed-off-by: Paul E. McKenney <[email protected]> Signed-off-by: Frederic Weisbecker <[email protected]>
1 parent 0ae9942 commit d8d5b7b

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

kernel/rcu/srcutree.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ static bool init_srcu_struct_nodes(struct srcu_struct *ssp, gfp_t gfp_flags)
223223
snp->grplo = cpu;
224224
snp->grphi = cpu;
225225
}
226-
sdp->grpmask = 1 << (cpu - sdp->mynode->grplo);
226+
sdp->grpmask = 1UL << (cpu - sdp->mynode->grplo);
227227
}
228228
smp_store_release(&ssp->srcu_sup->srcu_size_state, SRCU_SIZE_WAIT_BARRIER);
229229
return true;
@@ -835,7 +835,7 @@ static void srcu_schedule_cbs_snp(struct srcu_struct *ssp, struct srcu_node *snp
835835
int cpu;
836836

837837
for (cpu = snp->grplo; cpu <= snp->grphi; cpu++) {
838-
if (!(mask & (1 << (cpu - snp->grplo))))
838+
if (!(mask & (1UL << (cpu - snp->grplo))))
839839
continue;
840840
srcu_schedule_cbs_sdp(per_cpu_ptr(ssp->sda, cpu), delay);
841841
}

0 commit comments

Comments
 (0)