Message ID | 146116487861.14909.7528002102875279653.stgit@bahia.huguette.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Greg, On Wed, Apr 20, 2016 at 05:07:58PM +0200, Greg Kurz wrote: > Commit 338c7dbadd26 ("KVM: Improve create VCPU parameter (CVE-2013-4587)") > introduced a check to prevent potential kernel memory corruption in case > the vcpu id is too great. > > Unfortunately this check assumes vcpu ids grow in sequence with a common > difference of 1, which is wrong: archs are free to use vcpu id as they fit. > For example, QEMU originated vcpu ids for PowerPC cpus running in boot3s_hv > mode, can grow with a common difference of 2, 4 or 8: if KVM_MAX_VCPUS is > 1024, guests may be limited down to 128 vcpus on POWER8. > > This means the check does not belong here and should be moved to some arch > specific function: kvm_arch_vcpu_create() looks like a good candidate. > > ARM and s390 already have such a check. > > I could not spot any path in the PowerPC or common KVM code where a vcpu > id is used as described in the above commit: I believe PowerPC can live > without this check. > > In the end, this patch simply moves the check to MIPS and x86. > > Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com> > --- > arch/mips/kvm/mips.c | 3 +++ > arch/x86/kvm/x86.c | 3 +++ > virt/kvm/kvm_main.c | 3 --- > 3 files changed, 6 insertions(+), 3 deletions(-) > > diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c > index 70ef1a43c114..ce3f1e8a8b3f 100644 > --- a/arch/mips/kvm/mips.c > +++ b/arch/mips/kvm/mips.c > @@ -251,6 +251,9 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) > > struct kvm_vcpu *vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL); > > + if (id >= KVM_MAX_VCPUS) > + return -EINVAL; This needs to go before the kzalloc above, otherwise you introduce a memory leak. Cheers James > + > if (!vcpu) { > err = -ENOMEM; > goto out; > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 9b7798c7b210..f705d57b12ed 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -7358,6 +7358,9 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, > { > struct kvm_vcpu *vcpu; > > + if (id >= KVM_MAX_VCPUS) > + return -EINVAL; > + > if (check_tsc_unstable() && atomic_read(&kvm->online_vcpus) != 0) > printk_once(KERN_WARNING > "kvm: SMP vm created on host with unstable TSC; " > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c > index 4fd482fb9260..6b6cca3cb488 100644 > --- a/virt/kvm/kvm_main.c > +++ b/virt/kvm/kvm_main.c > @@ -2272,9 +2272,6 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id) > int r; > struct kvm_vcpu *vcpu; > > - if (id >= KVM_MAX_VCPUS) > - return -EINVAL; > - > vcpu = kvm_arch_vcpu_create(kvm, id); > if (IS_ERR(vcpu)) > return PTR_ERR(vcpu); >
Hi, [auto build test WARNING on kvm/linux-next] [also build test WARNING on v4.6-rc4 next-20160420] [if your patch is applied to the wrong git tree, please drop us a note to help improving the system] url: https://github.com/0day-ci/linux/commits/Greg-Kurz/KVM-remove-buggy-vcpu-id-check-on-vcpu-creation/20160420-231233 base: https://git.kernel.org/pub/scm/virt/kvm/kvm.git linux-next config: x86_64-randconfig-x017-201616 (attached as .config) reproduce: # save the attached .config to linux build tree make ARCH=x86_64 All warnings (new ones prefixed by >>): arch/x86/kvm/x86.c: In function 'kvm_arch_vcpu_create': >> arch/x86/kvm/x86.c:7362:10: warning: return makes pointer from integer without a cast [-Wint-conversion] return -EINVAL; ^ vim +7362 arch/x86/kvm/x86.c 7346 } 7347 7348 void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) 7349 { 7350 kvmclock_reset(vcpu); 7351 7352 free_cpumask_var(vcpu->arch.wbinvd_dirty_mask); 7353 kvm_x86_ops->vcpu_free(vcpu); 7354 } 7355 7356 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, 7357 unsigned int id) 7358 { 7359 struct kvm_vcpu *vcpu; 7360 7361 if (id >= KVM_MAX_VCPUS) > 7362 return -EINVAL; 7363 7364 if (check_tsc_unstable() && atomic_read(&kvm->online_vcpus) != 0) 7365 printk_once(KERN_WARNING 7366 "kvm: SMP vm created on host with unstable TSC; " 7367 "guest TSC will not be reliable\n"); 7368 7369 vcpu = kvm_x86_ops->vcpu_create(kvm, id); 7370 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
On Wed, 20 Apr 2016 16:12:46 +0100 James Hogan <james.hogan@imgtec.com> wrote: > Hi Greg, > > On Wed, Apr 20, 2016 at 05:07:58PM +0200, Greg Kurz wrote: > > Commit 338c7dbadd26 ("KVM: Improve create VCPU parameter (CVE-2013-4587)") > > introduced a check to prevent potential kernel memory corruption in case > > the vcpu id is too great. > > > > Unfortunately this check assumes vcpu ids grow in sequence with a common > > difference of 1, which is wrong: archs are free to use vcpu id as they fit. > > For example, QEMU originated vcpu ids for PowerPC cpus running in boot3s_hv > > mode, can grow with a common difference of 2, 4 or 8: if KVM_MAX_VCPUS is > > 1024, guests may be limited down to 128 vcpus on POWER8. > > > > This means the check does not belong here and should be moved to some arch > > specific function: kvm_arch_vcpu_create() looks like a good candidate. > > > > ARM and s390 already have such a check. > > > > I could not spot any path in the PowerPC or common KVM code where a vcpu > > id is used as described in the above commit: I believe PowerPC can live > > without this check. > > > > In the end, this patch simply moves the check to MIPS and x86. > > > > Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com> > > --- > > arch/mips/kvm/mips.c | 3 +++ > > arch/x86/kvm/x86.c | 3 +++ > > virt/kvm/kvm_main.c | 3 --- > > 3 files changed, 6 insertions(+), 3 deletions(-) > > > > diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c > > index 70ef1a43c114..ce3f1e8a8b3f 100644 > > --- a/arch/mips/kvm/mips.c > > +++ b/arch/mips/kvm/mips.c > > @@ -251,6 +251,9 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) > > > > struct kvm_vcpu *vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL); > > > > + if (id >= KVM_MAX_VCPUS) > > + return -EINVAL; > > This needs to go before the kzalloc above, otherwise you introduce a > memory leak. > Oops you're right.. my bad. I'll post a v2 right away. Thanks ! -- Greg > Cheers > James > > > + > > if (!vcpu) { > > err = -ENOMEM; > > goto out; > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > > index 9b7798c7b210..f705d57b12ed 100644 > > --- a/arch/x86/kvm/x86.c > > +++ b/arch/x86/kvm/x86.c > > @@ -7358,6 +7358,9 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, > > { > > struct kvm_vcpu *vcpu; > > > > + if (id >= KVM_MAX_VCPUS) > > + return -EINVAL; > > + > > if (check_tsc_unstable() && atomic_read(&kvm->online_vcpus) != 0) > > printk_once(KERN_WARNING > > "kvm: SMP vm created on host with unstable TSC; " > > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c > > index 4fd482fb9260..6b6cca3cb488 100644 > > --- a/virt/kvm/kvm_main.c > > +++ b/virt/kvm/kvm_main.c > > @@ -2272,9 +2272,6 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id) > > int r; > > struct kvm_vcpu *vcpu; > > > > - if (id >= KVM_MAX_VCPUS) > > - return -EINVAL; > > - > > vcpu = kvm_arch_vcpu_create(kvm, id); > > if (IS_ERR(vcpu)) > > return PTR_ERR(vcpu); > > -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c index 70ef1a43c114..ce3f1e8a8b3f 100644 --- a/arch/mips/kvm/mips.c +++ b/arch/mips/kvm/mips.c @@ -251,6 +251,9 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) struct kvm_vcpu *vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL); + if (id >= KVM_MAX_VCPUS) + return -EINVAL; + if (!vcpu) { err = -ENOMEM; goto out; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 9b7798c7b210..f705d57b12ed 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -7358,6 +7358,9 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, { struct kvm_vcpu *vcpu; + if (id >= KVM_MAX_VCPUS) + return -EINVAL; + if (check_tsc_unstable() && atomic_read(&kvm->online_vcpus) != 0) printk_once(KERN_WARNING "kvm: SMP vm created on host with unstable TSC; " diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 4fd482fb9260..6b6cca3cb488 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2272,9 +2272,6 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id) int r; struct kvm_vcpu *vcpu; - if (id >= KVM_MAX_VCPUS) - return -EINVAL; - vcpu = kvm_arch_vcpu_create(kvm, id); if (IS_ERR(vcpu)) return PTR_ERR(vcpu);
Commit 338c7dbadd26 ("KVM: Improve create VCPU parameter (CVE-2013-4587)") introduced a check to prevent potential kernel memory corruption in case the vcpu id is too great. Unfortunately this check assumes vcpu ids grow in sequence with a common difference of 1, which is wrong: archs are free to use vcpu id as they fit. For example, QEMU originated vcpu ids for PowerPC cpus running in boot3s_hv mode, can grow with a common difference of 2, 4 or 8: if KVM_MAX_VCPUS is 1024, guests may be limited down to 128 vcpus on POWER8. This means the check does not belong here and should be moved to some arch specific function: kvm_arch_vcpu_create() looks like a good candidate. ARM and s390 already have such a check. I could not spot any path in the PowerPC or common KVM code where a vcpu id is used as described in the above commit: I believe PowerPC can live without this check. In the end, this patch simply moves the check to MIPS and x86. Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com> --- arch/mips/kvm/mips.c | 3 +++ arch/x86/kvm/x86.c | 3 +++ virt/kvm/kvm_main.c | 3 --- 3 files changed, 6 insertions(+), 3 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html