diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 84 |
1 files changed, 83 insertions, 1 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 5f4912f72282..892bff53f61d 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2251,13 +2251,14 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2251 | static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | 2251 | static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, |
2252 | struct nfs_fsinfo *info) | 2252 | struct nfs_fsinfo *info) |
2253 | { | 2253 | { |
2254 | int minor_version = server->nfs_client->cl_minorversion; | ||
2254 | int status = nfs4_lookup_root(server, fhandle, info); | 2255 | int status = nfs4_lookup_root(server, fhandle, info); |
2255 | if ((status == -NFS4ERR_WRONGSEC) && !(server->flags & NFS_MOUNT_SECFLAVOUR)) | 2256 | if ((status == -NFS4ERR_WRONGSEC) && !(server->flags & NFS_MOUNT_SECFLAVOUR)) |
2256 | /* | 2257 | /* |
2257 | * A status of -NFS4ERR_WRONGSEC will be mapped to -EPERM | 2258 | * A status of -NFS4ERR_WRONGSEC will be mapped to -EPERM |
2258 | * by nfs4_map_errors() as this function exits. | 2259 | * by nfs4_map_errors() as this function exits. |
2259 | */ | 2260 | */ |
2260 | status = nfs4_find_root_sec(server, fhandle, info); | 2261 | status = nfs_v4_minor_ops[minor_version]->find_root_sec(server, fhandle, info); |
2261 | if (status == 0) | 2262 | if (status == 0) |
2262 | status = nfs4_server_capabilities(server, fhandle); | 2263 | status = nfs4_server_capabilities(server, fhandle); |
2263 | if (status == 0) | 2264 | if (status == 0) |
@@ -5935,6 +5936,85 @@ out: | |||
5935 | rpc_put_task(task); | 5936 | rpc_put_task(task); |
5936 | return status; | 5937 | return status; |
5937 | } | 5938 | } |
5939 | |||
5940 | static int | ||
5941 | _nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, | ||
5942 | struct nfs_fsinfo *info, struct nfs4_secinfo_flavors *flavors) | ||
5943 | { | ||
5944 | struct nfs41_secinfo_no_name_args args = { | ||
5945 | .style = SECINFO_STYLE_CURRENT_FH, | ||
5946 | }; | ||
5947 | struct nfs4_secinfo_res res = { | ||
5948 | .flavors = flavors, | ||
5949 | }; | ||
5950 | struct rpc_message msg = { | ||
5951 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SECINFO_NO_NAME], | ||
5952 | .rpc_argp = &args, | ||
5953 | .rpc_resp = &res, | ||
5954 | }; | ||
5955 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | ||
5956 | } | ||
5957 | |||
5958 | static int | ||
5959 | nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, | ||
5960 | struct nfs_fsinfo *info, struct nfs4_secinfo_flavors *flavors) | ||
5961 | { | ||
5962 | struct nfs4_exception exception = { }; | ||
5963 | int err; | ||
5964 | do { | ||
5965 | err = _nfs41_proc_secinfo_no_name(server, fhandle, info, flavors); | ||
5966 | switch (err) { | ||
5967 | case 0: | ||
5968 | case -NFS4ERR_WRONGSEC: | ||
5969 | case -NFS4ERR_NOTSUPP: | ||
5970 | break; | ||
5971 | default: | ||
5972 | err = nfs4_handle_exception(server, err, &exception); | ||
5973 | } | ||
5974 | } while (exception.retry); | ||
5975 | return err; | ||
5976 | } | ||
5977 | |||
5978 | static int | ||
5979 | nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, | ||
5980 | struct nfs_fsinfo *info) | ||
5981 | { | ||
5982 | int err; | ||
5983 | struct page *page; | ||
5984 | rpc_authflavor_t flavor; | ||
5985 | struct nfs4_secinfo_flavors *flavors; | ||
5986 | |||
5987 | page = alloc_page(GFP_KERNEL); | ||
5988 | if (!page) { | ||
5989 | err = -ENOMEM; | ||
5990 | goto out; | ||
5991 | } | ||
5992 | |||
5993 | flavors = page_address(page); | ||
5994 | err = nfs41_proc_secinfo_no_name(server, fhandle, info, flavors); | ||
5995 | |||
5996 | /* | ||
5997 | * Fall back on "guess and check" method if | ||
5998 | * the server doesn't support SECINFO_NO_NAME | ||
5999 | */ | ||
6000 | if (err == -NFS4ERR_WRONGSEC || err == -NFS4ERR_NOTSUPP) { | ||
6001 | err = nfs4_find_root_sec(server, fhandle, info); | ||
6002 | goto out_freepage; | ||
6003 | } | ||
6004 | if (err) | ||
6005 | goto out_freepage; | ||
6006 | |||
6007 | flavor = nfs_find_best_sec(flavors); | ||
6008 | if (err == 0) | ||
6009 | err = nfs4_lookup_root_sec(server, fhandle, info, flavor); | ||
6010 | |||
6011 | out_freepage: | ||
6012 | put_page(page); | ||
6013 | if (err == -EACCES) | ||
6014 | return -EPERM; | ||
6015 | out: | ||
6016 | return err; | ||
6017 | } | ||
5938 | #endif /* CONFIG_NFS_V4_1 */ | 6018 | #endif /* CONFIG_NFS_V4_1 */ |
5939 | 6019 | ||
5940 | struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { | 6020 | struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { |
@@ -5996,6 +6076,7 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = { | |||
5996 | .minor_version = 0, | 6076 | .minor_version = 0, |
5997 | .call_sync = _nfs4_call_sync, | 6077 | .call_sync = _nfs4_call_sync, |
5998 | .validate_stateid = nfs4_validate_delegation_stateid, | 6078 | .validate_stateid = nfs4_validate_delegation_stateid, |
6079 | .find_root_sec = nfs4_find_root_sec, | ||
5999 | .reboot_recovery_ops = &nfs40_reboot_recovery_ops, | 6080 | .reboot_recovery_ops = &nfs40_reboot_recovery_ops, |
6000 | .nograce_recovery_ops = &nfs40_nograce_recovery_ops, | 6081 | .nograce_recovery_ops = &nfs40_nograce_recovery_ops, |
6001 | .state_renewal_ops = &nfs40_state_renewal_ops, | 6082 | .state_renewal_ops = &nfs40_state_renewal_ops, |
@@ -6006,6 +6087,7 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { | |||
6006 | .minor_version = 1, | 6087 | .minor_version = 1, |
6007 | .call_sync = _nfs4_call_sync_session, | 6088 | .call_sync = _nfs4_call_sync_session, |
6008 | .validate_stateid = nfs41_validate_delegation_stateid, | 6089 | .validate_stateid = nfs41_validate_delegation_stateid, |
6090 | .find_root_sec = nfs41_find_root_sec, | ||
6009 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, | 6091 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, |
6010 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, | 6092 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, |
6011 | .state_renewal_ops = &nfs41_state_renewal_ops, | 6093 | .state_renewal_ops = &nfs41_state_renewal_ops, |