Received: by 2002:a05:6a10:f347:0:0:0:0 with SMTP id d7csp407890pxu; Tue, 1 Dec 2020 14:30:40 -0800 (PST) X-Google-Smtp-Source: ABdhPJwp2AsHqtpgRDraNVe7PBBtP1FNAUCTJCpkwrK6DOyzGwk82Os9zpEpHEmikqhhNk97YNNz X-Received: by 2002:a50:b264:: with SMTP id o91mr5332401edd.7.1606861840043; Tue, 01 Dec 2020 14:30:40 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1606861840; cv=none; d=google.com; s=arc-20160816; b=pwMaOgA7PQ+cehDMzrM1n4qeFkZax8SZaeJWJxtuSGqaqnMQHcda0xkRTp6QAsDMFu kJwKs/ijTnZit/UrNLHnzTBgQO+LIk5J7fuN/3E2adf3Q1DUitgjujctk8oePGAoT3QE IG74nn74543zywrcFcewBnw/y9di8tcyG/ukB6s+6/iKFxWPARQOS+7x3w8hRSMKoDDe tgZqdr0L5IEYjVaP4K5p7yBpURV3Ya3Mi4E7cuuY8JEYvDv8drYF+vF8n0AMV+5kqjRf KSDJgX9hC/A9S3nH1h6NV44pVEEWMS0MCK3DMPJXMZYc2HJblnNMzncaaz40wY25V8rA EiTA== 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=2sEDTe8nABu3PJKRhU0W8BxmR23Yzq7BU0UjSbKY51s=; b=Ku7fgB0J8ZMFooqB8FXWyYFIIFR/aDaZGmPVHLPtDQ2gAGkx2w+c6S7U3QMLd550lq 9xEWqGjB4lD/HSSPmPpQOCwMrochtt1ocbsKrDt1PINWEyJHShu3IKw6LhXSVx/UvpZs Yfb7z3ikFrSC0jlM7bhtcmOnO2l2lbbtKew7IcIuBSq5k5LOxfZbSYwi9ROwzfVYMqeq 4ja84yzcOSE6Z7z5yHZB80Y5Ej6jJC9SdbjhQKI5/sfMBd9xz24LPbCzgBUItZTgkSeE Z3iznw8eXt9flIG2cYCLtLFT/muGVLT6XjE9B9oCGXXHgosOsY/8vCSZg8igweGXXEDQ I4sw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=pTGKDNfl; 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 c23si832708edt.456.2020.12.01.14.30.17; Tue, 01 Dec 2020 14:30:40 -0800 (PST) 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=pTGKDNfl; 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 S1729271AbgLAJPW (ORCPT + 99 others); Tue, 1 Dec 2020 04:15:22 -0500 Received: from mail.kernel.org ([198.145.29.99]:53772 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390367AbgLAJOz (ORCPT ); Tue, 1 Dec 2020 04:14:55 -0500 Received: from localhost (83-86-74-64.cable.dynamic.v4.ziggo.nl [83.86.74.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 10BA8221FD; Tue, 1 Dec 2020 09:14:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1606814054; bh=LhfZG3xHXZPNbZFuaekbwLOjaC7JiiaJPt/xc2EHxzM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pTGKDNfllSlFFbZzir5opj7eBxcx0OL3InSCf2x5DW3zVw4OuiUm4VTYnVJNONyAb UbWKILZkBns8hepP4ITFVr55N2h/tbD2LaNGmkRPegQw2YtBCJ4p5VgsG0eNGA9vQO 7Jr8zFM/mzKU5KfE3SQTvHetBHvPLJEHgT6jtj6U= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Willem de Bruijn , Xiaochen Shen , Borislav Petkov , Reinette Chatre Subject: [PATCH 5.9 151/152] x86/resctrl: Add necessary kernfs_put() calls to prevent refcount leak Date: Tue, 1 Dec 2020 09:54:26 +0100 Message-Id: <20201201084731.638470131@linuxfoundation.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201201084711.707195422@linuxfoundation.org> References: <20201201084711.707195422@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: Xiaochen Shen commit 758999246965eeb8b253d47e72f7bfe508804b16 upstream. On resource group creation via a mkdir an extra kernfs_node reference is obtained by kernfs_get() to ensure that the rdtgroup structure remains accessible for the rdtgroup_kn_unlock() calls where it is removed on deletion. Currently the extra kernfs_node reference count is only dropped by kernfs_put() in rdtgroup_kn_unlock() while the rdtgroup structure is removed in a few other locations that lack the matching reference drop. In call paths of rmdir and umount, when a control group is removed, kernfs_remove() is called to remove the whole kernfs nodes tree of the control group (including the kernfs nodes trees of all child monitoring groups), and then rdtgroup structure is freed by kfree(). The rdtgroup structures of all child monitoring groups under the control group are freed by kfree() in free_all_child_rdtgrp(). Before calling kfree() to free the rdtgroup structures, the kernfs node of the control group itself as well as the kernfs nodes of all child monitoring groups still take the extra references which will never be dropped to 0 and the kernfs nodes will never be freed. It leads to reference count leak and kernfs_node_cache memory leak. For example, reference count leak is observed in these two cases: (1) mount -t resctrl resctrl /sys/fs/resctrl mkdir /sys/fs/resctrl/c1 mkdir /sys/fs/resctrl/c1/mon_groups/m1 umount /sys/fs/resctrl (2) mkdir /sys/fs/resctrl/c1 mkdir /sys/fs/resctrl/c1/mon_groups/m1 rmdir /sys/fs/resctrl/c1 The same reference count leak issue also exists in the error exit paths of mkdir in mkdir_rdt_prepare() and rdtgroup_mkdir_ctrl_mon(). Fix this issue by following changes to make sure the extra kernfs_node reference on rdtgroup is dropped before freeing the rdtgroup structure. (1) Introduce rdtgroup removal helper rdtgroup_remove() to wrap up kernfs_put() and kfree(). (2) Call rdtgroup_remove() in rdtgroup removal path where the rdtgroup structure is about to be freed by kfree(). (3) Call rdtgroup_remove() or kernfs_put() as appropriate in the error exit paths of mkdir where an extra reference is taken by kernfs_get(). Fixes: f3cbeacaa06e ("x86/intel_rdt/cqm: Add rmdir support") Fixes: e02737d5b826 ("x86/intel_rdt: Add tasks files") Fixes: 60cf5e101fd4 ("x86/intel_rdt: Add mkdir to resctrl file system") Reported-by: Willem de Bruijn Signed-off-by: Xiaochen Shen Signed-off-by: Borislav Petkov Reviewed-by: Reinette Chatre Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/1604085088-31707-1-git-send-email-xiaochen.shen@intel.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/resctrl/rdtgroup.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) --- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c +++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c @@ -507,6 +507,24 @@ unlock: return ret ?: nbytes; } +/** + * rdtgroup_remove - the helper to remove resource group safely + * @rdtgrp: resource group to remove + * + * On resource group creation via a mkdir, an extra kernfs_node reference is + * taken to ensure that the rdtgroup structure remains accessible for the + * rdtgroup_kn_unlock() calls where it is removed. + * + * Drop the extra reference here, then free the rdtgroup structure. + * + * Return: void + */ +static void rdtgroup_remove(struct rdtgroup *rdtgrp) +{ + kernfs_put(rdtgrp->kn); + kfree(rdtgrp); +} + struct task_move_callback { struct callback_head work; struct rdtgroup *rdtgrp; @@ -529,7 +547,7 @@ static void move_myself(struct callback_ (rdtgrp->flags & RDT_DELETED)) { current->closid = 0; current->rmid = 0; - kfree(rdtgrp); + rdtgroup_remove(rdtgrp); } if (unlikely(current->flags & PF_EXITING)) @@ -2004,8 +2022,7 @@ void rdtgroup_kn_unlock(struct kernfs_no rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) rdtgroup_pseudo_lock_remove(rdtgrp); kernfs_unbreak_active_protection(kn); - kernfs_put(rdtgrp->kn); - kfree(rdtgrp); + rdtgroup_remove(rdtgrp); } else { kernfs_unbreak_active_protection(kn); } @@ -2292,7 +2309,7 @@ static void free_all_child_rdtgrp(struct if (atomic_read(&sentry->waitcount) != 0) sentry->flags = RDT_DELETED; else - kfree(sentry); + rdtgroup_remove(sentry); } } @@ -2334,7 +2351,7 @@ static void rmdir_all_sub(void) if (atomic_read(&rdtgrp->waitcount) != 0) rdtgrp->flags = RDT_DELETED; else - kfree(rdtgrp); + rdtgroup_remove(rdtgrp); } /* Notify online CPUs to update per cpu storage and PQR_ASSOC MSR */ update_closid_rmid(cpu_online_mask, &rdtgroup_default); @@ -2769,7 +2786,7 @@ static int mkdir_rdt_prepare(struct kern * kernfs_remove() will drop the reference count on "kn" which * will free it. But we still need it to stick around for the * rdtgroup_kn_unlock(kn) call. Take one extra reference here, - * which will be dropped inside rdtgroup_kn_unlock(). + * which will be dropped by kernfs_put() in rdtgroup_remove(). */ kernfs_get(kn); @@ -2810,6 +2827,7 @@ static int mkdir_rdt_prepare(struct kern out_idfree: free_rmid(rdtgrp->mon.rmid); out_destroy: + kernfs_put(rdtgrp->kn); kernfs_remove(rdtgrp->kn); out_free_rgrp: kfree(rdtgrp); @@ -2822,7 +2840,7 @@ static void mkdir_rdt_prepare_clean(stru { kernfs_remove(rgrp->kn); free_rmid(rgrp->mon.rmid); - kfree(rgrp); + rdtgroup_remove(rgrp); } /*