Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: s390/diag: fix racy access of physical cpu number in diag 9c handler

We do check for target CPU == -1, but this might change at the time we
are going to use it. Hold the physical target CPU in a local variable to
avoid out-of-bound accesses to the cpu arrays.

Cc: Pierre Morel <pmorel@linux.ibm.com>
Fixes: 87e28a15c42c ("KVM: s390: diag9c (directed yield) forwarding")
Reported-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Nico Boehr <nrb@linux.ibm.com>
Reviewed-by: Pierre Morel <pmorel@linux.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>

authored by

Christian Borntraeger and committed by
Janosch Frank
0bc380be 246be7d2

+5 -3
+5 -3
arch/s390/kvm/diag.c
··· 166 166 static int __diag_time_slice_end_directed(struct kvm_vcpu *vcpu) 167 167 { 168 168 struct kvm_vcpu *tcpu; 169 + int tcpu_cpu; 169 170 int tid; 170 171 171 172 tid = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4]; ··· 182 181 goto no_yield; 183 182 184 183 /* target guest VCPU already running */ 185 - if (READ_ONCE(tcpu->cpu) >= 0) { 184 + tcpu_cpu = READ_ONCE(tcpu->cpu); 185 + if (tcpu_cpu >= 0) { 186 186 if (!diag9c_forwarding_hz || diag9c_forwarding_overrun()) 187 187 goto no_yield; 188 188 189 189 /* target host CPU already running */ 190 - if (!vcpu_is_preempted(tcpu->cpu)) 190 + if (!vcpu_is_preempted(tcpu_cpu)) 191 191 goto no_yield; 192 - smp_yield_cpu(tcpu->cpu); 192 + smp_yield_cpu(tcpu_cpu); 193 193 VCPU_EVENT(vcpu, 5, 194 194 "diag time slice end directed to %d: yield forwarded", 195 195 tid);