From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
stable@vger.kernel.org, Jann Horn <jannh@google.com>,
Al Viro <viro@zeniv.linux.org.uk>
Subject: [PATCH 4.4 11/43] fix mntput/mntput race
Date: Tue, 14 Aug 2018 19:17:47 +0200 [thread overview]
Message-ID: <20180814171517.835654211@linuxfoundation.org> (raw)
In-Reply-To: <20180814171517.014285600@linuxfoundation.org>
4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <viro@zeniv.linux.org.uk>
commit 9ea0a46ca2c318fcc449c1e6b62a7230a17888f1 upstream.
mntput_no_expire() does the calculation of total refcount under mount_lock;
unfortunately, the decrement (as well as all increments) are done outside
of it, leading to false positives in the "are we dropping the last reference"
test. Consider the following situation:
* mnt is a lazy-umounted mount, kept alive by two opened files. One
of those files gets closed. Total refcount of mnt is 2. On CPU 42
mntput(mnt) (called from __fput()) drops one reference, decrementing component
* After it has looked at component #0, the process on CPU 0 does
mntget(), incrementing component #0, gets preempted and gets to run again -
on CPU 69. There it does mntput(), which drops the reference (component #69)
and proceeds to spin on mount_lock.
* On CPU 42 our first mntput() finishes counting. It observes the
decrement of component #69, but not the increment of component #0. As the
result, the total it gets is not 1 as it should've been - it's 0. At which
point we decide that vfsmount needs to be killed and proceed to free it and
shut the filesystem down. However, there's still another opened file
on that filesystem, with reference to (now freed) vfsmount, etc. and we are
screwed.
It's not a wide race, but it can be reproduced with artificial slowdown of
the mnt_get_count() loop, and it should be easier to hit on SMP KVM setups.
Fix consists of moving the refcount decrement under mount_lock; the tricky
part is that we want (and can) keep the fast case (i.e. mount that still
has non-NULL ->mnt_ns) entirely out of mount_lock. All places that zero
mnt->mnt_ns are dropping some reference to mnt and they call synchronize_rcu()
before that mntput(). IOW, if mntput() observes (under rcu_read_lock())
a non-NULL ->mnt_ns, it is guaranteed that there is another reference yet to
be dropped.
Reported-by: Jann Horn <jannh@google.com>
Tested-by: Jann Horn <jannh@google.com>
Fixes: 48a066e72d97 ("RCU'd vsfmounts")
Cc: stable@vger.kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/namespace.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1124,12 +1124,22 @@ static DECLARE_DELAYED_WORK(delayed_mntp
static void mntput_no_expire(struct mount *mnt)
{
rcu_read_lock();
- mnt_add_count(mnt, -1);
- if (likely(mnt->mnt_ns)) { /* shouldn't be the last one */
+ if (likely(READ_ONCE(mnt->mnt_ns))) {
+ /*
+ * Since we don't do lock_mount_hash() here,
+ * ->mnt_ns can change under us. However, if it's
+ * non-NULL, then there's a reference that won't
+ * be dropped until after an RCU delay done after
+ * turning ->mnt_ns NULL. So if we observe it
+ * non-NULL under rcu_read_lock(), the reference
+ * we are dropping is not the final one.
+ */
+ mnt_add_count(mnt, -1);
rcu_read_unlock();
return;
}
lock_mount_hash();
+ mnt_add_count(mnt, -1);
if (mnt_get_count(mnt)) {
rcu_read_unlock();
unlock_mount_hash();
next prev parent reply other threads:[~2018-08-14 17:17 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-08-14 17:17 [PATCH 4.4 00/43] 4.4.148-stable review Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 01/43] ext4: fix check to prevent initializing reserved inodes Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 02/43] tpm: fix race condition in tpm_common_write() Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 03/43] ipv4+ipv6: Make INET*_ESP select CRYPTO_ECHAINIV Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 04/43] fork: unconditionally clear stack on fork Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 05/43] parisc: Enable CONFIG_MLONGCALLS by default Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 07/43] xen/netfront: dont cache skb_shinfo() Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 08/43] ACPI / LPSS: Add missing prv_offset setting for byt/cht PWM devices Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 09/43] scsi: sr: Avoid that opening a CD-ROM hangs with runtime power management enabled Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 10/43] root dentries need RCU-delayed freeing Greg Kroah-Hartman
2018-08-14 17:17 ` Greg Kroah-Hartman [this message]
2018-08-14 17:17 ` [PATCH 4.4 12/43] fix __legitimize_mnt()/mntput() race Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 13/43] IB/core: Make testing MR flags for writability a static inline function Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 14/43] IB/mlx4: Mark user MR as writable if actual virtual memory is writable Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 15/43] IB/ocrdma: fix out of bounds access to local buffer Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 16/43] ARM: dts: imx6sx: fix irq for pcie bridge Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 17/43] x86/paravirt: Fix spectre-v2 mitigations for paravirt guests Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 18/43] x86/speculation: Protect against userspace-userspace spectreRSB Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 19/43] kprobes/x86: Fix %p uses in error messages Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 20/43] x86/irqflags: Provide a declaration for native_save_fl Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 21/43] x86/speculation/l1tf: Increase 32bit PAE __PHYSICAL_PAGE_SHIFT Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 22/43] x86/mm: Move swap offset/type up in PTE to work around erratum Greg Kroah-Hartman
2018-08-14 17:17 ` [PATCH 4.4 23/43] x86/mm: Fix swap entry comment and macro Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 24/43] mm: x86: move _PAGE_SWP_SOFT_DIRTY from bit 7 to bit 1 Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 25/43] x86/speculation/l1tf: Change order of offset/type in swap entry Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 26/43] x86/speculation/l1tf: Protect swap entries against L1TF Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 27/43] x86/speculation/l1tf: Protect PROT_NONE PTEs against speculation Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 28/43] x86/speculation/l1tf: Make sure the first page is always reserved Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 29/43] x86/speculation/l1tf: Add sysfs reporting for l1tf Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 30/43] mm: Add vm_insert_pfn_prot() Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 31/43] mm: fix cache mode tracking in vm_insert_mixed() Greg Kroah-Hartman
2018-09-07 17:05 ` Ben Hutchings
2018-09-07 20:03 ` Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 32/43] x86/speculation/l1tf: Disallow non privileged high MMIO PROT_NONE mappings Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 33/43] x86/speculation/l1tf: Limit swap file size to MAX_PA/2 Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 34/43] x86/bugs: Move the l1tf function and define pr_fmt properly Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 35/43] x86/speculation/l1tf: Extend 64bit swap file size limit Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 36/43] x86/cpufeatures: Add detection of L1D cache flush support Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 37/43] x86/speculation/l1tf: Protect PAE swap entries against L1TF Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 38/43] x86/speculation/l1tf: Fix up pte->pfn conversion for PAE Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 39/43] x86/speculation/l1tf: Invert all not present mappings Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 40/43] x86/speculation/l1tf: Make pmd/pud_mknotpresent() invert Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 41/43] x86/mm/pat: Make set_memory_np() L1TF safe Greg Kroah-Hartman
2018-09-09 16:46 ` Ben Hutchings
2018-09-09 17:06 ` Guenter Roeck
2018-09-10 7:16 ` Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 42/43] x86/mm/kmmio: Make the tracer robust against L1TF Greg Kroah-Hartman
2018-08-14 17:18 ` [PATCH 4.4 43/43] x86/speculation/l1tf: Fix up CPU feature flags Greg Kroah-Hartman
2018-08-15 6:15 ` [PATCH 4.4 00/43] 4.4.148-stable review Greg Kroah-Hartman
2018-08-15 13:10 ` Guenter Roeck
2018-08-15 20:52 ` Dan Rue
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180814171517.835654211@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=jannh@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).