Skip to content

Commit

Permalink
Merge tag 'kvm-s390-master-4.4-1' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/kvms390/linux into kvm-master

KVM: s390: Fixes for 4.4

1. disallow changing the SIMD mode when CPUs have been created.
   it allowed userspace to corrupt kernel memory
2. Fix vCPU lookup. Until now the vCPU number equals the vCPU id. Some
   kernel code places relied on that. This might
   a: cause guest failures
   b: allow userspace to corrupt kernel memory
3. Fencing of the PFMF instruction should use the guest facilities
   and not the host facilities.
  • Loading branch information
Paolo Bonzini committed Nov 19, 2015
2 parents 62a193e + 152e9f6 commit d792aba
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 10 deletions.
7 changes: 5 additions & 2 deletions arch/s390/kvm/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1030,8 +1030,7 @@ static int __inject_extcall(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
src_id, 0);

/* sending vcpu invalid */
if (src_id >= KVM_MAX_VCPUS ||
kvm_get_vcpu(vcpu->kvm, src_id) == NULL)
if (kvm_get_vcpu_by_id(vcpu->kvm, src_id) == NULL)
return -EINVAL;

if (sclp.has_sigpif)
Expand Down Expand Up @@ -1110,6 +1109,10 @@ static int __inject_sigp_emergency(struct kvm_vcpu *vcpu,
trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_INT_EMERGENCY,
irq->u.emerg.code, 0);

/* sending vcpu invalid */
if (kvm_get_vcpu_by_id(vcpu->kvm, irq->u.emerg.code) == NULL)
return -EINVAL;

set_bit(irq->u.emerg.code, li->sigp_emerg_pending);
set_bit(IRQ_PEND_EXT_EMERGENCY, &li->pending_irqs);
atomic_or(CPUSTAT_EXT_INT, li->cpuflags);
Expand Down
6 changes: 5 additions & 1 deletion arch/s390/kvm/kvm-s390.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,12 +342,16 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
r = 0;
break;
case KVM_CAP_S390_VECTOR_REGISTERS:
if (MACHINE_HAS_VX) {
mutex_lock(&kvm->lock);
if (atomic_read(&kvm->online_vcpus)) {
r = -EBUSY;
} else if (MACHINE_HAS_VX) {
set_kvm_facility(kvm->arch.model.fac->mask, 129);
set_kvm_facility(kvm->arch.model.fac->list, 129);
r = 0;
} else
r = -EINVAL;
mutex_unlock(&kvm->lock);
VM_EVENT(kvm, 3, "ENABLE: CAP_S390_VECTOR_REGISTERS %s",
r ? "(not available)" : "(success)");
break;
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/kvm/priv.c
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)

kvm_s390_get_regs_rre(vcpu, &reg1, &reg2);

if (!MACHINE_HAS_PFMF)
if (!test_kvm_facility(vcpu->kvm, 8))
return kvm_s390_inject_program_int(vcpu, PGM_OPERATION);

if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
Expand Down
8 changes: 2 additions & 6 deletions arch/s390/kvm/sigp.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,8 @@ static int handle_sigp_dst(struct kvm_vcpu *vcpu, u8 order_code,
u16 cpu_addr, u32 parameter, u64 *status_reg)
{
int rc;
struct kvm_vcpu *dst_vcpu;
struct kvm_vcpu *dst_vcpu = kvm_get_vcpu_by_id(vcpu->kvm, cpu_addr);

if (cpu_addr >= KVM_MAX_VCPUS)
return SIGP_CC_NOT_OPERATIONAL;

dst_vcpu = kvm_get_vcpu(vcpu->kvm, cpu_addr);
if (!dst_vcpu)
return SIGP_CC_NOT_OPERATIONAL;

Expand Down Expand Up @@ -478,7 +474,7 @@ int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu)
trace_kvm_s390_handle_sigp_pei(vcpu, order_code, cpu_addr);

if (order_code == SIGP_EXTERNAL_CALL) {
dest_vcpu = kvm_get_vcpu(vcpu->kvm, cpu_addr);
dest_vcpu = kvm_get_vcpu_by_id(vcpu->kvm, cpu_addr);
BUG_ON(dest_vcpu == NULL);

kvm_s390_vcpu_wakeup(dest_vcpu);
Expand Down
11 changes: 11 additions & 0 deletions include/linux/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,17 @@ static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i)
(vcpup = kvm_get_vcpu(kvm, idx)) != NULL; \
idx++)

static inline struct kvm_vcpu *kvm_get_vcpu_by_id(struct kvm *kvm, int id)
{
struct kvm_vcpu *vcpu;
int i;

kvm_for_each_vcpu(i, vcpu, kvm)
if (vcpu->vcpu_id == id)
return vcpu;
return NULL;
}

#define kvm_for_each_memslot(memslot, slots) \
for (memslot = &slots->memslots[0]; \
memslot < slots->memslots + KVM_MEM_SLOTS_NUM && memslot->npages;\
Expand Down

0 comments on commit d792aba

Please sign in to comment.