diff options
author | J. Bruce Fields <bfields@redhat.com> | 2013-04-15 16:03:46 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2013-04-26 16:18:15 -0400 |
commit | aa387d6ce15330e09037947147c5a5a2ba42a0e8 (patch) | |
tree | ab9ec0cbd2636e3089db7a10ec49756cce702820 /fs/nfsd | |
parent | 030d794bf49855f5e2a9e8dfbfad34211d1eb08b (diff) |
nfsd: fix EXDEV checking in rename
We again check for the EXDEV a little later on, so the first check is
redundant. This check is also slightly racier, since a badly timed
eviction from the export cache could leave us with the two fh_export
pointers pointing to two different cache entries which each refer to the
same underlying export.
It's better to compare vfsmounts as the later check does, but that
leaves a minor security hole in the case where the two exports refer to
two different directories especially if (for example) they have
different root-squashing options.
So, compare ex_path.dentry too.
Reported-by: Joe Habermann <joe.habermann@gmail.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/vfs.c | 6 |
1 files changed, 2 insertions, 4 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 2b2e2396a869..84ce601d8063 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -1758,10 +1758,6 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1758 | tdentry = tfhp->fh_dentry; | 1758 | tdentry = tfhp->fh_dentry; |
1759 | tdir = tdentry->d_inode; | 1759 | tdir = tdentry->d_inode; |
1760 | 1760 | ||
1761 | err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev; | ||
1762 | if (ffhp->fh_export != tfhp->fh_export) | ||
1763 | goto out; | ||
1764 | |||
1765 | err = nfserr_perm; | 1761 | err = nfserr_perm; |
1766 | if (!flen || isdotent(fname, flen) || !tlen || isdotent(tname, tlen)) | 1762 | if (!flen || isdotent(fname, flen) || !tlen || isdotent(tname, tlen)) |
1767 | goto out; | 1763 | goto out; |
@@ -1802,6 +1798,8 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1802 | host_err = -EXDEV; | 1798 | host_err = -EXDEV; |
1803 | if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt) | 1799 | if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt) |
1804 | goto out_dput_new; | 1800 | goto out_dput_new; |
1801 | if (ffhp->fh_export->ex_path.dentry != tfhp->fh_export->ex_path.dentry) | ||
1802 | goto out_dput_new; | ||
1805 | 1803 | ||
1806 | host_err = nfsd_break_lease(odentry->d_inode); | 1804 | host_err = nfsd_break_lease(odentry->d_inode); |
1807 | if (host_err) | 1805 | if (host_err) |