From e5f06f720eff24e32f1cc08ec03bcc8c4b2d2934 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 11 Apr 2012 15:13:28 +0400 Subject: nfsd: make expkey cache allocated per network namespace context This patch also changes svcauth_unix_purge() function: added network namespace as a parameter and thus loop over all networks was replaced by only one call for ip map cache purge. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields --- net/sunrpc/svcauth_unix.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 521d8f7dc83..9c3b9f01446 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -346,17 +346,12 @@ static inline int ip_map_update(struct net *net, struct ip_map *ipm, return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry); } - -void svcauth_unix_purge(void) +void svcauth_unix_purge(struct net *net) { - struct net *net; - - for_each_net(net) { - struct sunrpc_net *sn; + struct sunrpc_net *sn; - sn = net_generic(net, sunrpc_net_id); - cache_purge(sn->ip_map_cache); - } + sn = net_generic(net, sunrpc_net_id); + cache_purge(sn->ip_map_cache); } EXPORT_SYMBOL_GPL(svcauth_unix_purge); -- cgit v1.2.3 From fc2952a2a9f724f7d200c69a2b059ec331a80363 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 17 Apr 2012 09:39:06 -0400 Subject: SUNRPC: split upcall function to extract reusable parts This is needed to share code between the current server upcall mechanism and the new gssproxy upcall mechanism introduced in a following patch. Signed-off-by: Simo Sorce Signed-off-by: J. Bruce Fields --- net/sunrpc/auth_gss/svcauth_gss.c | 100 ++++++++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 36 deletions(-) (limited to 'net') diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 1600cfb1618..f0a0cd4470b 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -964,16 +964,17 @@ svcauth_gss_set_client(struct svc_rqst *rqstp) } static inline int -gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, struct rsi *rsip) +gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, + struct xdr_netobj *out_handle, int *major_status) { struct rsc *rsci; int rc; - if (rsip->major_status != GSS_S_COMPLETE) + if (*major_status != GSS_S_COMPLETE) return gss_write_null_verf(rqstp); - rsci = gss_svc_searchbyctx(cd, &rsip->out_handle); + rsci = gss_svc_searchbyctx(cd, out_handle); if (rsci == NULL) { - rsip->major_status = GSS_S_NO_CONTEXT; + *major_status = GSS_S_NO_CONTEXT; return gss_write_null_verf(rqstp); } rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN); @@ -981,22 +982,13 @@ gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, struct rsi return rc; } -/* - * Having read the cred already and found we're in the context - * initiation case, read the verifier and initiate (or check the results - * of) upcalls to userspace for help with context initiation. If - * the upcall results are available, write the verifier and result. - * Otherwise, drop the request pending an answer to the upcall. - */ -static int svcauth_gss_handle_init(struct svc_rqst *rqstp, - struct rpc_gss_wire_cred *gc, __be32 *authp) +static inline int +gss_read_verf(struct rpc_gss_wire_cred *gc, + struct kvec *argv, __be32 *authp, + struct xdr_netobj *in_handle, + struct xdr_netobj *in_token) { - struct kvec *argv = &rqstp->rq_arg.head[0]; - struct kvec *resv = &rqstp->rq_res.head[0]; struct xdr_netobj tmpobj; - struct rsi *rsip, rsikey; - int ret; - struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); /* Read the verifier; should be NULL: */ *authp = rpc_autherr_badverf; @@ -1006,24 +998,67 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp, return SVC_DENIED; if (svc_getnl(argv) != 0) return SVC_DENIED; - /* Martial context handle and token for upcall: */ *authp = rpc_autherr_badcred; if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0) return SVC_DENIED; - memset(&rsikey, 0, sizeof(rsikey)); - if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx)) + if (dup_netobj(in_handle, &gc->gc_ctx)) return SVC_CLOSE; *authp = rpc_autherr_badverf; if (svc_safe_getnetobj(argv, &tmpobj)) { - kfree(rsikey.in_handle.data); + kfree(in_handle->data); return SVC_DENIED; } - if (dup_netobj(&rsikey.in_token, &tmpobj)) { - kfree(rsikey.in_handle.data); + if (dup_netobj(in_token, &tmpobj)) { + kfree(in_handle->data); return SVC_CLOSE; } + return 0; +} + +static inline int +gss_write_resv(struct kvec *resv, size_t size_limit, + struct xdr_netobj *out_handle, struct xdr_netobj *out_token, + int major_status, int minor_status) +{ + if (resv->iov_len + 4 > size_limit) + return -1; + svc_putnl(resv, RPC_SUCCESS); + if (svc_safe_putnetobj(resv, out_handle)) + return -1; + if (resv->iov_len + 3 * 4 > size_limit) + return -1; + svc_putnl(resv, major_status); + svc_putnl(resv, minor_status); + svc_putnl(resv, GSS_SEQ_WIN); + if (svc_safe_putnetobj(resv, out_token)) + return -1; + return 0; +} + +/* + * Having read the cred already and found we're in the context + * initiation case, read the verifier and initiate (or check the results + * of) upcalls to userspace for help with context initiation. If + * the upcall results are available, write the verifier and result. + * Otherwise, drop the request pending an answer to the upcall. + */ +static int svcauth_gss_handle_init(struct svc_rqst *rqstp, + struct rpc_gss_wire_cred *gc, __be32 *authp) +{ + struct kvec *argv = &rqstp->rq_arg.head[0]; + struct kvec *resv = &rqstp->rq_res.head[0]; + struct rsi *rsip, rsikey; + int ret; + struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); + + memset(&rsikey, 0, sizeof(rsikey)); + ret = gss_read_verf(gc, argv, authp, + &rsikey.in_handle, &rsikey.in_token); + if (ret) + return ret; + /* Perform upcall, or find upcall result: */ rsip = rsi_lookup(sn->rsi_cache, &rsikey); rsi_free(&rsikey); @@ -1035,19 +1070,12 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp, ret = SVC_CLOSE; /* Got an answer to the upcall; use it: */ - if (gss_write_init_verf(sn->rsc_cache, rqstp, rsip)) + if (gss_write_init_verf(sn->rsc_cache, rqstp, + &rsip->out_handle, &rsip->major_status)) goto out; - if (resv->iov_len + 4 > PAGE_SIZE) - goto out; - svc_putnl(resv, RPC_SUCCESS); - if (svc_safe_putnetobj(resv, &rsip->out_handle)) - goto out; - if (resv->iov_len + 3 * 4 > PAGE_SIZE) - goto out; - svc_putnl(resv, rsip->major_status); - svc_putnl(resv, rsip->minor_status); - svc_putnl(resv, GSS_SEQ_WIN); - if (svc_safe_putnetobj(resv, &rsip->out_token)) + if (gss_write_resv(resv, PAGE_SIZE, + &rsip->out_handle, &rsip->out_token, + rsip->major_status, rsip->minor_status)) goto out; ret = SVC_COMPLETE; -- cgit v1.2.3