Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 47ee5298 authored by J. Bruce Fields's avatar J. Bruce Fields
Browse files

nfsd4: adjust buflen to session channel limit



We can simplify session limit enforcement by restricting the xdr buflen
to the session size.

Also fix a preexisting bug: we should really have been taking into
account the auth-required space when comparing against session limits,
which are limits on the size of the entire rpc reply, including any krb5
overhead.

Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent db3f58a9
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
@@ -2208,11 +2208,13 @@ nfsd4_sequence(struct svc_rqst *rqstp,
	       struct nfsd4_sequence *seq)
	       struct nfsd4_sequence *seq)
{
{
	struct nfsd4_compoundres *resp = rqstp->rq_resp;
	struct nfsd4_compoundres *resp = rqstp->rq_resp;
	struct xdr_stream *xdr = &resp->xdr;
	struct nfsd4_session *session;
	struct nfsd4_session *session;
	struct nfs4_client *clp;
	struct nfs4_client *clp;
	struct nfsd4_slot *slot;
	struct nfsd4_slot *slot;
	struct nfsd4_conn *conn;
	struct nfsd4_conn *conn;
	__be32 status;
	__be32 status;
	int buflen;
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);


	if (resp->opcnt != 1)
	if (resp->opcnt != 1)
@@ -2281,6 +2283,15 @@ nfsd4_sequence(struct svc_rqst *rqstp,
	if (status)
	if (status)
		goto out_put_session;
		goto out_put_session;


	buflen = (seq->cachethis) ?
			session->se_fchannel.maxresp_cached :
			session->se_fchannel.maxresp_sz;
	status = (seq->cachethis) ? nfserr_rep_too_big_to_cache :
				    nfserr_rep_too_big;
	if (xdr_restrict_buflen(xdr, buflen - 2 * RPC_MAX_AUTH_SIZE))
		goto out_put_session;

	status = nfs_ok;
	/* Success! bump slot seqid */
	/* Success! bump slot seqid */
	slot->sl_seqid = seq->seqid;
	slot->sl_seqid = seq->seqid;
	slot->sl_flags |= NFSD4_SLOT_INUSE;
	slot->sl_flags |= NFSD4_SLOT_INUSE;
+8 −16
Original line number Original line Diff line number Diff line
@@ -3767,25 +3767,17 @@ static nfsd4_enc nfsd4_enc_ops[] = {
__be32 nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 respsize)
__be32 nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 respsize)
{
{
	struct xdr_buf *buf = &resp->rqstp->rq_res;
	struct xdr_buf *buf = &resp->rqstp->rq_res;
	struct nfsd4_session *session = resp->cstate.session;

	if (nfsd4_has_session(&resp->cstate)) {
	struct nfsd4_slot *slot = resp->cstate.slot;
	struct nfsd4_slot *slot = resp->cstate.slot;


		if (buf->len + respsize > session->se_fchannel.maxresp_sz)
	if (buf->len + respsize <= buf->buflen)
			return nfserr_rep_too_big;
		return nfs_ok;

	if (!nfsd4_has_session(&resp->cstate))
		if ((slot->sl_flags & NFSD4_SLOT_CACHETHIS) &&
		    buf->len + respsize > session->se_fchannel.maxresp_cached)
			return nfserr_rep_too_big_to_cache;
	}

	if (buf->len + respsize > buf->buflen) {
		WARN_ON_ONCE(nfsd4_has_session(&resp->cstate));
		return nfserr_resource;
		return nfserr_resource;
	if (slot->sl_flags & NFSD4_SLOT_CACHETHIS) {
		WARN_ON_ONCE(1);
		return nfserr_rep_too_big_to_cache;
	}
	}

	return nfserr_rep_too_big;
	return 0;
}
}


void
void