diff options
-rw-r--r-- | fs/nfsd/export.c | 26 | ||||
-rw-r--r-- | fs/nfsd/nfsfh.c | 6 | ||||
-rw-r--r-- | fs/nfsd/nfssvc.c | 10 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 4 | ||||
-rw-r--r-- | include/linux/nfsd/export.h | 1 | ||||
-rw-r--r-- | include/linux/nfsd/nfsd.h | 1 |
6 files changed, 48 insertions, 0 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 4537a8f5cb9a..323cbdcc9bfd 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -1228,6 +1228,28 @@ exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, | |||
1228 | return exp; | 1228 | return exp; |
1229 | } | 1229 | } |
1230 | 1230 | ||
1231 | __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp) | ||
1232 | { | ||
1233 | struct exp_flavor_info *f; | ||
1234 | struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors; | ||
1235 | |||
1236 | /* legacy gss-only clients are always OK: */ | ||
1237 | if (exp->ex_client == rqstp->rq_gssclient) | ||
1238 | return 0; | ||
1239 | /* ip-address based client; check sec= export option: */ | ||
1240 | for (f = exp->ex_flavors; f < end; f++) { | ||
1241 | if (f->pseudoflavor == rqstp->rq_flavor) | ||
1242 | return 0; | ||
1243 | } | ||
1244 | /* defaults in absence of sec= options: */ | ||
1245 | if (exp->ex_nflavors == 0) { | ||
1246 | if (rqstp->rq_flavor == RPC_AUTH_NULL || | ||
1247 | rqstp->rq_flavor == RPC_AUTH_UNIX) | ||
1248 | return 0; | ||
1249 | } | ||
1250 | return nfserr_wrongsec; | ||
1251 | } | ||
1252 | |||
1231 | /* | 1253 | /* |
1232 | * Uses rq_client and rq_gssclient to find an export; uses rq_client (an | 1254 | * Uses rq_client and rq_gssclient to find an export; uses rq_client (an |
1233 | * auth_unix client) if it's available and has secinfo information; | 1255 | * auth_unix client) if it's available and has secinfo information; |
@@ -1340,6 +1362,10 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp) | |||
1340 | if (IS_ERR(exp)) | 1362 | if (IS_ERR(exp)) |
1341 | return nfserrno(PTR_ERR(exp)); | 1363 | return nfserrno(PTR_ERR(exp)); |
1342 | rv = fh_compose(fhp, exp, exp->ex_dentry, NULL); | 1364 | rv = fh_compose(fhp, exp, exp->ex_dentry, NULL); |
1365 | if (rv) | ||
1366 | goto out; | ||
1367 | rv = check_nfsd_access(exp, rqstp); | ||
1368 | out: | ||
1343 | exp_put(exp); | 1369 | exp_put(exp); |
1344 | return rv; | 1370 | return rv; |
1345 | } | 1371 | } |
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 22cb5be79ad0..d5fe392b14fb 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | #include <linux/sunrpc/clnt.h> | 21 | #include <linux/sunrpc/clnt.h> |
22 | #include <linux/sunrpc/svc.h> | 22 | #include <linux/sunrpc/svc.h> |
23 | #include <linux/sunrpc/svcauth_gss.h> | ||
23 | #include <linux/nfsd/nfsd.h> | 24 | #include <linux/nfsd/nfsd.h> |
24 | 25 | ||
25 | #define NFSDDBG_FACILITY NFSDDBG_FH | 26 | #define NFSDDBG_FACILITY NFSDDBG_FH |
@@ -248,6 +249,11 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
248 | if (error) | 249 | if (error) |
249 | goto out; | 250 | goto out; |
250 | 251 | ||
252 | /* Check security flavor */ | ||
253 | error = check_nfsd_access(exp, rqstp); | ||
254 | if (error) | ||
255 | goto out; | ||
256 | |||
251 | /* Finally, check access permissions. */ | 257 | /* Finally, check access permissions. */ |
252 | error = nfsd_permission(exp, dentry, access); | 258 | error = nfsd_permission(exp, dentry, access); |
253 | 259 | ||
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 5c8192bcbced..a8c89ae4c743 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
@@ -494,6 +494,15 @@ out: | |||
494 | module_put_and_exit(0); | 494 | module_put_and_exit(0); |
495 | } | 495 | } |
496 | 496 | ||
497 | static __be32 map_new_errors(u32 vers, __be32 nfserr) | ||
498 | { | ||
499 | if (nfserr == nfserr_jukebox && vers == 2) | ||
500 | return nfserr_dropit; | ||
501 | if (nfserr == nfserr_wrongsec && vers < 4) | ||
502 | return nfserr_acces; | ||
503 | return nfserr; | ||
504 | } | ||
505 | |||
497 | int | 506 | int |
498 | nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) | 507 | nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) |
499 | { | 508 | { |
@@ -536,6 +545,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) | |||
536 | 545 | ||
537 | /* Now call the procedure handler, and encode NFS status. */ | 546 | /* Now call the procedure handler, and encode NFS status. */ |
538 | nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); | 547 | nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); |
548 | nfserr = map_new_errors(rqstp->rq_vers, nfserr); | ||
539 | if (nfserr == nfserr_jukebox && rqstp->rq_vers == 2) | 549 | if (nfserr == nfserr_jukebox && rqstp->rq_vers == 2) |
540 | nfserr = nfserr_dropit; | 550 | nfserr = nfserr_dropit; |
541 | if (nfserr == nfserr_dropit) { | 551 | if (nfserr == nfserr_dropit) { |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 627f460a4007..8e109e586a74 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -240,6 +240,9 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, | |||
240 | err = nfsd_lookup_dentry(rqstp, fhp, name, len, &exp, &dentry); | 240 | err = nfsd_lookup_dentry(rqstp, fhp, name, len, &exp, &dentry); |
241 | if (err) | 241 | if (err) |
242 | return err; | 242 | return err; |
243 | err = check_nfsd_access(exp, rqstp); | ||
244 | if (err) | ||
245 | goto out; | ||
243 | /* | 246 | /* |
244 | * Note: we compose the file handle now, but as the | 247 | * Note: we compose the file handle now, but as the |
245 | * dentry may be negative, it may need to be updated. | 248 | * dentry may be negative, it may need to be updated. |
@@ -247,6 +250,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, | |||
247 | err = fh_compose(resfh, exp, dentry, fhp); | 250 | err = fh_compose(resfh, exp, dentry, fhp); |
248 | if (!err && !dentry->d_inode) | 251 | if (!err && !dentry->d_inode) |
249 | err = nfserr_noent; | 252 | err = nfserr_noent; |
253 | out: | ||
250 | dput(dentry); | 254 | dput(dentry); |
251 | exp_put(exp); | 255 | exp_put(exp); |
252 | return err; | 256 | return err; |
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 1ba53e524749..424be41130ba 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h | |||
@@ -116,6 +116,7 @@ struct svc_expkey { | |||
116 | #define EX_NOHIDE(exp) ((exp)->ex_flags & NFSEXP_NOHIDE) | 116 | #define EX_NOHIDE(exp) ((exp)->ex_flags & NFSEXP_NOHIDE) |
117 | #define EX_WGATHER(exp) ((exp)->ex_flags & NFSEXP_GATHERED_WRITES) | 117 | #define EX_WGATHER(exp) ((exp)->ex_flags & NFSEXP_GATHERED_WRITES) |
118 | 118 | ||
119 | __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp); | ||
119 | 120 | ||
120 | /* | 121 | /* |
121 | * Function declarations | 122 | * Function declarations |
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index ce5e345a9bce..62499c2f0918 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h | |||
@@ -236,6 +236,7 @@ void nfsd_lockd_shutdown(void); | |||
236 | #define nfserr_badname __constant_htonl(NFSERR_BADNAME) | 236 | #define nfserr_badname __constant_htonl(NFSERR_BADNAME) |
237 | #define nfserr_cb_path_down __constant_htonl(NFSERR_CB_PATH_DOWN) | 237 | #define nfserr_cb_path_down __constant_htonl(NFSERR_CB_PATH_DOWN) |
238 | #define nfserr_locked __constant_htonl(NFSERR_LOCKED) | 238 | #define nfserr_locked __constant_htonl(NFSERR_LOCKED) |
239 | #define nfserr_wrongsec __constant_htonl(NFSERR_WRONGSEC) | ||
239 | #define nfserr_replay_me __constant_htonl(NFSERR_REPLAY_ME) | 240 | #define nfserr_replay_me __constant_htonl(NFSERR_REPLAY_ME) |
240 | 241 | ||
241 | /* error codes for internal use */ | 242 | /* error codes for internal use */ |