From 099e99f09697793129674546a5d21219a786935e Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 4 Aug 2003 23:21:13 -0700 Subject: [PATCH] [PATCH] nfsv4 page boundary handling fixes. From: Galen Michael Elias This patch fixes two places where the handling of page boundaries was incorrect and caused to IO_ERR's when it shouldn't have. 1. In decode_write it was just a small typo. 2. In decode_compound we avoid using READ_BUF, but don't provide all of it's functionality, specifically crosses a page boundary. --- fs/nfsd/nfs4xdr.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index a0db2de6f9f72..986aed1b5ac08 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -880,7 +880,7 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) v++; write->wr_vec[v].iov_base = page_address(argp->pagelist[0]); argp->pagelist++; - if (len >= PAGE_SIZE) { + if (argp->pagelen >= PAGE_SIZE) { write->wr_vec[v].iov_len = PAGE_SIZE; argp->pagelen -= PAGE_SIZE; } else { @@ -934,16 +934,35 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) op = &argp->ops[i]; /* - * Before reading the opcode, we test for the 4-byte buffer - * overrun explicitly, instead of using READ_BUF(). This is - * because we want a missing opcode to be treated as opcode - * OP_WRITE+1, instead of a failed XDR. + * We can't use READ_BUF() here because we need to handle + * a missing opcode as an OP_WRITE + 1. So we need to check + * to see if we're truly at the end of our buffer or if there + * is another page we need to flip to. */ + if (argp->p == argp->end) { - op->opnum = OP_WRITE + 1; - op->status = nfserr_bad_xdr; - argp->opcnt = i+1; - break; + if (argp->pagelen < 4) { + /* There isn't an opcode still on the wire */ + op->opnum = OP_WRITE + 1; + op->status = nfserr_bad_xdr; + argp->opcnt = i+1; + break; + } + + /* + * False alarm. We just hit a page boundary, but there + * is still data available. Move pointer across page + * boundary. *snip from READ_BUF* + */ + argp->p = page_address(argp->pagelist[0]); + argp->pagelist++; + if (argp->pagelen < PAGE_SIZE) { + argp->end = p + (argp->pagelen>>2); + argp->pagelen = 0; + } else { + argp->end = p + (PAGE_SIZE>>2); + argp->pagelen -= PAGE_SIZE; + } } op->opnum = ntohl(*argp->p++); -- 2.53.0