diff options
Diffstat (limited to 'fs/nfsd/nfsfh.c')
-rw-r--r-- | fs/nfsd/nfsfh.c | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 100ae5641162..f45451eb1e38 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
@@ -176,9 +176,24 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp) | |||
176 | if (IS_ERR(exp)) | 176 | if (IS_ERR(exp)) |
177 | return nfserrno(PTR_ERR(exp)); | 177 | return nfserrno(PTR_ERR(exp)); |
178 | 178 | ||
179 | error = nfsd_setuser_and_check_port(rqstp, exp); | 179 | if (exp->ex_flags & NFSEXP_NOSUBTREECHECK) { |
180 | if (error) | 180 | /* Elevate privileges so that the lack of 'r' or 'x' |
181 | goto out; | 181 | * permission on some parent directory will |
182 | * not stop exportfs_decode_fh from being able | ||
183 | * to reconnect a directory into the dentry cache. | ||
184 | * The same problem can affect "SUBTREECHECK" exports, | ||
185 | * but as nfsd_acceptable depends on correct | ||
186 | * access control settings being in effect, we cannot | ||
187 | * fix that case easily. | ||
188 | */ | ||
189 | current->cap_effective = | ||
190 | cap_raise_nfsd_set(current->cap_effective, | ||
191 | current->cap_permitted); | ||
192 | } else { | ||
193 | error = nfsd_setuser_and_check_port(rqstp, exp); | ||
194 | if (error) | ||
195 | goto out; | ||
196 | } | ||
182 | 197 | ||
183 | /* | 198 | /* |
184 | * Look up the dentry using the NFS file handle. | 199 | * 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) | |||
215 | goto out; | 230 | goto out; |
216 | } | 231 | } |
217 | 232 | ||
233 | if (exp->ex_flags & NFSEXP_NOSUBTREECHECK) { | ||
234 | error = nfsd_setuser_and_check_port(rqstp, exp); | ||
235 | if (error) { | ||
236 | dput(dentry); | ||
237 | goto out; | ||
238 | } | ||
239 | } | ||
240 | |||
218 | if (S_ISDIR(dentry->d_inode->i_mode) && | 241 | if (S_ISDIR(dentry->d_inode->i_mode) && |
219 | (dentry->d_flags & DCACHE_DISCONNECTED)) { | 242 | (dentry->d_flags & DCACHE_DISCONNECTED)) { |
220 | printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n", | 243 | printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n", |
@@ -279,7 +302,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
279 | if (error) | 302 | if (error) |
280 | goto out; | 303 | goto out; |
281 | 304 | ||
282 | if (!(access & MAY_LOCK)) { | 305 | if (!(access & NFSD_MAY_LOCK)) { |
283 | /* | 306 | /* |
284 | * pseudoflavor restrictions are not enforced on NLM, | 307 | * pseudoflavor restrictions are not enforced on NLM, |
285 | * which clients virtually always use auth_sys for, | 308 | * which clients virtually always use auth_sys for, |