aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs2xdr.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-06-20 22:35:05 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-06-28 17:20:43 -0400
commit64bd577ea0021f5903505de061b3b7d8a785ee94 (patch)
tree7081480d903325bb82d2384b69cff4579f289de1 /fs/nfs/nfs2xdr.c
parentc337d3655ce85e12c7c476cb81406521926cacd2 (diff)
NFS: Let xdr_read_pages() check for buffer overflows
xdr_read_pages will already do all of the buffer overflow checks that are currently being open-coded in the various callers. This patch simplifies the existing code by replacing the open coded checks. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs2xdr.c')
-rw-r--r--fs/nfs/nfs2xdr.c22
1 files changed, 3 insertions, 19 deletions
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index db81166182c9..d04f0df7be55 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -106,19 +106,16 @@ static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
106static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_readres *result) 106static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_readres *result)
107{ 107{
108 u32 recvd, count; 108 u32 recvd, count;
109 size_t hdrlen;
110 __be32 *p; 109 __be32 *p;
111 110
112 p = xdr_inline_decode(xdr, 4); 111 p = xdr_inline_decode(xdr, 4);
113 if (unlikely(p == NULL)) 112 if (unlikely(p == NULL))
114 goto out_overflow; 113 goto out_overflow;
115 count = be32_to_cpup(p); 114 count = be32_to_cpup(p);
116 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; 115 recvd = xdr_read_pages(xdr, count);
117 recvd = xdr->buf->len - hdrlen;
118 if (unlikely(count > recvd)) 116 if (unlikely(count > recvd))
119 goto out_cheating; 117 goto out_cheating;
120out: 118out:
121 xdr_read_pages(xdr, count);
122 result->eof = 0; /* NFSv2 does not pass EOF flag on the wire. */ 119 result->eof = 0; /* NFSv2 does not pass EOF flag on the wire. */
123 result->count = count; 120 result->count = count;
124 return count; 121 return count;
@@ -440,7 +437,6 @@ static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length)
440static int decode_path(struct xdr_stream *xdr) 437static int decode_path(struct xdr_stream *xdr)
441{ 438{
442 u32 length, recvd; 439 u32 length, recvd;
443 size_t hdrlen;
444 __be32 *p; 440 __be32 *p;
445 441
446 p = xdr_inline_decode(xdr, 4); 442 p = xdr_inline_decode(xdr, 4);
@@ -449,12 +445,9 @@ static int decode_path(struct xdr_stream *xdr)
449 length = be32_to_cpup(p); 445 length = be32_to_cpup(p);
450 if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN)) 446 if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN))
451 goto out_size; 447 goto out_size;
452 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; 448 recvd = xdr_read_pages(xdr, length);
453 recvd = xdr->buf->len - hdrlen;
454 if (unlikely(length > recvd)) 449 if (unlikely(length > recvd))
455 goto out_cheating; 450 goto out_cheating;
456
457 xdr_read_pages(xdr, length);
458 xdr_terminate_string(xdr->buf, length); 451 xdr_terminate_string(xdr->buf, length);
459 return 0; 452 return 0;
460out_size: 453out_size:
@@ -972,16 +965,7 @@ out_overflow:
972 */ 965 */
973static int decode_readdirok(struct xdr_stream *xdr) 966static int decode_readdirok(struct xdr_stream *xdr)
974{ 967{
975 u32 recvd, pglen; 968 return xdr_read_pages(xdr, xdr->buf->page_len);
976 size_t hdrlen;
977
978 pglen = xdr->buf->page_len;
979 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
980 recvd = xdr->buf->len - hdrlen;
981 if (pglen > recvd)
982 pglen = recvd;
983 xdr_read_pages(xdr, pglen);
984 return pglen;
985} 969}
986 970
987static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req, 971static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req,