diff options
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 63f2395c57ed..2723c1badd01 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -294,7 +294,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, | |||
294 | READ32(nace); | 294 | READ32(nace); |
295 | 295 | ||
296 | if (nace > NFS4_ACL_MAX) | 296 | if (nace > NFS4_ACL_MAX) |
297 | return nfserr_resource; | 297 | return nfserr_fbig; |
298 | 298 | ||
299 | *acl = nfs4_acl_new(nace); | 299 | *acl = nfs4_acl_new(nace); |
300 | if (*acl == NULL) | 300 | if (*acl == NULL) |
@@ -1222,7 +1222,6 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) | |||
1222 | } | 1222 | } |
1223 | write->wr_head.iov_base = p; | 1223 | write->wr_head.iov_base = p; |
1224 | write->wr_head.iov_len = avail; | 1224 | write->wr_head.iov_len = avail; |
1225 | WARN_ON(avail != (XDR_QUADLEN(avail) << 2)); | ||
1226 | write->wr_pagelist = argp->pagelist; | 1225 | write->wr_pagelist = argp->pagelist; |
1227 | 1226 | ||
1228 | len = XDR_QUADLEN(write->wr_buflen) << 2; | 1227 | len = XDR_QUADLEN(write->wr_buflen) << 2; |
@@ -2483,6 +2482,8 @@ out_acl: | |||
2483 | goto out; | 2482 | goto out; |
2484 | } | 2483 | } |
2485 | if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) { | 2484 | if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) { |
2485 | if ((buflen -= 16) < 0) | ||
2486 | goto out_resource; | ||
2486 | WRITE32(3); | 2487 | WRITE32(3); |
2487 | WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0); | 2488 | WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0); |
2488 | WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD1); | 2489 | WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD1); |
@@ -2499,8 +2500,10 @@ out: | |||
2499 | security_release_secctx(context, contextlen); | 2500 | security_release_secctx(context, contextlen); |
2500 | #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ | 2501 | #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ |
2501 | kfree(acl); | 2502 | kfree(acl); |
2502 | if (tempfh) | 2503 | if (tempfh) { |
2503 | fh_put(tempfh); | 2504 | fh_put(tempfh); |
2505 | kfree(tempfh); | ||
2506 | } | ||
2504 | return status; | 2507 | return status; |
2505 | out_nfserr: | 2508 | out_nfserr: |
2506 | status = nfserrno(err); | 2509 | status = nfserrno(err); |
@@ -3471,6 +3474,9 @@ nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
3471 | struct nfsd4_test_stateid_id *stateid, *next; | 3474 | struct nfsd4_test_stateid_id *stateid, *next; |
3472 | __be32 *p; | 3475 | __be32 *p; |
3473 | 3476 | ||
3477 | if (nfserr) | ||
3478 | return nfserr; | ||
3479 | |||
3474 | RESERVE_SPACE(4 + (4 * test_stateid->ts_num_ids)); | 3480 | RESERVE_SPACE(4 + (4 * test_stateid->ts_num_ids)); |
3475 | *p++ = htonl(test_stateid->ts_num_ids); | 3481 | *p++ = htonl(test_stateid->ts_num_ids); |
3476 | 3482 | ||
@@ -3579,8 +3585,6 @@ __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 pad) | |||
3579 | return 0; | 3585 | return 0; |
3580 | 3586 | ||
3581 | session = resp->cstate.session; | 3587 | session = resp->cstate.session; |
3582 | if (session == NULL) | ||
3583 | return 0; | ||
3584 | 3588 | ||
3585 | if (xb->page_len == 0) { | 3589 | if (xb->page_len == 0) { |
3586 | length = (char *)resp->p - (char *)xb->head[0].iov_base + pad; | 3590 | length = (char *)resp->p - (char *)xb->head[0].iov_base + pad; |
@@ -3620,9 +3624,17 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) | |||
3620 | BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) || | 3624 | BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) || |
3621 | !nfsd4_enc_ops[op->opnum]); | 3625 | !nfsd4_enc_ops[op->opnum]); |
3622 | op->status = nfsd4_enc_ops[op->opnum](resp, op->status, &op->u); | 3626 | op->status = nfsd4_enc_ops[op->opnum](resp, op->status, &op->u); |
3623 | /* nfsd4_check_drc_limit guarantees enough room for error status */ | 3627 | /* nfsd4_check_resp_size guarantees enough room for error status */ |
3624 | if (!op->status) | 3628 | if (!op->status) |
3625 | op->status = nfsd4_check_resp_size(resp, 0); | 3629 | op->status = nfsd4_check_resp_size(resp, 0); |
3630 | if (op->status == nfserr_resource && nfsd4_has_session(&resp->cstate)) { | ||
3631 | struct nfsd4_slot *slot = resp->cstate.slot; | ||
3632 | |||
3633 | if (slot->sl_flags & NFSD4_SLOT_CACHETHIS) | ||
3634 | op->status = nfserr_rep_too_big_to_cache; | ||
3635 | else | ||
3636 | op->status = nfserr_rep_too_big; | ||
3637 | } | ||
3626 | if (so) { | 3638 | if (so) { |
3627 | so->so_replay.rp_status = op->status; | 3639 | so->so_replay.rp_status = op->status; |
3628 | so->so_replay.rp_buflen = (char *)resp->p - (char *)(statp+1); | 3640 | so->so_replay.rp_buflen = (char *)resp->p - (char *)(statp+1); |
@@ -3691,6 +3703,12 @@ int nfsd4_release_compoundargs(void *rq, __be32 *p, void *resp) | |||
3691 | int | 3703 | int |
3692 | nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args) | 3704 | nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args) |
3693 | { | 3705 | { |
3706 | if (rqstp->rq_arg.head[0].iov_len % 4) { | ||
3707 | /* client is nuts */ | ||
3708 | dprintk("%s: compound not properly padded! (peeraddr=%pISc xid=0x%x)", | ||
3709 | __func__, svc_addr(rqstp), be32_to_cpu(rqstp->rq_xid)); | ||
3710 | return 0; | ||
3711 | } | ||
3694 | args->p = p; | 3712 | args->p = p; |
3695 | args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len; | 3713 | args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len; |
3696 | args->pagelist = rqstp->rq_arg.pages; | 3714 | args->pagelist = rqstp->rq_arg.pages; |