aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/callback_xdr.c
diff options
context:
space:
mode:
authorAndy Adamson <andros@netapp.com>2010-01-14 17:45:04 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-02-10 08:30:56 -0500
commit31d2b4356b054537c35f4f8a7533e0b4a494dcc6 (patch)
tree22a46ee42a65ad2f15785337a803305fbd018c14 /fs/nfs/callback_xdr.c
parent72ce2b3c064471fc511a9ca2fb6c38d90d2ab826 (diff)
nfs41: fix wrong error on callback header xdr overflow
Set NFS4ERR_RESOURCE as CB_COMPOUND status and do not return an op on decode_op_hdr or encode_op_hdr buffer overflow. NFS4ERR_RESOURCE is correct for v4.0. Will fix the return for v4.1 along with all the other NFS4ERR_RESOURCE errors in a later patch. Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/callback_xdr.c')
-rw-r--r--fs/nfs/callback_xdr.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 8e1a2511c8be..6ae327871b86 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -28,6 +28,9 @@
28 28
29#define NFSDBG_FACILITY NFSDBG_CALLBACK 29#define NFSDBG_FACILITY NFSDBG_CALLBACK
30 30
31/* Internal error code */
32#define NFS4ERR_RESOURCE_HDR 11050
33
31typedef __be32 (*callback_process_op_t)(void *, void *); 34typedef __be32 (*callback_process_op_t)(void *, void *);
32typedef __be32 (*callback_decode_arg_t)(struct svc_rqst *, struct xdr_stream *, void *); 35typedef __be32 (*callback_decode_arg_t)(struct svc_rqst *, struct xdr_stream *, void *);
33typedef __be32 (*callback_encode_res_t)(struct svc_rqst *, struct xdr_stream *, void *); 36typedef __be32 (*callback_encode_res_t)(struct svc_rqst *, struct xdr_stream *, void *);
@@ -173,7 +176,7 @@ static __be32 decode_op_hdr(struct xdr_stream *xdr, unsigned int *op)
173 __be32 *p; 176 __be32 *p;
174 p = read_buf(xdr, 4); 177 p = read_buf(xdr, 4);
175 if (unlikely(p == NULL)) 178 if (unlikely(p == NULL))
176 return htonl(NFS4ERR_RESOURCE); 179 return htonl(NFS4ERR_RESOURCE_HDR);
177 *op = ntohl(*p); 180 *op = ntohl(*p);
178 return 0; 181 return 0;
179} 182}
@@ -465,7 +468,7 @@ static __be32 encode_op_hdr(struct xdr_stream *xdr, uint32_t op, __be32 res)
465 468
466 p = xdr_reserve_space(xdr, 8); 469 p = xdr_reserve_space(xdr, 8);
467 if (unlikely(p == NULL)) 470 if (unlikely(p == NULL))
468 return htonl(NFS4ERR_RESOURCE); 471 return htonl(NFS4ERR_RESOURCE_HDR);
469 *p++ = htonl(op); 472 *p++ = htonl(op);
470 *p = res; 473 *p = res;
471 return 0; 474 return 0;
@@ -605,17 +608,15 @@ static __be32 process_op(uint32_t minorversion, int nop,
605 struct xdr_stream *xdr_out, void *resp) 608 struct xdr_stream *xdr_out, void *resp)
606{ 609{
607 struct callback_op *op = &callback_ops[0]; 610 struct callback_op *op = &callback_ops[0];
608 unsigned int op_nr = OP_CB_ILLEGAL; 611 unsigned int op_nr;
609 __be32 status; 612 __be32 status;
610 long maxlen; 613 long maxlen;
611 __be32 res; 614 __be32 res;
612 615
613 dprintk("%s: start\n", __func__); 616 dprintk("%s: start\n", __func__);
614 status = decode_op_hdr(xdr_in, &op_nr); 617 status = decode_op_hdr(xdr_in, &op_nr);
615 if (unlikely(status)) { 618 if (unlikely(status))
616 status = htonl(NFS4ERR_OP_ILLEGAL); 619 return status;
617 goto out;
618 }
619 620
620 dprintk("%s: minorversion=%d nop=%d op_nr=%u\n", 621 dprintk("%s: minorversion=%d nop=%d op_nr=%u\n",
621 __func__, minorversion, nop, op_nr); 622 __func__, minorversion, nop, op_nr);
@@ -624,7 +625,7 @@ static __be32 process_op(uint32_t minorversion, int nop,
624 preprocess_nfs4_op(op_nr, &op); 625 preprocess_nfs4_op(op_nr, &op);
625 if (status == htonl(NFS4ERR_OP_ILLEGAL)) 626 if (status == htonl(NFS4ERR_OP_ILLEGAL))
626 op_nr = OP_CB_ILLEGAL; 627 op_nr = OP_CB_ILLEGAL;
627out: 628
628 maxlen = xdr_out->end - xdr_out->p; 629 maxlen = xdr_out->end - xdr_out->p;
629 if (maxlen > 0 && maxlen < PAGE_SIZE) { 630 if (maxlen > 0 && maxlen < PAGE_SIZE) {
630 if (likely(status == 0 && op->decode_args != NULL)) 631 if (likely(status == 0 && op->decode_args != NULL))
@@ -635,8 +636,8 @@ out:
635 status = htonl(NFS4ERR_RESOURCE); 636 status = htonl(NFS4ERR_RESOURCE);
636 637
637 res = encode_op_hdr(xdr_out, op_nr, status); 638 res = encode_op_hdr(xdr_out, op_nr, status);
638 if (status == 0) 639 if (unlikely(res))
639 status = res; 640 return res;
640 if (op->encode_res != NULL && status == 0) 641 if (op->encode_res != NULL && status == 0)
641 status = op->encode_res(rqstp, xdr_out, resp); 642 status = op->encode_res(rqstp, xdr_out, resp);
642 dprintk("%s: done, status = %d\n", __func__, ntohl(status)); 643 dprintk("%s: done, status = %d\n", __func__, ntohl(status));
@@ -677,6 +678,13 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
677 nops++; 678 nops++;
678 } 679 }
679 680
681 /* Buffer overflow in decode_ops_hdr or encode_ops_hdr. Return
682 * resource error in cb_compound status without returning op */
683 if (unlikely(status == htonl(NFS4ERR_RESOURCE_HDR))) {
684 status = htonl(NFS4ERR_RESOURCE);
685 nops--;
686 }
687
680 *hdr_res.status = status; 688 *hdr_res.status = status;
681 *hdr_res.nops = htonl(nops); 689 *hdr_res.nops = htonl(nops);
682 dprintk("%s: done, status = %u\n", __func__, ntohl(status)); 690 dprintk("%s: done, status = %u\n", __func__, ntohl(status));