aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2007-10-26 13:31:52 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-01-30 02:05:44 -0500
commit6232dbbcffc617a5a47596b2ec347b24dc2dd2fd (patch)
tree2ebfdeaef4df7751a47dfaa4b200efd61303198b
parent8a8c74bf94fcdec058062d331b3d9777910778ab (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.c24
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
262nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) 262nfs_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");