| From torvalds@osdl.org Sat Aug 6 11:33:12 2005 |
| Date: Sat, 6 Aug 2005 11:33:11 -0700 (PDT) |
| From: Linus Torvalds <torvalds@osdl.org> |
| To: Tim Yamin <plasmaroo@gentoo.org> |
| cc: "H. Peter Anvin" <hpa@zytor.com>, Chris Wright <chrisw@osdl.org>, |
| security@kernel.org |
| Subject: Check input buffer size in zisofs |
| |
| Add fakey 'deflateBound()' function to the in-kernel zlib routines |
| |
| It's not the real deflateBound() in newer zlib libraries, partly because |
| the upcoming usage of it won't have the "stream" available, so we can't |
| have the same interfaces anyway. |
| |
| This uses the new deflateBound() thing to sanity-check the input to the |
| zlib decompressor before we even bother to start reading in the blocks. |
| |
| Problem noted by Tim Yamin <plasmaroo@gentoo.org> |
| |
| Signed-off-by: Chris Wright <chrisw@osdl.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| Signed-off-by: H. Peter Anvin <hpa@zytor.com> |
| --- |
| fs/isofs/compress.c | 6 ++++++ |
| include/linux/zlib.h | 5 +++++ |
| 2 files changed, 11 insertions(+) |
| |
| Index: linux-2.6.12.y/include/linux/zlib.h |
| =================================================================== |
| --- linux-2.6.12.y.orig/include/linux/zlib.h |
| +++ linux-2.6.12.y/include/linux/zlib.h |
| @@ -506,6 +506,11 @@ extern int zlib_deflateReset (z_streamp |
| stream state was inconsistent (such as zalloc or state being NULL). |
| */ |
| |
| +static inline unsigned long deflateBound(unsigned long s) |
| +{ |
| + return s + ((s + 7) >> 3) + ((s + 63) >> 6) + 11; |
| +} |
| + |
| extern int zlib_deflateParams (z_streamp strm, int level, int strategy); |
| /* |
| Dynamically update the compression level and compression strategy. The |
| Index: linux-2.6.12.y/fs/isofs/compress.c |
| =================================================================== |
| --- linux-2.6.12.y.orig/fs/isofs/compress.c |
| +++ linux-2.6.12.y/fs/isofs/compress.c |
| @@ -129,8 +129,14 @@ static int zisofs_readpage(struct file * |
| cend = le32_to_cpu(*(__le32 *)(bh->b_data + (blockendptr & bufmask))); |
| brelse(bh); |
| |
| + if (cstart > cend) |
| + goto eio; |
| + |
| csize = cend-cstart; |
| |
| + if (csize > deflateBound(1UL << zisofs_block_shift)) |
| + goto eio; |
| + |
| /* Now page[] contains an array of pages, any of which can be NULL, |
| and the locks on which we hold. We should now read the data and |
| release the pages. If the pages are NULL the decompressed data |