aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-31 21:18:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-31 21:18:11 -0400
commita00b6151a2ae4c52576c35d3998e144a993d50b8 (patch)
treefc312be05c4deb4dead7a6afa09e88017d3a0146 /net/sunrpc
parent08615d7d85e5aa02c05bf6c4dde87d940e7f85f6 (diff)
parentb108fe6b08f3f61c2c465649b20b7d4b4c185728 (diff)
Merge branch 'for-3.5-take-2' of git://linux-nfs.org/~bfields/linux
Pull nfsd update from Bruce Fields. * 'for-3.5-take-2' of git://linux-nfs.org/~bfields/linux: (23 commits) nfsd: trivial: use SEEK_SET instead of 0 in vfs_llseek SUNRPC: split upcall function to extract reusable parts nfsd: allocate id-to-name and name-to-id caches in per-net operations. nfsd: make name-to-id cache allocated per network namespace context nfsd: make id-to-name cache allocated per network namespace context nfsd: pass network context to idmap init/exit functions nfsd: allocate export and expkey caches in per-net operations. nfsd: make expkey cache allocated per network namespace context nfsd: make export cache allocated per network namespace context nfsd: pass pointer to export cache down to stack wherever possible. nfsd: pass network context to export caches init/shutdown routines Lockd: pass network namespace to creation and destruction routines NFSd: remove hard-coded dereferences to name-to-id and id-to-name caches nfsd: pass pointer to expkey cache down to stack wherever possible. nfsd: use hash table from cache detail in nfsd export seq ops nfsd: pass svc_export_cache pointer as private data to "exports" seq file ops nfsd: use exp_put() for svc_export_cache put nfsd: use cache detail pointer from svc_export structure on cache put nfsd: add link to owner cache detail to svc_export structure nfsd: use passed cache_detail pointer expkey_parse() ...
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c100
-rw-r--r--net/sunrpc/svcauth_unix.c13
2 files changed, 68 insertions, 45 deletions
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 28b62dbb6d1e..3089de37c433 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -969,16 +969,17 @@ svcauth_gss_set_client(struct svc_rqst *rqstp)
969} 969}
970 970
971static inline int 971static inline int
972gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, struct rsi *rsip) 972gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp,
973 struct xdr_netobj *out_handle, int *major_status)
973{ 974{
974 struct rsc *rsci; 975 struct rsc *rsci;
975 int rc; 976 int rc;
976 977
977 if (rsip->major_status != GSS_S_COMPLETE) 978 if (*major_status != GSS_S_COMPLETE)
978 return gss_write_null_verf(rqstp); 979 return gss_write_null_verf(rqstp);
979 rsci = gss_svc_searchbyctx(cd, &rsip->out_handle); 980 rsci = gss_svc_searchbyctx(cd, out_handle);
980 if (rsci == NULL) { 981 if (rsci == NULL) {
981 rsip->major_status = GSS_S_NO_CONTEXT; 982 *major_status = GSS_S_NO_CONTEXT;
982 return gss_write_null_verf(rqstp); 983 return gss_write_null_verf(rqstp);
983 } 984 }
984 rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN); 985 rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN);
@@ -986,22 +987,13 @@ gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, struct rsi
986 return rc; 987 return rc;
987} 988}
988 989
989/* 990static inline int
990 * Having read the cred already and found we're in the context 991gss_read_verf(struct rpc_gss_wire_cred *gc,
991 * initiation case, read the verifier and initiate (or check the results 992 struct kvec *argv, __be32 *authp,
992 * of) upcalls to userspace for help with context initiation. If 993 struct xdr_netobj *in_handle,
993 * the upcall results are available, write the verifier and result. 994 struct xdr_netobj *in_token)
994 * Otherwise, drop the request pending an answer to the upcall.
995 */
996static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
997 struct rpc_gss_wire_cred *gc, __be32 *authp)
998{ 995{
999 struct kvec *argv = &rqstp->rq_arg.head[0];
1000 struct kvec *resv = &rqstp->rq_res.head[0];
1001 struct xdr_netobj tmpobj; 996 struct xdr_netobj tmpobj;
1002 struct rsi *rsip, rsikey;
1003 int ret;
1004 struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id);
1005 997
1006 /* Read the verifier; should be NULL: */ 998 /* Read the verifier; should be NULL: */
1007 *authp = rpc_autherr_badverf; 999 *authp = rpc_autherr_badverf;
@@ -1011,24 +1003,67 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
1011 return SVC_DENIED; 1003 return SVC_DENIED;
1012 if (svc_getnl(argv) != 0) 1004 if (svc_getnl(argv) != 0)
1013 return SVC_DENIED; 1005 return SVC_DENIED;
1014
1015 /* Martial context handle and token for upcall: */ 1006 /* Martial context handle and token for upcall: */
1016 *authp = rpc_autherr_badcred; 1007 *authp = rpc_autherr_badcred;
1017 if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0) 1008 if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0)
1018 return SVC_DENIED; 1009 return SVC_DENIED;
1019 memset(&rsikey, 0, sizeof(rsikey)); 1010 if (dup_netobj(in_handle, &gc->gc_ctx))
1020 if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx))
1021 return SVC_CLOSE; 1011 return SVC_CLOSE;
1022 *authp = rpc_autherr_badverf; 1012 *authp = rpc_autherr_badverf;
1023 if (svc_safe_getnetobj(argv, &tmpobj)) { 1013 if (svc_safe_getnetobj(argv, &tmpobj)) {
1024 kfree(rsikey.in_handle.data); 1014 kfree(in_handle->data);
1025 return SVC_DENIED; 1015 return SVC_DENIED;
1026 } 1016 }
1027 if (dup_netobj(&rsikey.in_token, &tmpobj)) { 1017 if (dup_netobj(in_token, &tmpobj)) {
1028 kfree(rsikey.in_handle.data); 1018 kfree(in_handle->data);
1029 return SVC_CLOSE; 1019 return SVC_CLOSE;
1030 } 1020 }
1031 1021
1022 return 0;
1023}
1024
1025static inline int
1026gss_write_resv(struct kvec *resv, size_t size_limit,
1027 struct xdr_netobj *out_handle, struct xdr_netobj *out_token,
1028 int major_status, int minor_status)
1029{
1030 if (resv->iov_len + 4 > size_limit)
1031 return -1;
1032 svc_putnl(resv, RPC_SUCCESS);
1033 if (svc_safe_putnetobj(resv, out_handle))
1034 return -1;
1035 if (resv->iov_len + 3 * 4 > size_limit)
1036 return -1;
1037 svc_putnl(resv, major_status);
1038 svc_putnl(resv, minor_status);
1039 svc_putnl(resv, GSS_SEQ_WIN);
1040 if (svc_safe_putnetobj(resv, out_token))
1041 return -1;
1042 return 0;
1043}
1044
1045/*
1046 * Having read the cred already and found we're in the context
1047 * initiation case, read the verifier and initiate (or check the results
1048 * of) upcalls to userspace for help with context initiation. If
1049 * the upcall results are available, write the verifier and result.
1050 * Otherwise, drop the request pending an answer to the upcall.
1051 */
1052static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
1053 struct rpc_gss_wire_cred *gc, __be32 *authp)
1054{
1055 struct kvec *argv = &rqstp->rq_arg.head[0];
1056 struct kvec *resv = &rqstp->rq_res.head[0];
1057 struct rsi *rsip, rsikey;
1058 int ret;
1059 struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id);
1060
1061 memset(&rsikey, 0, sizeof(rsikey));
1062 ret = gss_read_verf(gc, argv, authp,
1063 &rsikey.in_handle, &rsikey.in_token);
1064 if (ret)
1065 return ret;
1066
1032 /* Perform upcall, or find upcall result: */ 1067 /* Perform upcall, or find upcall result: */
1033 rsip = rsi_lookup(sn->rsi_cache, &rsikey); 1068 rsip = rsi_lookup(sn->rsi_cache, &rsikey);
1034 rsi_free(&rsikey); 1069 rsi_free(&rsikey);
@@ -1040,19 +1075,12 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
1040 1075
1041 ret = SVC_CLOSE; 1076 ret = SVC_CLOSE;
1042 /* Got an answer to the upcall; use it: */ 1077 /* Got an answer to the upcall; use it: */
1043 if (gss_write_init_verf(sn->rsc_cache, rqstp, rsip)) 1078 if (gss_write_init_verf(sn->rsc_cache, rqstp,
1079 &rsip->out_handle, &rsip->major_status))
1044 goto out; 1080 goto out;
1045 if (resv->iov_len + 4 > PAGE_SIZE) 1081 if (gss_write_resv(resv, PAGE_SIZE,
1046 goto out; 1082 &rsip->out_handle, &rsip->out_token,
1047 svc_putnl(resv, RPC_SUCCESS); 1083 rsip->major_status, rsip->minor_status))
1048 if (svc_safe_putnetobj(resv, &rsip->out_handle))
1049 goto out;
1050 if (resv->iov_len + 3 * 4 > PAGE_SIZE)
1051 goto out;
1052 svc_putnl(resv, rsip->major_status);
1053 svc_putnl(resv, rsip->minor_status);
1054 svc_putnl(resv, GSS_SEQ_WIN);
1055 if (svc_safe_putnetobj(resv, &rsip->out_token))
1056 goto out; 1084 goto out;
1057 1085
1058 ret = SVC_COMPLETE; 1086 ret = SVC_COMPLETE;
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 71ec8530ec8c..6138c925923d 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -347,17 +347,12 @@ static inline int ip_map_update(struct net *net, struct ip_map *ipm,
347 return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry); 347 return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry);
348} 348}
349 349
350 350void svcauth_unix_purge(struct net *net)
351void svcauth_unix_purge(void)
352{ 351{
353 struct net *net; 352 struct sunrpc_net *sn;
354
355 for_each_net(net) {
356 struct sunrpc_net *sn;
357 353
358 sn = net_generic(net, sunrpc_net_id); 354 sn = net_generic(net, sunrpc_net_id);
359 cache_purge(sn->ip_map_cache); 355 cache_purge(sn->ip_map_cache);
360 }
361} 356}
362EXPORT_SYMBOL_GPL(svcauth_unix_purge); 357EXPORT_SYMBOL_GPL(svcauth_unix_purge);
363 358