Commit db1d6165 authored by Chuck Lever's avatar Chuck Lever
Browse files

SUNRPC: Go back to using gsd->body_start



Now that svcauth_gss_prepare_to_wrap() no longer computes the
location of RPC header fields in the response buffer,
svcauth_gss_accept() can save the location of the databody
rather than the location of the verifier.

Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 4bcf0343
Loading
Loading
Loading
Loading
+36 −42
Original line number Diff line number Diff line
@@ -71,9 +71,7 @@
struct gss_svc_data {
	/* decoded gss client cred: */
	struct rpc_gss_wire_cred	clcred;
	/* save a pointer to the beginning of the encoded verifier,
	 * for use in encryption/checksumming in svcauth_gss_release: */
	__be32				*verf_start;
	u32				gsd_databody_offset;
	struct rsc			*rsci;

	/* for temporary results */
@@ -1595,7 +1593,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp)
	if (!svcdata)
		goto auth_err;
	rqstp->rq_auth_data = svcdata;
	svcdata->verf_start = NULL;
	svcdata->gsd_databody_offset = 0;
	svcdata->rsci = NULL;
	gc = &svcdata->clcred;

@@ -1647,11 +1645,11 @@ svcauth_gss_accept(struct svc_rqst *rqstp)
		goto complete;
	case RPC_GSS_PROC_DATA:
		rqstp->rq_auth_stat = rpcsec_gsserr_ctxproblem;
		svcdata->verf_start = xdr_reserve_space(&rqstp->rq_res_stream, 0);
		if (!svcauth_gss_encode_verf(rqstp, rsci->mechctx, gc->gc_seq))
			goto auth_err;
		if (!svcxdr_set_accept_stat(rqstp))
			goto auth_err;
		svcdata->gsd_databody_offset = xdr_stream_pos(&rqstp->rq_res_stream);
		rqstp->rq_cred = rsci->cred;
		get_group_info(rsci->cred.cr_group_info);
		rqstp->rq_auth_stat = rpc_autherr_badcred;
@@ -1705,30 +1703,24 @@ svcauth_gss_accept(struct svc_rqst *rqstp)
	return ret;
}

static __be32 *
static u32
svcauth_gss_prepare_to_wrap(struct svc_rqst *rqstp, struct gss_svc_data *gsd)
{
	__be32 *p;
	u32 verf_len;
	u32 offset;

	p = gsd->verf_start;
	gsd->verf_start = NULL;
	/* Release can be called twice, but we only wrap once. */
	offset = gsd->gsd_databody_offset;
	gsd->gsd_databody_offset = 0;

	/* AUTH_ERROR replies are not wrapped. */
	if (rqstp->rq_auth_stat != rpc_auth_ok)
		return NULL;

	/* Skip the verifier: */
	p += 1;
	verf_len = ntohl(*p++);
	p += XDR_QUADLEN(verf_len);
		return 0;

	/* Also don't wrap if the accept_stat is nonzero: */
	if (*rqstp->rq_accept_statp != rpc_success)
		return NULL;
		return 0;

	p++;
	return p;
	return offset;
}

/*
@@ -1756,21 +1748,21 @@ static int svcauth_gss_wrap_integ(struct svc_rqst *rqstp)
	struct xdr_buf *buf = xdr->buf;
	struct xdr_buf databody_integ;
	struct xdr_netobj checksum;
	u32 offset, len, maj_stat;
	__be32 *p;
	u32 offset, maj_stat;

	p = svcauth_gss_prepare_to_wrap(rqstp, gsd);
	if (p == NULL)
	offset = svcauth_gss_prepare_to_wrap(rqstp, gsd);
	if (!offset)
		goto out;

	offset = (u8 *)(p + 1) - (u8 *)buf->head[0].iov_base;
	len = buf->len - offset;
	if (xdr_buf_subsegment(buf, &databody_integ, offset, len))
	if (xdr_buf_subsegment(buf, &databody_integ, offset + XDR_UNIT,
			       buf->len - offset - XDR_UNIT))
		goto wrap_failed;
	/* Buffer space for these has already been reserved in
	 * svcauth_gss_accept(). */
	*p++ = cpu_to_be32(len);
	*p = cpu_to_be32(gc->gc_seq);
	if (xdr_encode_word(buf, offset, databody_integ.len))
		goto wrap_failed;
	if (xdr_encode_word(buf, offset + XDR_UNIT, gc->gc_seq))
		goto wrap_failed;

	checksum.data = gsd->gsd_scratch;
	maj_stat = gss_get_mic(gsd->rsci->mechctx, &databody_integ, &checksum);
@@ -1817,17 +1809,19 @@ static int svcauth_gss_wrap_priv(struct svc_rqst *rqstp)
	struct kvec *head = buf->head;
	struct kvec *tail = buf->tail;
	u32 offset, pad, maj_stat;
	__be32 *p, *lenp;
	__be32 *p;

	p = svcauth_gss_prepare_to_wrap(rqstp, gsd);
	if (p == NULL)
	offset = svcauth_gss_prepare_to_wrap(rqstp, gsd);
	if (!offset)
		return 0;

	lenp = p++;
	offset = (u8 *)p - (u8 *)head->iov_base;
	/* Buffer space for this field has already been reserved
	 * in svcauth_gss_accept(). */
	*p = cpu_to_be32(gc->gc_seq);
	/*
	 * Buffer space for this field has already been reserved
	 * in svcauth_gss_accept(). Note that the GSS sequence
	 * number is encrypted along with the RPC reply payload.
	 */
	if (xdr_encode_word(buf, offset + XDR_UNIT, gc->gc_seq))
		goto wrap_failed;

	/*
	 * If there is currently tail data, make sure there is
@@ -1863,12 +1857,15 @@ static int svcauth_gss_wrap_priv(struct svc_rqst *rqstp)
		tail->iov_len = 0;
	}

	maj_stat = gss_wrap(gsd->rsci->mechctx, offset, buf, buf->pages);
	maj_stat = gss_wrap(gsd->rsci->mechctx, offset + XDR_UNIT, buf,
			    buf->pages);
	if (maj_stat != GSS_S_COMPLETE)
		goto bad_wrap;

	*lenp = cpu_to_be32(buf->len - offset);
	pad = xdr_pad_size(buf->len - offset);
	/* Wrapping can change the size of databody_priv. */
	if (xdr_encode_word(buf, offset, buf->len - offset - XDR_UNIT))
		goto wrap_failed;
	pad = xdr_pad_size(buf->len - offset - XDR_UNIT);
	p = (__be32 *)(tail->iov_base + tail->iov_len);
	memset(p, 0, pad);
	tail->iov_len += pad;
@@ -1908,9 +1905,6 @@ svcauth_gss_release(struct svc_rqst *rqstp)
	gc = &gsd->clcred;
	if (gc->gc_proc != RPC_GSS_PROC_DATA)
		goto out;
	/* Release can be called twice, but we only wrap once. */
	if (gsd->verf_start == NULL)
		goto out;

	switch (gc->gc_svc) {
	case RPC_GSS_SVC_NONE: