Received: by 2002:a05:6a10:f347:0:0:0:0 with SMTP id d7csp13951948pxu; Mon, 4 Jan 2021 08:49:38 -0800 (PST) X-Google-Smtp-Source: ABdhPJxHN6JTkuk8CcXerzdu3llPAU1GSKOFCbHSc4vxxLhPHhf/PvxNulyRs+Tr7+bPwX/WzeRm X-Received: by 2002:a50:b765:: with SMTP id g92mr71627481ede.317.1609778978559; Mon, 04 Jan 2021 08:49:38 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1609778978; cv=none; d=google.com; s=arc-20160816; b=ONICG0wJDufD3fXCbZvFHHPNRdPcDRkrKPhd5dMf70uuRHyG8EqvROq0XKB0CcKwCK 9Bf5k1xFUweovj3PhurMCPrLp2AiRlFf/EiJasb5vrOs0w26Qn9Wng3Nt8JdV49XebLw WTGkj/Qn6ykfaNoqwrIU08TAQhC7MRWa2jspfatvlg6XxY/ETZHbgEi6lDPUUc6azDfY Ecwf5MLPJigI0VuP55bT19tvSMAMHTEDd8hIcqp7vvVmiIqy8Q4Kz9pspBhU/IgcjOCi mNf5OZSNuUyRkRwjFeUTYuXoquTU8m3T0mhi7aHbs7Ue9rcG38bwInulw5aB6R56R+QQ X7ZA== 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=Tt7CEB0QqgIM5mFuOAJ2NW8UfHrQ8ea3Ryiq74Twu0M=; b=nsUTg3ikWYPkDXAliFd8gZZBGSusBhN9HR5q9pb7C5Ukno3WX8es8ftgurtK6Eewsx PwZklVrRNY0OP1K9gkXeIKGhapAHQ45HHE9QuxZpWEqyIQaA3Q8LgySPbzlpuAoDdLAg mksFesaPM/q5Oq7TeykI/M63aDSt1uMf5Gei+QZaxGaBavExm3oDcTe9B9LraAe7eulz RN4Yo2+ff0QdS8bEqzK43/7MNJ0AzWQ4H9SO4QlN7/IvymWMo2JnaOwkSFuIxE5Ic0DJ Uhpw3e1OSLI4SbXecItt2ADth6KV5HFqThMeBm+Fcc93DxjOh1X2zNkRpPifj1JX0ows x1nA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=elVDUO9z; 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 x2si28729483ejc.177.2021.01.04.08.49.14; Mon, 04 Jan 2021 08:49:38 -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=elVDUO9z; 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 S1728589AbhADQB3 (ORCPT + 99 others); Mon, 4 Jan 2021 11:01:29 -0500 Received: from mail.kernel.org ([198.145.29.99]:38732 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728576AbhADQBZ (ORCPT ); Mon, 4 Jan 2021 11:01:25 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 684C922522; Mon, 4 Jan 2021 16:00:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1609776044; bh=zalySSx7DbzBGWtwr3ORW40jKfdlWX2z7z2fB+j1pO0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=elVDUO9zRy+BCiO/2WEhLek4Th2sBr0MoYYxhGmjjEwSZ9/0H80V3PEZe/OORK4nL bR63xLGMUzHtsQMfr3Zxo0FLGmpqFcn8yDL5yzH1E6+7170jQfcCjTSuCI4pkMyVPT 1xhsKMLOLDl9/Z+7jkP3SmCX5yoCOEcVFVTPdGDU= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Miklos Szeredi , Eric Biggers , Al Viro , Sasha Levin Subject: [PATCH 5.4 43/47] fs/namespace.c: WARN if mnt_count has become negative Date: Mon, 4 Jan 2021 16:57:42 +0100 Message-Id: <20210104155707.809306684@linuxfoundation.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210104155705.740576914@linuxfoundation.org> References: <20210104155705.740576914@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: Eric Biggers [ Upstream commit edf7ddbf1c5eb98b720b063b73e20e8a4a1ce673 ] Missing calls to mntget() (or equivalently, too many calls to mntput()) are hard to detect because mntput() delays freeing mounts using task_work_add(), then again using call_rcu(). As a result, mnt_count can often be decremented to -1 without getting a KASAN use-after-free report. Such cases are still bugs though, and they point to real use-after-frees being possible. For an example of this, see the bug fixed by commit 1b0b9cc8d379 ("vfs: fsmount: add missing mntget()"), discussed at https://lkml.kernel.org/linux-fsdevel/20190605135401.GB30925@xxxxxxxxxxxxxxxxxxxxxxxxx/T/#u. This bug *should* have been trivial to find. But actually, it wasn't found until syzkaller happened to use fchdir() to manipulate the reference count just right for the bug to be noticeable. Address this by making mntput_no_expire() issue a WARN if mnt_count has become negative. Suggested-by: Miklos Szeredi Signed-off-by: Eric Biggers Signed-off-by: Al Viro Signed-off-by: Sasha Levin --- fs/namespace.c | 9 ++++++--- fs/pnode.h | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 2adfe7b166a3e..76ea92994d26d 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -156,10 +156,10 @@ static inline void mnt_add_count(struct mount *mnt, int n) /* * vfsmount lock must be held for write */ -unsigned int mnt_get_count(struct mount *mnt) +int mnt_get_count(struct mount *mnt) { #ifdef CONFIG_SMP - unsigned int count = 0; + int count = 0; int cpu; for_each_possible_cpu(cpu) { @@ -1123,6 +1123,7 @@ static DECLARE_DELAYED_WORK(delayed_mntput_work, delayed_mntput); static void mntput_no_expire(struct mount *mnt) { LIST_HEAD(list); + int count; rcu_read_lock(); if (likely(READ_ONCE(mnt->mnt_ns))) { @@ -1146,7 +1147,9 @@ static void mntput_no_expire(struct mount *mnt) */ smp_mb(); mnt_add_count(mnt, -1); - if (mnt_get_count(mnt)) { + count = mnt_get_count(mnt); + if (count != 0) { + WARN_ON(count < 0); rcu_read_unlock(); unlock_mount_hash(); return; diff --git a/fs/pnode.h b/fs/pnode.h index 49a058c73e4c7..26f74e092bd98 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -44,7 +44,7 @@ int propagate_mount_busy(struct mount *, int); void propagate_mount_unlock(struct mount *); void mnt_release_group_id(struct mount *); int get_dominating_id(struct mount *mnt, const struct path *root); -unsigned int mnt_get_count(struct mount *mnt); +int mnt_get_count(struct mount *mnt); void mnt_set_mountpoint(struct mount *, struct mountpoint *, struct mount *); void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp, -- 2.27.0