diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-06-20 22:35:05 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-06-28 17:20:43 -0400 |
commit | 64bd577ea0021f5903505de061b3b7d8a785ee94 (patch) | |
tree | 7081480d903325bb82d2384b69cff4579f289de1 /fs/nfs/nfs2xdr.c | |
parent | c337d3655ce85e12c7c476cb81406521926cacd2 (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.c | 22 |
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) | |||
106 | static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_readres *result) | 106 | static 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; |
120 | out: | 118 | out: |
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) | |||
440 | static int decode_path(struct xdr_stream *xdr) | 437 | static 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; |
460 | out_size: | 453 | out_size: |
@@ -972,16 +965,7 @@ out_overflow: | |||
972 | */ | 965 | */ |
973 | static int decode_readdirok(struct xdr_stream *xdr) | 966 | static 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 | ||
987 | static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req, | 971 | static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req, |