]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.8.5/nfs-fix-inode-corruption-in-nfs_prime_dcache.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.8.5 / nfs-fix-inode-corruption-in-nfs_prime_dcache.patch
CommitLineData
677c3905
GKH
1From 7dc72d5f7a0ec97a53e126c46e2cbd2560757955 Mon Sep 17 00:00:00 2001
2From: Trond Myklebust <trond.myklebust@primarydata.com>
3Date: Thu, 22 Sep 2016 13:38:52 -0400
4Subject: NFS: Fix inode corruption in nfs_prime_dcache()
5
6From: Trond Myklebust <trond.myklebust@primarydata.com>
7
8commit 7dc72d5f7a0ec97a53e126c46e2cbd2560757955 upstream.
9
10Due to inode number reuse in filesystems, we can end up corrupting the
11inode on our client if we apply the file attributes without ensuring that
12the filehandle matches.
13Typical symptoms include spurious "mode changed" reports in the syslog.
14
15We still do want to ensure that we don't invalidate the dentry if the
16inode number matches, but we don't have a filehandle.
17
18Fixes: fa9233699cc1 ("NFS: Don't require a filehandle to refresh...")
19Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
20Tested-by: Oleg Drokin <green@linuxhacker.ru>
21Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
22Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
23
24---
25 fs/nfs/dir.c | 16 +++++++++++-----
26 1 file changed, 11 insertions(+), 5 deletions(-)
27
28--- a/fs/nfs/dir.c
29+++ b/fs/nfs/dir.c
30@@ -435,11 +435,11 @@ int nfs_same_file(struct dentry *dentry,
31 return 0;
32
33 nfsi = NFS_I(inode);
34- if (entry->fattr->fileid == nfsi->fileid)
35- return 1;
36- if (nfs_compare_fh(entry->fh, &nfsi->fh) == 0)
37- return 1;
38- return 0;
39+ if (entry->fattr->fileid != nfsi->fileid)
40+ return 0;
41+ if (entry->fh->size && nfs_compare_fh(entry->fh, &nfsi->fh) != 0)
42+ return 0;
43+ return 1;
44 }
45
46 static
47@@ -517,6 +517,8 @@ again:
48 &entry->fattr->fsid))
49 goto out;
50 if (nfs_same_file(dentry, entry)) {
51+ if (!entry->fh->size)
52+ goto out;
53 nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
54 status = nfs_refresh_inode(d_inode(dentry), entry->fattr);
55 if (!status)
56@@ -529,6 +531,10 @@ again:
57 goto again;
58 }
59 }
60+ if (!entry->fh->size) {
61+ d_lookup_done(dentry);
62+ goto out;
63+ }
64
65 inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr, entry->label);
66 alias = d_splice_alias(inode, dentry);