The patch titled NFS: Check lengths more thoroughly in NFS4 readdir XDR decode has been added to the -mm tree. Its filename is nfs-check-lengths-more-thoroughly-in-nfs4-readdir-xdr-decode.patch See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find out what to do about this ------------------------------------------------------ Subject: NFS: Check lengths more thoroughly in NFS4 readdir XDR decode From: David Howells <dhowells@xxxxxxxxxx> Check the bounds of length specifiers more thoroughly in the XDR decoding of NFS4 readdir reply data. Currently, if the server returns a bitmap or attr length that causes the current decode point pointer to wrap, this could go undetected (consider a small "negative" length on a 32-bit machine). Also add a check into the main XDR decode handler to make sure that the amount of data is a multiple of four bytes (as specified by RFC-1014). This makes sure that we can do u32* pointer subtraction in the NFS client without risking an undefined result (the result is undefined if the pointers are not correctly aligned with respect to one another). Signed-off-by: David Howells <dhowells@xxxxxxxxxx> Cc: Trond Myklebust <trond.myklebust@xxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxx> --- fs/nfs/nfs4xdr.c | 22 +++++++++++----------- net/sunrpc/clnt.c | 11 +++++++++++ 2 files changed, 22 insertions(+), 11 deletions(-) diff -puN fs/nfs/nfs4xdr.c~nfs-check-lengths-more-thoroughly-in-nfs4-readdir-xdr-decode fs/nfs/nfs4xdr.c --- a/fs/nfs/nfs4xdr.c~nfs-check-lengths-more-thoroughly-in-nfs4-readdir-xdr-decode +++ a/fs/nfs/nfs4xdr.c @@ -3355,7 +3355,7 @@ static int decode_readdir(struct xdr_str struct kvec *iov = rcvbuf->head; unsigned int nr, pglen = rcvbuf->page_len; uint32_t *end, *entry, *p, *kaddr; - uint32_t len, attrlen; + uint32_t len, attrlen, xlen; int hdrlen, recvd, status; status = decode_op_hdr(xdr, OP_READDIR); @@ -3374,13 +3374,12 @@ static int decode_readdir(struct xdr_str if (pglen > recvd) pglen = recvd; xdr_read_pages(xdr, pglen); - BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE); kaddr = p = (uint32_t *) kmap_atomic(page, KM_USER0); - end = (uint32_t *) ((char *)p + pglen + readdir->pgbase); + end = p + ((pglen + readdir->pgbase) >> 2); entry = p; for (nr = 0; *p++; nr++) { - if (p + 3 > end) + if (end - p < 3) goto short_pkt; dprintk("cookie = %Lu, ", *((unsigned long long *)p)); p += 2; /* cookie */ @@ -3389,18 +3388,19 @@ static int decode_readdir(struct xdr_str printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len); goto err_unmap; } - dprintk("filename = %*s\n", len, (char *)p); - p += XDR_QUADLEN(len); - if (p + 1 > end) + xlen = XDR_QUADLEN(len); + if (end - p < xlen) goto short_pkt; + dprintk("filename = %*s\n", len, (char *)p); + p += xlen; len = ntohl(*p++); /* bitmap length */ - p += len; - if (p + 1 > end) + if (end - p < len) goto short_pkt; + p += len; attrlen = XDR_QUADLEN(ntohl(*p++)); - p += attrlen; /* attributes */ - if (p + 2 > end) + if (end - p < attrlen + 1) goto short_pkt; + p += attrlen; /* attributes */ entry = p; } if (!nr && (entry[0] != 0 || entry[1] == 0)) diff -puN net/sunrpc/clnt.c~nfs-check-lengths-more-thoroughly-in-nfs4-readdir-xdr-decode net/sunrpc/clnt.c --- a/net/sunrpc/clnt.c~nfs-check-lengths-more-thoroughly-in-nfs4-readdir-xdr-decode +++ a/net/sunrpc/clnt.c @@ -1181,6 +1181,17 @@ call_verify(struct rpc_task *task) u32 *p = iov->iov_base, n; int error = -EACCES; + if ((task->tk_rqstp->rq_rcv_buf.len & 3) != 0) { + /* RFC-1014 says that the representation of XDR data must be a + * multiple of four bytes + * - if it isn't pointer subtraction in the NFS client may give + * undefined results + */ + printk(KERN_WARNING + "call_verify: XDR representation not a multiple of" + " 4 bytes: 0x%x\n", task->tk_rqstp->rq_rcv_buf.len); + goto out_eio; + } if ((len -= 3) < 0) goto out_overflow; p += 1; /* skip XID */ _ Patches currently in -mm which might be from dhowells@xxxxxxxxxx are git-gfs2.patch git-nfs.patch nfs-replace-null-dentries-that-appear-in-readdirs-list-2.patch nfs-fix-up-warnings.patch nfs-check-lengths-more-thoroughly-in-nfs4-readdir-xdr-decode.patch binfmt_elf-consistently-use-loff_t.patch afs-add-lock-annotations-to-afs_proc_cell_servers_startstop.patch elf_fdpic_core_dump-dont-take-tasklist_lock.patch reiserfs-make-sure-all-dentries-refs-are-released-before-calling-kill_block_super-try-2.patch fs-cache-provide-a-filesystem-specific-syncable-page-bit.patch fs-cache-generic-filesystem-caching-facility.patch fs-cache-release-page-private-in-failed-readahead.patch fs-cache-release-page-private-after-failed-readahead-12.patch fs-cache-make-kafs-use-fs-cache.patch fs-cache-make-kafs-use-fs-cache-fix.patch fs-cache-make-kafs-use-fs-cache-12.patch fs-cache-make-kafs-use-fs-cache-12-fix.patch fs-cache-make-kafs-use-fs-cache-vs-streamline-generic_file_-interfaces-and-filemap.patch nfs-use-local-caching.patch nfs-use-local-caching-12.patch nfs-use-local-caching-12-fix.patch fs-cache-cachefiles-ia64-missing-copy_page-export.patch fs-cache-cachefiles-a-cache-that-backs-onto-a-mounted-filesystem.patch fs-cache-cachefiles-a-cache-that-backs-onto-a-mounted-filesystem-cachefiles-printk-format-warning.patch fs-cache-cachefiles-a-cache-that-backs-onto-a-mounted-filesystem-warning-fixes.patch autofs-make-sure-all-dentries-refs-are-released-before-calling-kill_anon_super.patch vfs-destroy-the-dentries-contributed-by-a-superblock-on-unmounting.patch vfs-make-filldir_t-and-struct-kstat-deal-in-64-bit-inode-numbers.patch vfs-make-filldir_t-and-struct-kstat-deal-in-64-bit-inode-numbers-alpha-fix.patch nfs-represent-64-bit-fileids-as-64-bit-inode-numbers-on-32-bit-systems.patch ecryptfs-get_sb_dev-fix.patch reiser4-get_sb_dev-fix.patch mutex-subsystem-synchro-test-module.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html