From e7198fd620d03a35320b737cdbe0889b5db02d80 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Thu, 8 May 2008 13:03:09 +1000 Subject: [PATCH] --- yaml --- r: 104099 b: refs/heads/master c: 496d6c32d4d057cb44272d9bd587ff97d023ee92 h: refs/heads/master i: 104097: bfbc2477455f7b7795a79d13faf99a3323bcf8fb 104095: 613a9a0b79a25086656739d42116f8cbae47ba5a v: v3 --- [refs] | 2 +- trunk/fs/nfsd/nfsfh.c | 29 ++++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 310c4cc1c1f9..e69cc57bd484 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 863a24882ed0a57ff25daaf39885f3a47b706e4b +refs/heads/master: 496d6c32d4d057cb44272d9bd587ff97d023ee92 diff --git a/trunk/fs/nfsd/nfsfh.c b/trunk/fs/nfsd/nfsfh.c index c7b0fdaeac96..f45451eb1e38 100644 --- a/trunk/fs/nfsd/nfsfh.c +++ b/trunk/fs/nfsd/nfsfh.c @@ -176,9 +176,24 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp) if (IS_ERR(exp)) return nfserrno(PTR_ERR(exp)); - error = nfsd_setuser_and_check_port(rqstp, exp); - if (error) - goto out; + if (exp->ex_flags & NFSEXP_NOSUBTREECHECK) { + /* Elevate privileges so that the lack of 'r' or 'x' + * permission on some parent directory will + * not stop exportfs_decode_fh from being able + * to reconnect a directory into the dentry cache. + * The same problem can affect "SUBTREECHECK" exports, + * but as nfsd_acceptable depends on correct + * access control settings being in effect, we cannot + * fix that case easily. + */ + current->cap_effective = + cap_raise_nfsd_set(current->cap_effective, + current->cap_permitted); + } else { + error = nfsd_setuser_and_check_port(rqstp, exp); + if (error) + goto out; + } /* * Look up the dentry using the NFS file handle. @@ -215,6 +230,14 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp) goto out; } + if (exp->ex_flags & NFSEXP_NOSUBTREECHECK) { + error = nfsd_setuser_and_check_port(rqstp, exp); + if (error) { + dput(dentry); + goto out; + } + } + if (S_ISDIR(dentry->d_inode->i_mode) && (dentry->d_flags & DCACHE_DISCONNECTED)) { printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",