Skip to content

Commit

Permalink
nfsd4: adjust buflen to session channel limit
Browse files Browse the repository at this point in the history
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: J. Bruce Fields <bfields@redhat.com>
  • Loading branch information
J. Bruce Fields committed May 30, 2014
1 parent db3f58a commit 47ee529
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 16 deletions.
11 changes: 11 additions & 0 deletions fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -2208,11 +2208,13 @@ nfsd4_sequence(struct svc_rqst *rqstp,
struct nfsd4_sequence *seq)
{
struct nfsd4_compoundres *resp = rqstp->rq_resp;
struct xdr_stream *xdr = &resp->xdr;
struct nfsd4_session *session;
struct nfs4_client *clp;
struct nfsd4_slot *slot;
struct nfsd4_conn *conn;
__be32 status;
int buflen;
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);

if (resp->opcnt != 1)
Expand Down Expand Up @@ -2281,6 +2283,15 @@ nfsd4_sequence(struct svc_rqst *rqstp,
if (status)
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 */
slot->sl_seqid = seq->seqid;
slot->sl_flags |= NFSD4_SLOT_INUSE;
Expand Down
24 changes: 8 additions & 16 deletions fs/nfsd/nfs4xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -3767,25 +3767,17 @@ static nfsd4_enc nfsd4_enc_ops[] = {
__be32 nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 respsize)
{
struct xdr_buf *buf = &resp->rqstp->rq_res;
struct nfsd4_session *session = resp->cstate.session;
struct nfsd4_slot *slot = resp->cstate.slot;

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

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

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));
if (buf->len + respsize <= buf->buflen)
return nfs_ok;
if (!nfsd4_has_session(&resp->cstate))
return nfserr_resource;
if (slot->sl_flags & NFSD4_SLOT_CACHETHIS) {
WARN_ON_ONCE(1);
return nfserr_rep_too_big_to_cache;
}

return 0;
return nfserr_rep_too_big;
}

void
Expand Down

0 comments on commit 47ee529

Please sign in to comment.