diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2007-10-26 13:31:52 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-01-30 02:05:44 -0500 |
commit | 6232dbbcffc617a5a47596b2ec347b24dc2dd2fd (patch) | |
tree | 2ebfdeaef4df7751a47dfaa4b200efd61303198b | |
parent | 8a8c74bf94fcdec058062d331b3d9777910778ab (diff) |
NFS: Use unsigned intermediates for manipulating header lengths (NFSv2 XDR)
Clean up: prevent length underflow and mixed sign comparisons when
unmarshalling NFS version 2 read, readdir, and readlink replies.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/nfs2xdr.c | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index 668ab96c7b59..1f7ea675e0c5 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c | |||
@@ -262,7 +262,9 @@ static int | |||
262 | nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) | 262 | nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) |
263 | { | 263 | { |
264 | struct kvec *iov = req->rq_rcv_buf.head; | 264 | struct kvec *iov = req->rq_rcv_buf.head; |
265 | int status, count, recvd, hdrlen; | 265 | size_t hdrlen; |
266 | u32 count, recvd; | ||
267 | int status; | ||
266 | 268 | ||
267 | if ((status = ntohl(*p++))) | 269 | if ((status = ntohl(*p++))) |
268 | return -nfs_stat_to_errno(status); | 270 | return -nfs_stat_to_errno(status); |
@@ -273,7 +275,7 @@ nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) | |||
273 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; | 275 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; |
274 | if (iov->iov_len < hdrlen) { | 276 | if (iov->iov_len < hdrlen) { |
275 | dprintk("NFS: READ reply header overflowed:" | 277 | dprintk("NFS: READ reply header overflowed:" |
276 | "length %d > %Zu\n", hdrlen, iov->iov_len); | 278 | "length %Zu > %Zu\n", hdrlen, iov->iov_len); |
277 | return -errno_NFSERR_IO; | 279 | return -errno_NFSERR_IO; |
278 | } else if (iov->iov_len != hdrlen) { | 280 | } else if (iov->iov_len != hdrlen) { |
279 | dprintk("NFS: READ header is short. iovec will be shifted.\n"); | 281 | dprintk("NFS: READ header is short. iovec will be shifted.\n"); |
@@ -283,11 +285,11 @@ nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) | |||
283 | recvd = req->rq_rcv_buf.len - hdrlen; | 285 | recvd = req->rq_rcv_buf.len - hdrlen; |
284 | if (count > recvd) { | 286 | if (count > recvd) { |
285 | dprintk("NFS: server cheating in read reply: " | 287 | dprintk("NFS: server cheating in read reply: " |
286 | "count %d > recvd %d\n", count, recvd); | 288 | "count %u > recvd %u\n", count, recvd); |
287 | count = recvd; | 289 | count = recvd; |
288 | } | 290 | } |
289 | 291 | ||
290 | dprintk("RPC: readres OK count %d\n", count); | 292 | dprintk("RPC: readres OK count %u\n", count); |
291 | if (count < res->count) | 293 | if (count < res->count) |
292 | res->count = count; | 294 | res->count = count; |
293 | 295 | ||
@@ -423,9 +425,10 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy) | |||
423 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; | 425 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; |
424 | struct kvec *iov = rcvbuf->head; | 426 | struct kvec *iov = rcvbuf->head; |
425 | struct page **page; | 427 | struct page **page; |
426 | int hdrlen, recvd; | 428 | size_t hdrlen; |
429 | unsigned int pglen, recvd; | ||
430 | u32 len; | ||
427 | int status, nr; | 431 | int status, nr; |
428 | unsigned int len, pglen; | ||
429 | __be32 *end, *entry, *kaddr; | 432 | __be32 *end, *entry, *kaddr; |
430 | 433 | ||
431 | if ((status = ntohl(*p++))) | 434 | if ((status = ntohl(*p++))) |
@@ -434,7 +437,7 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy) | |||
434 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; | 437 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; |
435 | if (iov->iov_len < hdrlen) { | 438 | if (iov->iov_len < hdrlen) { |
436 | dprintk("NFS: READDIR reply header overflowed:" | 439 | dprintk("NFS: READDIR reply header overflowed:" |
437 | "length %d > %Zu\n", hdrlen, iov->iov_len); | 440 | "length %Zu > %Zu\n", hdrlen, iov->iov_len); |
438 | return -errno_NFSERR_IO; | 441 | return -errno_NFSERR_IO; |
439 | } else if (iov->iov_len != hdrlen) { | 442 | } else if (iov->iov_len != hdrlen) { |
440 | dprintk("NFS: READDIR header is short. iovec will be shifted.\n"); | 443 | dprintk("NFS: READDIR header is short. iovec will be shifted.\n"); |
@@ -576,7 +579,8 @@ nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy) | |||
576 | { | 579 | { |
577 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; | 580 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; |
578 | struct kvec *iov = rcvbuf->head; | 581 | struct kvec *iov = rcvbuf->head; |
579 | int hdrlen, len, recvd; | 582 | size_t hdrlen; |
583 | u32 len, recvd; | ||
580 | char *kaddr; | 584 | char *kaddr; |
581 | int status; | 585 | int status; |
582 | 586 | ||
@@ -584,14 +588,14 @@ nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy) | |||
584 | return -nfs_stat_to_errno(status); | 588 | return -nfs_stat_to_errno(status); |
585 | /* Convert length of symlink */ | 589 | /* Convert length of symlink */ |
586 | len = ntohl(*p++); | 590 | len = ntohl(*p++); |
587 | if (len >= rcvbuf->page_len || len <= 0) { | 591 | if (len >= rcvbuf->page_len) { |
588 | dprintk("nfs: server returned giant symlink!\n"); | 592 | dprintk("nfs: server returned giant symlink!\n"); |
589 | return -ENAMETOOLONG; | 593 | return -ENAMETOOLONG; |
590 | } | 594 | } |
591 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; | 595 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; |
592 | if (iov->iov_len < hdrlen) { | 596 | if (iov->iov_len < hdrlen) { |
593 | dprintk("NFS: READLINK reply header overflowed:" | 597 | dprintk("NFS: READLINK reply header overflowed:" |
594 | "length %d > %Zu\n", hdrlen, iov->iov_len); | 598 | "length %Zu > %Zu\n", hdrlen, iov->iov_len); |
595 | return -errno_NFSERR_IO; | 599 | return -errno_NFSERR_IO; |
596 | } else if (iov->iov_len != hdrlen) { | 600 | } else if (iov->iov_len != hdrlen) { |
597 | dprintk("NFS: READLINK header is short. iovec will be shifted.\n"); | 601 | dprintk("NFS: READLINK header is short. iovec will be shifted.\n"); |