Skip to content

Commit 72a1e53

Browse files
committed
SUNRPC: Use xdr_stream for encoding GSS reply verifiers
Done as part of hardening the server-side RPC header encoding path. Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent b2f42f1 commit 72a1e53

File tree

1 file changed

+8
-73
lines changed

1 file changed

+8
-73
lines changed

net/sunrpc/auth_gss/svcauth_gss.c

Lines changed: 8 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -693,28 +693,6 @@ static bool gss_check_seq_num(const struct svc_rqst *rqstp, struct rsc *rsci,
693693
goto out;
694694
}
695695

696-
static inline u32 round_up_to_quad(u32 i)
697-
{
698-
return (i + 3 ) & ~3;
699-
}
700-
701-
static inline int
702-
svc_safe_putnetobj(struct kvec *resv, struct xdr_netobj *o)
703-
{
704-
u8 *p;
705-
706-
if (resv->iov_len + 4 > PAGE_SIZE)
707-
return -1;
708-
svc_putnl(resv, o->len);
709-
p = resv->iov_base + resv->iov_len;
710-
resv->iov_len += round_up_to_quad(o->len);
711-
if (resv->iov_len > PAGE_SIZE)
712-
return -1;
713-
memcpy(p, o->data, o->len);
714-
memset(p + o->len, 0, round_up_to_quad(o->len) - o->len);
715-
return 0;
716-
}
717-
718696
/*
719697
* Decode and verify a Call's verifier field. For RPC_AUTH_GSS Calls,
720698
* the body of this field contains a variable length checksum.
@@ -772,42 +750,6 @@ svcauth_gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
772750
return SVC_OK;
773751
}
774752

775-
static int
776-
gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)
777-
{
778-
__be32 *xdr_seq;
779-
u32 maj_stat;
780-
struct xdr_buf verf_data;
781-
struct xdr_netobj mic;
782-
__be32 *p;
783-
struct kvec iov;
784-
int err = -1;
785-
786-
svc_putnl(rqstp->rq_res.head, RPC_AUTH_GSS);
787-
xdr_seq = kmalloc(4, GFP_KERNEL);
788-
if (!xdr_seq)
789-
return -ENOMEM;
790-
*xdr_seq = htonl(seq);
791-
792-
iov.iov_base = xdr_seq;
793-
iov.iov_len = 4;
794-
xdr_buf_from_iov(&iov, &verf_data);
795-
p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
796-
mic.data = (u8 *)(p + 1);
797-
maj_stat = gss_get_mic(ctx_id, &verf_data, &mic);
798-
if (maj_stat != GSS_S_COMPLETE)
799-
goto out;
800-
*p++ = htonl(mic.len);
801-
memset((u8 *)p + mic.len, 0, round_up_to_quad(mic.len) - mic.len);
802-
p += XDR_QUADLEN(mic.len);
803-
if (!xdr_ressize_check(rqstp, p))
804-
goto out;
805-
err = 0;
806-
out:
807-
kfree(xdr_seq);
808-
return err;
809-
}
810-
811753
/*
812754
* Construct and encode a Reply's verifier field. The verifier's body
813755
* field contains a variable-length checksum of the GSS sequence
@@ -1454,8 +1396,6 @@ svcauth_gss_proc_init(struct svc_rqst *rqstp, struct rpc_gss_wire_cred *gc)
14541396
u32 flavor, len;
14551397
void *body;
14561398

1457-
svcxdr_init_encode(rqstp);
1458-
14591399
/* Call's verf field: */
14601400
if (xdr_stream_decode_opaque_auth(xdr, &flavor, &body, &len) < 0)
14611401
return SVC_GARBAGE;
@@ -1642,15 +1582,15 @@ svcauth_gss_decode_credbody(struct xdr_stream *xdr,
16421582
static int
16431583
svcauth_gss_accept(struct svc_rqst *rqstp)
16441584
{
1645-
struct kvec *resv = &rqstp->rq_res.head[0];
16461585
struct gss_svc_data *svcdata = rqstp->rq_auth_data;
16471586
__be32 *rpcstart;
16481587
struct rpc_gss_wire_cred *gc;
16491588
struct rsc *rsci = NULL;
1650-
__be32 *reject_stat = resv->iov_base + resv->iov_len;
16511589
int ret;
16521590
struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id);
16531591

1592+
svcxdr_init_encode(rqstp);
1593+
16541594
rqstp->rq_auth_stat = rpc_autherr_badcred;
16551595
if (!svcdata)
16561596
svcdata = kmalloc(sizeof(*svcdata), GFP_KERNEL);
@@ -1700,28 +1640,25 @@ svcauth_gss_accept(struct svc_rqst *rqstp)
17001640
/* now act upon the command: */
17011641
switch (gc->gc_proc) {
17021642
case RPC_GSS_PROC_DESTROY:
1703-
if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
1643+
if (!svcauth_gss_encode_verf(rqstp, rsci->mechctx, gc->gc_seq))
17041644
goto auth_err;
17051645
/* Delete the entry from the cache_list and call cache_put */
17061646
sunrpc_cache_unhash(sn->rsc_cache, &rsci->h);
1707-
if (resv->iov_len + 4 > PAGE_SIZE)
1708-
goto drop;
1709-
svc_putnl(resv, RPC_SUCCESS);
1647+
if (xdr_stream_encode_u32(&rqstp->rq_res_stream, RPC_SUCCESS) < 0)
1648+
goto auth_err;
17101649
goto complete;
17111650
case RPC_GSS_PROC_DATA:
17121651
rqstp->rq_auth_stat = rpcsec_gsserr_ctxproblem;
1713-
svcdata->verf_start = resv->iov_base + resv->iov_len;
1714-
if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
1652+
svcdata->verf_start = xdr_reserve_space(&rqstp->rq_res_stream, 0);
1653+
if (!svcauth_gss_encode_verf(rqstp, rsci->mechctx, gc->gc_seq))
17151654
goto auth_err;
17161655
rqstp->rq_cred = rsci->cred;
17171656
get_group_info(rsci->cred.cr_group_info);
17181657
rqstp->rq_auth_stat = rpc_autherr_badcred;
17191658
switch (gc->gc_svc) {
17201659
case RPC_GSS_SVC_NONE:
1721-
svcxdr_init_encode(rqstp);
17221660
break;
17231661
case RPC_GSS_SVC_INTEGRITY:
1724-
svcxdr_init_encode(rqstp);
17251662
/* placeholders for body length and seq. number: */
17261663
xdr_reserve_space(&rqstp->rq_res_stream, XDR_UNIT * 2);
17271664
if (svcauth_gss_unwrap_integ(rqstp, gc->gc_seq,
@@ -1730,7 +1667,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp)
17301667
svcxdr_set_auth_slack(rqstp, RPC_MAX_AUTH_SIZE);
17311668
break;
17321669
case RPC_GSS_SVC_PRIVACY:
1733-
svcxdr_init_encode(rqstp);
17341670
/* placeholders for body length and seq. number: */
17351671
xdr_reserve_space(&rqstp->rq_res_stream, XDR_UNIT * 2);
17361672
if (svcauth_gss_unwrap_priv(rqstp, gc->gc_seq,
@@ -1755,8 +1691,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp)
17551691
ret = SVC_GARBAGE;
17561692
goto out;
17571693
auth_err:
1758-
/* Restore write pointer to its original value: */
1759-
xdr_ressize_check(rqstp, reject_stat);
1694+
xdr_truncate_encode(&rqstp->rq_res_stream, XDR_UNIT * 2);
17601695
ret = SVC_DENIED;
17611696
goto out;
17621697
complete:

0 commit comments

Comments
 (0)