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: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
parent
db3f58a95b
commit
47ee529864
@ -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;
|
||||||
|
@ -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;
|
struct nfsd4_slot *slot = resp->cstate.slot;
|
||||||
|
|
||||||
if (nfsd4_has_session(&resp->cstate)) {
|
if (buf->len + respsize <= buf->buflen)
|
||||||
struct nfsd4_slot *slot = resp->cstate.slot;
|
return nfs_ok;
|
||||||
|
if (!nfsd4_has_session(&resp->cstate))
|
||||||
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));
|
|
||||||
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
|
||||||
|
Loading…
Reference in New Issue
Block a user