| From d5f50b0c290431c65377c4afa1c764e2c3fe5305 Mon Sep 17 00:00:00 2001 |
| From: "J. Bruce Fields" <bfields@redhat.com> |
| Date: Tue, 4 Dec 2012 18:25:10 -0500 |
| Subject: nfsd4: fix oops on unusual readlike compound |
| |
| From: "J. Bruce Fields" <bfields@redhat.com> |
| |
| commit d5f50b0c290431c65377c4afa1c764e2c3fe5305 upstream. |
| |
| If the argument and reply together exceed the maximum payload size, then |
| a reply with a read-like operation can overlow the rq_pages array. |
| |
| Signed-off-by: J. Bruce Fields <bfields@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/nfsd/nfs4xdr.c | 11 ++++++++++- |
| 1 file changed, 10 insertions(+), 1 deletion(-) |
| |
| --- a/fs/nfsd/nfs4xdr.c |
| +++ b/fs/nfsd/nfs4xdr.c |
| @@ -2946,11 +2946,16 @@ nfsd4_encode_read(struct nfsd4_compoundr |
| len = maxcount; |
| v = 0; |
| while (len > 0) { |
| - pn = resp->rqstp->rq_resused++; |
| + pn = resp->rqstp->rq_resused; |
| + if (!resp->rqstp->rq_respages[pn]) { /* ran out of pages */ |
| + maxcount -= len; |
| + break; |
| + } |
| resp->rqstp->rq_vec[v].iov_base = |
| page_address(resp->rqstp->rq_respages[pn]); |
| resp->rqstp->rq_vec[v].iov_len = |
| len < PAGE_SIZE ? len : PAGE_SIZE; |
| + resp->rqstp->rq_resused++; |
| v++; |
| len -= PAGE_SIZE; |
| } |
| @@ -2996,6 +3001,8 @@ nfsd4_encode_readlink(struct nfsd4_compo |
| return nfserr; |
| if (resp->xbuf->page_len) |
| return nfserr_resource; |
| + if (!resp->rqstp->rq_respages[resp->rqstp->rq_resused]) |
| + return nfserr_resource; |
| |
| page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]); |
| |
| @@ -3045,6 +3052,8 @@ nfsd4_encode_readdir(struct nfsd4_compou |
| return nfserr; |
| if (resp->xbuf->page_len) |
| return nfserr_resource; |
| + if (!resp->rqstp->rq_respages[resp->rqstp->rq_resused]) |
| + return nfserr_resource; |
| |
| RESERVE_SPACE(NFS4_VERIFIER_SIZE); |
| savep = p; |