Received: by 2002:a05:6a10:c604:0:0:0:0 with SMTP id y4csp3762279pxt; Tue, 10 Aug 2021 10:43:45 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxECrKwxvgSsAzdaCBwrsuladbYQzutgAs9UM2zBdIKQR+MANcmNkY2hRTGsLipZbiDy60P X-Received: by 2002:a05:6402:280e:: with SMTP id h14mr6304108ede.187.1628617424846; Tue, 10 Aug 2021 10:43:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1628617424; cv=none; d=google.com; s=arc-20160816; b=UGboYOoyu4x67DqzBZhPcbDRJWtUypxEdtednK35xAF3B6ugDMrOp6AUVjMvfb6Mc4 Hs9WiDwqW8FNe/c/BCFCfjK1ejA3IYmPzWjv68eruuF8mwKgzmjm7jyFWUPQYXko4D3B sdG3EJmm/EaddBH1k0JxeQ4YdpfON1qL/Y2bDfu/IUhE0Xme/p7QUJ8WETv0KpVB+oak weeQT6UzPzF7DaxZ6xBmL+bi8NfjXz4vKxOsz/JUNLxTyCBtKGYgUnhcUFuHqWd9IYKB H47HTFrvlwvCrnbg9fczbvWjPideYGd5J0b2C7oGh3LtmA1MQdiPN3Yp9X1pzrCMr9HP 8xuA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=hutaGgbtn3lY451UXUKkAErWoAm9aA9UfYE8cASPoKE=; b=qe6n4lrPBsp+axT03s3nKDSR6lgp3aJKdq1GmEsALNgoAoc9knXeCQU2EbNFLoWkVx 3GIESHDww32nGQxFAP7z+d2DFkmot8qiWoeTQy5osiHva8qIcJlkOQ1rCdoQBYxEvHnn H2PfO8jrd5r4LJMdnOmAj80Awq5dhoBmAUm3p/IO7o2IXCTpHMJTB6k7yeSAZtLNEY+z Pz32FujfjTy+qId2tMUzjmeaSoVbys8Jyv1+pNQuZ18eSrHnqb/a8OXeoJL1CF59EZGU esfRJiJ0SZrY6A2naEhaGzredFLlzOrFvOJrOnQhJACooLt4AOGaLwG8WYmWj25KmFO/ nvMQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=JFUKstZi; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id j11si20350207ejc.265.2021.08.10.10.43.20; Tue, 10 Aug 2021 10:43:44 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=JFUKstZi; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234213AbhHJRkA (ORCPT + 99 others); Tue, 10 Aug 2021 13:40:00 -0400 Received: from mail.kernel.org ([198.145.29.99]:35348 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233715AbhHJRhf (ORCPT ); Tue, 10 Aug 2021 13:37:35 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 2A92C60F11; Tue, 10 Aug 2021 17:36:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1628616966; bh=Vp727FYbvVTJmQTjmUT3YYRd/B/lgEGQLoRJdbtCGGk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JFUKstZiFqimqK4zylHdQBG++Q8JtqEwtSTjomN46g/jTqODCCCYJ6hnSBZ7eSJYw E1GmM43L6OU2FI/E3ChsObB2MyLwLlF4ze49aHvyGNDM6hr1NDPGLm1rjKUnykHfdx ICBnVE8n5ya2IiwxZDI6WFZ3AL7JkoZZ+Qi7cTGQ= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Alexey Kardashevskiy , Paolo Bonzini Subject: [PATCH 5.4 71/85] KVM: Do not leak memory for duplicate debugfs directories Date: Tue, 10 Aug 2021 19:30:44 +0200 Message-Id: <20210810172950.639666479@linuxfoundation.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210810172948.192298392@linuxfoundation.org> References: <20210810172948.192298392@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Paolo Bonzini commit 85cd39af14f498f791d8aab3fbd64cd175787f1a upstream. KVM creates a debugfs directory for each VM in order to store statistics about the virtual machine. The directory name is built from the process pid and a VM fd. While generally unique, it is possible to keep a file descriptor alive in a way that causes duplicate directories, which manifests as these messages: [ 471.846235] debugfs: Directory '20245-4' with parent 'kvm' already present! Even though this should not happen in practice, it is more or less expected in the case of KVM for testcases that call KVM_CREATE_VM and close the resulting file descriptor repeatedly and in parallel. When this happens, debugfs_create_dir() returns an error but kvm_create_vm_debugfs() goes on to allocate stat data structs which are later leaked. The slow memory leak was spotted by syzkaller, where it caused OOM reports. Since the issue only affects debugfs, do a lookup before calling debugfs_create_dir, so that the message is downgraded and rate-limited. While at it, ensure kvm->debugfs_dentry is NULL rather than an error if it is not created. This fixes kvm_destroy_vm_debugfs, which was not checking IS_ERR_OR_NULL correctly. Cc: stable@vger.kernel.org Fixes: 536a6f88c49d ("KVM: Create debugfs dir and stat files for each VM") Reported-by: Alexey Kardashevskiy Suggested-by: Greg Kroah-Hartman Acked-by: Greg Kroah-Hartman Signed-off-by: Paolo Bonzini Signed-off-by: Greg Kroah-Hartman --- virt/kvm/kvm_main.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -635,6 +635,8 @@ static void kvm_destroy_vm_debugfs(struc static int kvm_create_vm_debugfs(struct kvm *kvm, int fd) { + static DEFINE_MUTEX(kvm_debugfs_lock); + struct dentry *dent; char dir_name[ITOA_MAX_LEN * 2]; struct kvm_stat_data *stat_data; struct kvm_stats_debugfs_item *p; @@ -643,8 +645,20 @@ static int kvm_create_vm_debugfs(struct return 0; snprintf(dir_name, sizeof(dir_name), "%d-%d", task_pid_nr(current), fd); - kvm->debugfs_dentry = debugfs_create_dir(dir_name, kvm_debugfs_dir); + mutex_lock(&kvm_debugfs_lock); + dent = debugfs_lookup(dir_name, kvm_debugfs_dir); + if (dent) { + pr_warn_ratelimited("KVM: debugfs: duplicate directory %s\n", dir_name); + dput(dent); + mutex_unlock(&kvm_debugfs_lock); + return 0; + } + dent = debugfs_create_dir(dir_name, kvm_debugfs_dir); + mutex_unlock(&kvm_debugfs_lock); + if (IS_ERR(dent)) + return 0; + kvm->debugfs_dentry = dent; kvm->debugfs_stat_data = kcalloc(kvm_debugfs_num_entries, sizeof(*kvm->debugfs_stat_data), GFP_KERNEL_ACCOUNT); @@ -4367,7 +4381,7 @@ static void kvm_uevent_notify_change(uns } add_uevent_var(env, "PID=%d", kvm->userspace_pid); - if (!IS_ERR_OR_NULL(kvm->debugfs_dentry)) { + if (kvm->debugfs_dentry) { char *tmp, *p = kmalloc(PATH_MAX, GFP_KERNEL_ACCOUNT); if (p) {