From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.3 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, USER_AGENT_SANE_1 autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8C604C432C0 for ; Tue, 26 Nov 2019 18:18:45 +0000 (UTC) Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0841D20727 for ; Tue, 26 Nov 2019 18:18:44 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0841D20727 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=linuxppc-dev-bounces+linuxppc-dev=archiver.kernel.org@lists.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 47Msbj5FgqzDqZW for ; Wed, 27 Nov 2019 05:18:41 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=intel.com (client-ip=192.55.52.151; helo=mga17.intel.com; envelope-from=sean.j.christopherson@intel.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=intel.com Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 47MsVW30WGzDqMd for ; Wed, 27 Nov 2019 05:14:09 +1100 (AEDT) X-Amp-Result: UNKNOWN X-Amp-Original-Verdict: FILE UNKNOWN X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 Nov 2019 10:14:06 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.69,246,1571727600"; d="scan'208";a="211493575" Received: from sjchrist-coffee.jf.intel.com (HELO linux.intel.com) ([10.54.74.41]) by orsmga006.jf.intel.com with ESMTP; 26 Nov 2019 10:14:06 -0800 Date: Tue, 26 Nov 2019 10:14:06 -0800 From: Sean Christopherson To: Leonardo Bras Subject: Re: [PATCH 1/1] powerpc/kvm/book3s: Fixes possible 'use after release' of kvm Message-ID: <20191126181406.GC22233@linux.intel.com> References: <20191126175212.377171-1-leonardo@linux.ibm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20191126175212.377171-1-leonardo@linux.ibm.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kvm@vger.kernel.org, Radim =?utf-8?B?S3LEjW3DocWZ?= , linux-kernel@vger.kernel.org, kvm-ppc@vger.kernel.org, Paolo Bonzini , linuxppc-dev@lists.ozlabs.org Errors-To: linuxppc-dev-bounces+linuxppc-dev=archiver.kernel.org@lists.ozlabs.org Sender: "Linuxppc-dev" On Tue, Nov 26, 2019 at 02:52:12PM -0300, Leonardo Bras wrote: > Fixes a possible 'use after free' of kvm variable. > It does use mutex_unlock(&kvm->lock) after possible freeing a variable > with kvm_put_kvm(kvm). Moving the calls to kvm_put_kvm() to the end of the functions doesn't actually fix a use-after-free. In these flows, the reference being released is a borrowed reference that KVM takes on behalf of the entity it is creating, e.g. device, vcpu, or spapr tce. The caller of these create helpers must also hold its own reference to @kvm on top of the borrowed reference, i.e. these kvm_put_kvm() calls will never free @kvm (assuming there are no refcounting bugs elsewhere in KVM). If one these kvm_put_kvm() calls did unexpectedly free @kvm (due to a bug somewhere else), KVM would still hit a use-after-free scenario as the caller still thinks @kvm is valid. Currently, this would only happen on a subsequent ioctl() on the caller's file descriptor (which holds a pointer to @kvm), as the callers of these functions don't directly dereference @kvm after the functions return. But, not deferencing @kvm isn't deliberate or functionally required, it's just how the code happens to be written. The intent of adding kvm_put_kvm_no_destroy() was primarily to document that under no circumstance should the to-be-put reference be the *last* reference to @kvm. Moving the call to kvm_put_kvm{_no_destroy}() doesn't change that > Signed-off-by: Leonardo Bras > --- > arch/powerpc/kvm/book3s_64_vio.c | 3 +-- > virt/kvm/kvm_main.c | 8 ++++---- > 2 files changed, 5 insertions(+), 6 deletions(-) > > diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c > index 5834db0a54c6..a402ead833b6 100644 > --- a/arch/powerpc/kvm/book3s_64_vio.c > +++ b/arch/powerpc/kvm/book3s_64_vio.c > @@ -316,14 +316,13 @@ long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, > > if (ret >= 0) > list_add_rcu(&stt->list, &kvm->arch.spapr_tce_tables); > - else > - kvm_put_kvm(kvm); > > mutex_unlock(&kvm->lock); > > if (ret >= 0) > return ret; > > + kvm_put_kvm(kvm); > kfree(stt); > fail_acct: > account_locked_vm(current->mm, kvmppc_stt_pages(npages), false); > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c > index 13efc291b1c7..f37089b60d09 100644 > --- a/virt/kvm/kvm_main.c > +++ b/virt/kvm/kvm_main.c > @@ -2744,10 +2744,8 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id) > /* Now it's all set up, let userspace reach it */ > kvm_get_kvm(kvm); > r = create_vcpu_fd(vcpu); > - if (r < 0) { > - kvm_put_kvm(kvm); > + if (r < 0) > goto unlock_vcpu_destroy; > - } > > kvm->vcpus[atomic_read(&kvm->online_vcpus)] = vcpu; > > @@ -2771,6 +2769,8 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id) > mutex_lock(&kvm->lock); > kvm->created_vcpus--; > mutex_unlock(&kvm->lock); > + if (r < 0) > + kvm_put_kvm(kvm); > return r; > } > > @@ -3183,10 +3183,10 @@ static int kvm_ioctl_create_device(struct kvm *kvm, > kvm_get_kvm(kvm); > ret = anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR | O_CLOEXEC); > if (ret < 0) { > - kvm_put_kvm(kvm); > mutex_lock(&kvm->lock); > list_del(&dev->vm_node); > mutex_unlock(&kvm->lock); > + kvm_put_kvm(kvm); > ops->destroy(dev); > return ret; > } > -- > 2.23.0 >