diff options
author | Carsten Otte <carsteno@de.ibm.com> | 2009-11-30 11:14:41 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-12-03 02:32:26 -0500 |
commit | f50146bd7bdb75435638e60d4960edd9bcdf88b8 (patch) | |
tree | 5c52dfae9dc90d9ae9b07d87d63ca0f4704b0f4b /arch/s390/kvm/sigp.c | |
parent | 3548bab501887a698a887639b54d5ecaf35c387b (diff) |
KVM: s390: Fix prefix register checking in arch/s390/kvm/sigp.c
This patch corrects the checking of the new address for the prefix register.
On s390, the prefix register is used to address the cpu's lowcore (address
0...8k). This check is supposed to verify that the memory is readable and
present.
copy_from_guest is a helper function, that can be used to read from guest
memory. It applies prefixing, adds the start address of the guest memory in
user, and then calls copy_from_user. Previous code was obviously broken for
two reasons:
- prefixing should not be applied here. The current prefix register is
going to be updated soon, and the address we're looking for will be
0..8k after we've updated the register
- we're adding the guest origin (gmsor) twice: once in subject code
and once in copy_from_guest
With kuli, we did not hit this problem because (a) we were lucky with
previous prefix register content, and (b) our guest memory was mmaped
very low into user address space.
Cc: stable@kernel.org
Signed-off-by: Carsten Otte <cotte@de.ibm.com>
Reported-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/s390/kvm/sigp.c')
-rw-r--r-- | arch/s390/kvm/sigp.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index 40c8c6748cfe..15ee1111de58 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c | |||
@@ -188,9 +188,9 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, | |||
188 | 188 | ||
189 | /* make sure that the new value is valid memory */ | 189 | /* make sure that the new value is valid memory */ |
190 | address = address & 0x7fffe000u; | 190 | address = address & 0x7fffe000u; |
191 | if ((copy_from_guest(vcpu, &tmp, | 191 | if ((copy_from_user(&tmp, (void __user *) |
192 | (u64) (address + vcpu->arch.sie_block->gmsor) , 1)) || | 192 | (address + vcpu->arch.sie_block->gmsor) , 1)) || |
193 | (copy_from_guest(vcpu, &tmp, (u64) (address + | 193 | (copy_from_user(&tmp, (void __user *)(address + |
194 | vcpu->arch.sie_block->gmsor + PAGE_SIZE), 1))) { | 194 | vcpu->arch.sie_block->gmsor + PAGE_SIZE), 1))) { |
195 | *reg |= SIGP_STAT_INVALID_PARAMETER; | 195 | *reg |= SIGP_STAT_INVALID_PARAMETER; |
196 | return 1; /* invalid parameter */ | 196 | return 1; /* invalid parameter */ |