Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

SUNRPC: Add svc_rqst::rq_auth_stat

I'd like to take commit 4532608d71c8 ("SUNRPC: Clean up generic
dispatcher code") even further by using only private local SVC
dispatchers for all kernel RPC services. This change would enable
the removal of the logic that switches between
svc_generic_dispatch() and a service's private dispatcher, and
simplify the invocation of the service's pc_release method
so that humans can visually verify that it is always invoked
properly.

All that will come later.

First, let's provide a better way to return authentication errors
from SVC dispatcher functions. Instead of overloading the dispatch
method's *statp argument, add a field to struct svc_rqst that can
hold an error value.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>

authored by

Chuck Lever and committed by
Anna Schumaker
438623a0 69f2cd6d

+46 -45
+1
include/linux/sunrpc/svc.h
··· 282 282 void * rq_argp; /* decoded arguments */ 283 283 void * rq_resp; /* xdr'd results */ 284 284 void * rq_auth_data; /* flavor-specific data */ 285 + __be32 rq_auth_stat; /* authentication status */ 285 286 int rq_auth_slack; /* extra space xdr code 286 287 * should leave in head 287 288 * for krb5i, krb5p.
+2 -2
include/linux/sunrpc/svcauth.h
··· 127 127 char * name; 128 128 struct module *owner; 129 129 int flavour; 130 - int (*accept)(struct svc_rqst *rq, __be32 *authp); 130 + int (*accept)(struct svc_rqst *rq); 131 131 int (*release)(struct svc_rqst *rq); 132 132 void (*domain_release)(struct auth_domain *); 133 133 int (*set_client)(struct svc_rqst *rq); ··· 149 149 150 150 struct svc_xprt; 151 151 152 - extern int svc_authenticate(struct svc_rqst *rqstp, __be32 *authp); 152 + extern int svc_authenticate(struct svc_rqst *rqstp); 153 153 extern int svc_authorise(struct svc_rqst *rqstp); 154 154 extern int svc_set_client(struct svc_rqst *rqstp); 155 155 extern int svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops);
+3 -3
include/trace/events/sunrpc.h
··· 1582 1582 { SVC_COMPLETE, "SVC_COMPLETE" }) 1583 1583 1584 1584 TRACE_EVENT(svc_authenticate, 1585 - TP_PROTO(const struct svc_rqst *rqst, int auth_res, __be32 auth_stat), 1585 + TP_PROTO(const struct svc_rqst *rqst, int auth_res), 1586 1586 1587 - TP_ARGS(rqst, auth_res, auth_stat), 1587 + TP_ARGS(rqst, auth_res), 1588 1588 1589 1589 TP_STRUCT__entry( 1590 1590 __field(u32, xid) ··· 1595 1595 TP_fast_assign( 1596 1596 __entry->xid = be32_to_cpu(rqst->rq_xid); 1597 1597 __entry->svc_status = auth_res; 1598 - __entry->auth_stat = be32_to_cpu(auth_stat); 1598 + __entry->auth_stat = be32_to_cpu(rqst->rq_auth_stat); 1599 1599 ), 1600 1600 1601 1601 TP_printk("xid=0x%08x auth_res=%s auth_stat=%s",
+21 -22
net/sunrpc/auth_gss/svcauth_gss.c
··· 707 707 /* 708 708 * Verify the checksum on the header and return SVC_OK on success. 709 709 * Otherwise, return SVC_DROP (in the case of a bad sequence number) 710 - * or return SVC_DENIED and indicate error in authp. 710 + * or return SVC_DENIED and indicate error in rqstp->rq_auth_stat. 711 711 */ 712 712 static int 713 713 gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci, 714 - __be32 *rpcstart, struct rpc_gss_wire_cred *gc, __be32 *authp) 714 + __be32 *rpcstart, struct rpc_gss_wire_cred *gc) 715 715 { 716 716 struct gss_ctx *ctx_id = rsci->mechctx; 717 717 struct xdr_buf rpchdr; ··· 725 725 iov.iov_len = (u8 *)argv->iov_base - (u8 *)rpcstart; 726 726 xdr_buf_from_iov(&iov, &rpchdr); 727 727 728 - *authp = rpc_autherr_badverf; 728 + rqstp->rq_auth_stat = rpc_autherr_badverf; 729 729 if (argv->iov_len < 4) 730 730 return SVC_DENIED; 731 731 flavor = svc_getnl(argv); ··· 737 737 if (rqstp->rq_deferred) /* skip verification of revisited request */ 738 738 return SVC_OK; 739 739 if (gss_verify_mic(ctx_id, &rpchdr, &checksum) != GSS_S_COMPLETE) { 740 - *authp = rpcsec_gsserr_credproblem; 740 + rqstp->rq_auth_stat = rpcsec_gsserr_credproblem; 741 741 return SVC_DENIED; 742 742 } 743 743 744 744 if (gc->gc_seq > MAXSEQ) { 745 745 trace_rpcgss_svc_seqno_large(rqstp, gc->gc_seq); 746 - *authp = rpcsec_gsserr_ctxproblem; 746 + rqstp->rq_auth_stat = rpcsec_gsserr_ctxproblem; 747 747 return SVC_DENIED; 748 748 } 749 749 if (!gss_check_seq_num(rqstp, rsci, gc->gc_seq)) ··· 1142 1142 } 1143 1143 1144 1144 static int gss_read_proxy_verf(struct svc_rqst *rqstp, 1145 - struct rpc_gss_wire_cred *gc, __be32 *authp, 1145 + struct rpc_gss_wire_cred *gc, 1146 1146 struct xdr_netobj *in_handle, 1147 1147 struct gssp_in_token *in_token) 1148 1148 { ··· 1151 1151 int pages, i, res, pgto, pgfrom; 1152 1152 size_t inlen, to_offs, from_offs; 1153 1153 1154 - res = gss_read_common_verf(gc, argv, authp, in_handle); 1154 + res = gss_read_common_verf(gc, argv, &rqstp->rq_auth_stat, in_handle); 1155 1155 if (res) 1156 1156 return res; 1157 1157 ··· 1227 1227 * Otherwise, drop the request pending an answer to the upcall. 1228 1228 */ 1229 1229 static int svcauth_gss_legacy_init(struct svc_rqst *rqstp, 1230 - struct rpc_gss_wire_cred *gc, __be32 *authp) 1230 + struct rpc_gss_wire_cred *gc) 1231 1231 { 1232 1232 struct kvec *argv = &rqstp->rq_arg.head[0]; 1233 1233 struct kvec *resv = &rqstp->rq_res.head[0]; ··· 1236 1236 struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id); 1237 1237 1238 1238 memset(&rsikey, 0, sizeof(rsikey)); 1239 - ret = gss_read_verf(gc, argv, authp, 1239 + ret = gss_read_verf(gc, argv, &rqstp->rq_auth_stat, 1240 1240 &rsikey.in_handle, &rsikey.in_token); 1241 1241 if (ret) 1242 1242 return ret; ··· 1339 1339 } 1340 1340 1341 1341 static int svcauth_gss_proxy_init(struct svc_rqst *rqstp, 1342 - struct rpc_gss_wire_cred *gc, __be32 *authp) 1342 + struct rpc_gss_wire_cred *gc) 1343 1343 { 1344 1344 struct kvec *resv = &rqstp->rq_res.head[0]; 1345 1345 struct xdr_netobj cli_handle; ··· 1351 1351 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1352 1352 1353 1353 memset(&ud, 0, sizeof(ud)); 1354 - ret = gss_read_proxy_verf(rqstp, gc, authp, 1355 - &ud.in_handle, &ud.in_token); 1354 + ret = gss_read_proxy_verf(rqstp, gc, &ud.in_handle, &ud.in_token); 1356 1355 if (ret) 1357 1356 return ret; 1358 1357 ··· 1524 1525 * response here and return SVC_COMPLETE. 1525 1526 */ 1526 1527 static int 1527 - svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) 1528 + svcauth_gss_accept(struct svc_rqst *rqstp) 1528 1529 { 1529 1530 struct kvec *argv = &rqstp->rq_arg.head[0]; 1530 1531 struct kvec *resv = &rqstp->rq_res.head[0]; ··· 1537 1538 int ret; 1538 1539 struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id); 1539 1540 1540 - *authp = rpc_autherr_badcred; 1541 + rqstp->rq_auth_stat = rpc_autherr_badcred; 1541 1542 if (!svcdata) 1542 1543 svcdata = kmalloc(sizeof(*svcdata), GFP_KERNEL); 1543 1544 if (!svcdata) ··· 1574 1575 if ((gc->gc_proc != RPC_GSS_PROC_DATA) && (rqstp->rq_proc != 0)) 1575 1576 goto auth_err; 1576 1577 1577 - *authp = rpc_autherr_badverf; 1578 + rqstp->rq_auth_stat = rpc_autherr_badverf; 1578 1579 switch (gc->gc_proc) { 1579 1580 case RPC_GSS_PROC_INIT: 1580 1581 case RPC_GSS_PROC_CONTINUE_INIT: 1581 1582 if (use_gss_proxy(SVC_NET(rqstp))) 1582 - return svcauth_gss_proxy_init(rqstp, gc, authp); 1583 + return svcauth_gss_proxy_init(rqstp, gc); 1583 1584 else 1584 - return svcauth_gss_legacy_init(rqstp, gc, authp); 1585 + return svcauth_gss_legacy_init(rqstp, gc); 1585 1586 case RPC_GSS_PROC_DATA: 1586 1587 case RPC_GSS_PROC_DESTROY: 1587 1588 /* Look up the context, and check the verifier: */ 1588 - *authp = rpcsec_gsserr_credproblem; 1589 + rqstp->rq_auth_stat = rpcsec_gsserr_credproblem; 1589 1590 rsci = gss_svc_searchbyctx(sn->rsc_cache, &gc->gc_ctx); 1590 1591 if (!rsci) 1591 1592 goto auth_err; 1592 - switch (gss_verify_header(rqstp, rsci, rpcstart, gc, authp)) { 1593 + switch (gss_verify_header(rqstp, rsci, rpcstart, gc)) { 1593 1594 case SVC_OK: 1594 1595 break; 1595 1596 case SVC_DENIED: ··· 1599 1600 } 1600 1601 break; 1601 1602 default: 1602 - *authp = rpc_autherr_rejectedcred; 1603 + rqstp->rq_auth_stat = rpc_autherr_rejectedcred; 1603 1604 goto auth_err; 1604 1605 } 1605 1606 ··· 1615 1616 svc_putnl(resv, RPC_SUCCESS); 1616 1617 goto complete; 1617 1618 case RPC_GSS_PROC_DATA: 1618 - *authp = rpcsec_gsserr_ctxproblem; 1619 + rqstp->rq_auth_stat = rpcsec_gsserr_ctxproblem; 1619 1620 svcdata->verf_start = resv->iov_base + resv->iov_len; 1620 1621 if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq)) 1621 1622 goto auth_err; 1622 1623 rqstp->rq_cred = rsci->cred; 1623 1624 get_group_info(rsci->cred.cr_group_info); 1624 - *authp = rpc_autherr_badcred; 1625 + rqstp->rq_auth_stat = rpc_autherr_badcred; 1625 1626 switch (gc->gc_svc) { 1626 1627 case RPC_GSS_SVC_NONE: 1627 1628 break;
+9 -8
net/sunrpc/svc.c
··· 1283 1283 struct svc_process_info process; 1284 1284 __be32 *statp; 1285 1285 u32 prog, vers; 1286 - __be32 auth_stat, rpc_stat; 1286 + __be32 rpc_stat; 1287 1287 int auth_res; 1288 1288 __be32 *reply_statp; 1289 1289 ··· 1326 1326 * We do this before anything else in order to get a decent 1327 1327 * auth verifier. 1328 1328 */ 1329 - auth_res = svc_authenticate(rqstp, &auth_stat); 1329 + auth_res = svc_authenticate(rqstp); 1330 1330 /* Also give the program a chance to reject this call: */ 1331 1331 if (auth_res == SVC_OK && progp) { 1332 - auth_stat = rpc_autherr_badcred; 1332 + rqstp->rq_auth_stat = rpc_autherr_badcred; 1333 1333 auth_res = progp->pg_authenticate(rqstp); 1334 1334 } 1335 1335 if (auth_res != SVC_OK) 1336 - trace_svc_authenticate(rqstp, auth_res, auth_stat); 1336 + trace_svc_authenticate(rqstp, auth_res); 1337 1337 switch (auth_res) { 1338 1338 case SVC_OK: 1339 1339 break; ··· 1392 1392 goto release_dropit; 1393 1393 if (*statp == rpc_garbage_args) 1394 1394 goto err_garbage; 1395 - auth_stat = svc_get_autherr(rqstp, statp); 1396 - if (auth_stat != rpc_auth_ok) 1395 + rqstp->rq_auth_stat = svc_get_autherr(rqstp, statp); 1396 + if (rqstp->rq_auth_stat != rpc_auth_ok) 1397 1397 goto err_release_bad_auth; 1398 1398 } else { 1399 1399 dprintk("svc: calling dispatcher\n"); ··· 1450 1450 if (procp->pc_release) 1451 1451 procp->pc_release(rqstp); 1452 1452 err_bad_auth: 1453 - dprintk("svc: authentication failed (%d)\n", ntohl(auth_stat)); 1453 + dprintk("svc: authentication failed (%d)\n", 1454 + be32_to_cpu(rqstp->rq_auth_stat)); 1454 1455 serv->sv_stats->rpcbadauth++; 1455 1456 /* Restore write pointer to location of accept status: */ 1456 1457 xdr_ressize_check(rqstp, reply_statp); 1457 1458 svc_putnl(resv, 1); /* REJECT */ 1458 1459 svc_putnl(resv, 1); /* AUTH_ERROR */ 1459 - svc_putnl(resv, ntohl(auth_stat)); /* status */ 1460 + svc_putu32(resv, rqstp->rq_auth_stat); /* status */ 1460 1461 goto sendit; 1461 1462 1462 1463 err_bad_prog:
+4 -4
net/sunrpc/svcauth.c
··· 59 59 } 60 60 61 61 int 62 - svc_authenticate(struct svc_rqst *rqstp, __be32 *authp) 62 + svc_authenticate(struct svc_rqst *rqstp) 63 63 { 64 64 rpc_authflavor_t flavor; 65 65 struct auth_ops *aops; 66 66 67 - *authp = rpc_auth_ok; 67 + rqstp->rq_auth_stat = rpc_auth_ok; 68 68 69 69 flavor = svc_getnl(&rqstp->rq_arg.head[0]); 70 70 ··· 72 72 73 73 aops = svc_get_auth_ops(flavor); 74 74 if (aops == NULL) { 75 - *authp = rpc_autherr_badcred; 75 + rqstp->rq_auth_stat = rpc_autherr_badcred; 76 76 return SVC_DENIED; 77 77 } 78 78 ··· 80 80 init_svc_cred(&rqstp->rq_cred); 81 81 82 82 rqstp->rq_authop = aops; 83 - return aops->accept(rqstp, authp); 83 + return aops->accept(rqstp); 84 84 } 85 85 EXPORT_SYMBOL_GPL(svc_authenticate); 86 86
+6 -6
net/sunrpc/svcauth_unix.c
··· 725 725 EXPORT_SYMBOL_GPL(svcauth_unix_set_client); 726 726 727 727 static int 728 - svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp) 728 + svcauth_null_accept(struct svc_rqst *rqstp) 729 729 { 730 730 struct kvec *argv = &rqstp->rq_arg.head[0]; 731 731 struct kvec *resv = &rqstp->rq_res.head[0]; ··· 736 736 737 737 if (svc_getu32(argv) != 0) { 738 738 dprintk("svc: bad null cred\n"); 739 - *authp = rpc_autherr_badcred; 739 + rqstp->rq_auth_stat = rpc_autherr_badcred; 740 740 return SVC_DENIED; 741 741 } 742 742 if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { 743 743 dprintk("svc: bad null verf\n"); 744 - *authp = rpc_autherr_badverf; 744 + rqstp->rq_auth_stat = rpc_autherr_badverf; 745 745 return SVC_DENIED; 746 746 } 747 747 ··· 785 785 786 786 787 787 static int 788 - svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) 788 + svcauth_unix_accept(struct svc_rqst *rqstp) 789 789 { 790 790 struct kvec *argv = &rqstp->rq_arg.head[0]; 791 791 struct kvec *resv = &rqstp->rq_res.head[0]; ··· 827 827 } 828 828 groups_sort(cred->cr_group_info); 829 829 if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { 830 - *authp = rpc_autherr_badverf; 830 + rqstp->rq_auth_stat = rpc_autherr_badverf; 831 831 return SVC_DENIED; 832 832 } 833 833 ··· 839 839 return SVC_OK; 840 840 841 841 badcred: 842 - *authp = rpc_autherr_badcred; 842 + rqstp->rq_auth_stat = rpc_autherr_badcred; 843 843 return SVC_DENIED; 844 844 } 845 845