aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4xdr.c
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2012-12-04 18:25:10 -0500
committerJ. Bruce Fields <bfields@redhat.com>2012-12-17 21:55:21 -0500
commitd5f50b0c290431c65377c4afa1c764e2c3fe5305 (patch)
tree9d08b4a0a8a1aed35de43ec55cd0a94fbab2e015 /fs/nfsd/nfs4xdr.c
parent9b3234b9220aae5387b60bc35a424ab6748b2b59 (diff)
nfsd4: fix oops on unusual readlike compound
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. Cc: stable@kernel.org Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r--fs/nfsd/nfs4xdr.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 3bf8a9d7f217..d7a3be5ab777 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2925,11 +2925,16 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
2925 len = maxcount; 2925 len = maxcount;
2926 v = 0; 2926 v = 0;
2927 while (len > 0) { 2927 while (len > 0) {
2928 pn = resp->rqstp->rq_resused++; 2928 pn = resp->rqstp->rq_resused;
2929 if (!resp->rqstp->rq_respages[pn]) { /* ran out of pages */
2930 maxcount -= len;
2931 break;
2932 }
2929 resp->rqstp->rq_vec[v].iov_base = 2933 resp->rqstp->rq_vec[v].iov_base =
2930 page_address(resp->rqstp->rq_respages[pn]); 2934 page_address(resp->rqstp->rq_respages[pn]);
2931 resp->rqstp->rq_vec[v].iov_len = 2935 resp->rqstp->rq_vec[v].iov_len =
2932 len < PAGE_SIZE ? len : PAGE_SIZE; 2936 len < PAGE_SIZE ? len : PAGE_SIZE;
2937 resp->rqstp->rq_resused++;
2933 v++; 2938 v++;
2934 len -= PAGE_SIZE; 2939 len -= PAGE_SIZE;
2935 } 2940 }
@@ -2975,6 +2980,8 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd
2975 return nfserr; 2980 return nfserr;
2976 if (resp->xbuf->page_len) 2981 if (resp->xbuf->page_len)
2977 return nfserr_resource; 2982 return nfserr_resource;
2983 if (!resp->rqstp->rq_respages[resp->rqstp->rq_resused])
2984 return nfserr_resource;
2978 2985
2979 page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]); 2986 page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]);
2980 2987
@@ -3024,6 +3031,8 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
3024 return nfserr; 3031 return nfserr;
3025 if (resp->xbuf->page_len) 3032 if (resp->xbuf->page_len)
3026 return nfserr_resource; 3033 return nfserr_resource;
3034 if (!resp->rqstp->rq_respages[resp->rqstp->rq_resused])
3035 return nfserr_resource;
3027 3036
3028 RESERVE_SPACE(NFS4_VERIFIER_SIZE); 3037 RESERVE_SPACE(NFS4_VERIFIER_SIZE);
3029 savep = p; 3038 savep = p;