Commit 301f0268b63d1b07268e46f5901fc51d6cac20eb
1 parent
ca4e05195d
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
nfsd: racy access to ->d_name in nsfd4_encode_path()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Showing 1 changed file with 8 additions and 6 deletions Side-by-side Diff
fs/nfsd/nfs4xdr.c
... | ... | @@ -1816,10 +1816,7 @@ |
1816 | 1816 | static __be32 nfsd4_encode_path(const struct path *root, |
1817 | 1817 | const struct path *path, __be32 **pp, int *buflen) |
1818 | 1818 | { |
1819 | - struct path cur = { | |
1820 | - .mnt = path->mnt, | |
1821 | - .dentry = path->dentry, | |
1822 | - }; | |
1819 | + struct path cur = *path; | |
1823 | 1820 | __be32 *p = *pp; |
1824 | 1821 | struct dentry **components = NULL; |
1825 | 1822 | unsigned int ncomponents = 0; |
1826 | 1823 | |
1827 | 1824 | |
1828 | 1825 | |
1829 | 1826 | |
... | ... | @@ -1859,14 +1856,19 @@ |
1859 | 1856 | |
1860 | 1857 | while (ncomponents) { |
1861 | 1858 | struct dentry *dentry = components[ncomponents - 1]; |
1862 | - unsigned int len = dentry->d_name.len; | |
1859 | + unsigned int len; | |
1863 | 1860 | |
1861 | + spin_lock(&dentry->d_lock); | |
1862 | + len = dentry->d_name.len; | |
1864 | 1863 | *buflen -= 4 + (XDR_QUADLEN(len) << 2); |
1865 | - if (*buflen < 0) | |
1864 | + if (*buflen < 0) { | |
1865 | + spin_unlock(&dentry->d_lock); | |
1866 | 1866 | goto out_free; |
1867 | + } | |
1867 | 1868 | WRITE32(len); |
1868 | 1869 | WRITEMEM(dentry->d_name.name, len); |
1869 | 1870 | dprintk("/%s", dentry->d_name.name); |
1871 | + spin_unlock(&dentry->d_lock); | |
1870 | 1872 | dput(dentry); |
1871 | 1873 | ncomponents--; |
1872 | 1874 | } |