Please unblock squashfs 3.0-6.1
Hi,
version 3.0-6.1 of squashfs does fix the security problem in #415530,
please unblock the package, debdiff is attached.
Regards,
Daniel
--
Address: Daniel Baumann, Burgunderstrasse 3, CH-4562 Biberist
Email: daniel.baumann@panthera-systems.net
Internet: http://people.panthera-systems.net/~daniel-baumann/
diff -u squashfs-3.1r2/debian/changelog squashfs-3.1r2/debian/changelog
--- squashfs-3.1r2/debian/changelog
+++ squashfs-3.1r2/debian/changelog
@@ -1,3 +1,12 @@
+squashfs (1:3.1r2-6.1) unstable; urgency=high
+
+ * Non-maintainer upload.
+ * Added patch from upstream to linux-2.6.18/squashfs3.1-patch to fix kernel
+ crash on special crafted squashfs file systems CVE-2006-5701
+ (Closes: #415530).
+
+ -- Daniel Baumann <daniel@debian.org> Fri, 30 Mar 2007 08:52:00 +0200
+
squashfs (1:3.1r2-6) unstable; urgency=low
* Add manpage for unsquashfs command.
only in patch2:
unchanged:
--- squashfs-3.1r2.orig/linux-2.6.18/squashfs3.1-patch
+++ squashfs-3.1r2/linux-2.6.18/squashfs3.1-patch
@@ -87,7 +87,7 @@
diff --new-file -urp linux-2.6.18/fs/squashfs/inode.c linux-2.6.18-squashfs3.1/fs/squashfs/inode.c
--- linux-2.6.18/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.18-squashfs3.1/fs/squashfs/inode.c 2006-08-21 00:15:29.000000000 +0100
-@@ -0,0 +1,2156 @@
+@@ -0,0 +1,2194 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
@@ -263,14 +263,15 @@
+
+SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,
+ long long index, unsigned int length,
-+ long long *next_index)
++ long long *next_index, int srclength)
+{
+ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
+ struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>
+ msblk->devblksize_log2) + 2];
+ unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
+ unsigned int cur_index = index >> msblk->devblksize_log2;
-+ int bytes, avail_bytes, b = 0, k;
++ int bytes, avail_bytes, b = 0, k = 0;
+ char *c_buffer;
+ unsigned int compressed;
+ unsigned int c_byte = length;
@@ -281,8 +282,11 @@
+ c_buffer = compressed ? msblk->read_data : buffer;
+ c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
+
-+ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
-+ ? "" : "un", (unsigned int) c_byte);
++ TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, compressed
++ ? "" : "un", (unsigned int) c_byte, srclength);
++
++ if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used)
++ goto read_failure;
+
+ if (!(bh[0] = sb_getblk(s, cur_index)))
+ goto block_release;
@@ -294,6 +298,9 @@
+ }
+ ll_rw_block(READ, b, bh);
+ } else {
++ if (index < 0 || (index + 2) > sblk->bytes_used)
++ goto read_failure;
++
+ if (!(bh[0] = get_block_length(s, &cur_index, &offset,
+ &c_byte)))
+ goto read_failure;
@@ -306,6 +313,9 @@
+ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
+ ? "" : "un", (unsigned int) c_byte);
+
++ if (c_byte > srclength || (index + c_byte) > sblk->bytes_used)
++ goto read_failure;
++
+ for (b = 1; bytes < c_byte; b++) {
+ if (!(bh[b] = sb_getblk(s, ++cur_index)))
+ goto block_release;
@@ -317,7 +327,7 @@
+ if (compressed)
+ down(&msblk->read_data_mutex);
+
-+ for (bytes = 0, k = 0; k < b; k++) {
++ for (bytes = 0; k < b; k++) {
+ avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
+ msblk->devblksize - offset :
+ c_byte - bytes;
@@ -339,7 +349,7 @@
+ msblk->stream.next_in = c_buffer;
+ msblk->stream.avail_in = c_byte;
+ msblk->stream.next_out = buffer;
-+ msblk->stream.avail_out = msblk->read_size;
++ msblk->stream.avail_out = srclength;
+
+ if (((zlib_err = zlib_inflateInit(&msblk->stream)) != Z_OK) ||
+ ((zlib_err = zlib_inflate(&msblk->stream, Z_FINISH))
@@ -361,8 +371,8 @@
+ return bytes;
+
+block_release:
-+ while (--b >= 0)
-+ brelse(bh[b]);
++ for (; k < b; k++)
++ brelse(bh[k]);
+
+read_failure:
+ ERROR("sb_bread failed reading block 0x%x\n", cur_index);
@@ -426,14 +436,20 @@
+ msblk->block_cache[i].block = SQUASHFS_USED_BLK;
+ up(&msblk->block_cache_mutex);
+
-+ if (!(msblk->block_cache[i].length =
-+ squashfs_read_data(s,
-+ msblk->block_cache[i].data,
-+ block, 0, &next_index))) {
-+ ERROR("Unable to read cache block [%llx:%x]\n",
-+ block, offset);
-+ goto out;
-+ }
++ msblk->block_cache[i].length = squashfs_read_data(s,
++ msblk->block_cache[i].data, block, 0, &next_index,
++ SQUASHFS_METADATA_SIZE);
++
++ if (msblk->block_cache[i].length == 0) {
++ ERROR("Unable to read cache block [%llx:%x]\n",
++ block, offset);
++ down(&msblk->block_cache_mutex);
++ msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
++ kfree(msblk->block_cache[i].data);
++ wake_up(&msblk->waitq);
++ up(&msblk->block_cache_mutex);
++ goto out;
++ }
+
+ down(&msblk->block_cache_mutex);
+ wake_up(&msblk->waitq);
@@ -447,7 +463,11 @@
+ continue;
+ }
+
-+ if ((bytes = msblk->block_cache[i].length - offset) >= length) {
++ bytes = msblk->block_cache[i].length - offset;
++
++ if (bytes < 1)
++ goto out;
++ else if (bytes >= length) {
+ if (buffer)
+ memcpy(buffer, msblk->block_cache[i].data +
+ offset, length);
@@ -532,6 +552,7 @@
+{
+ int i, n;
+ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
+
+ while ( 1 ) {
+ down(&msblk->fragment_mutex);
@@ -577,7 +598,8 @@
+
+ if (!(msblk->fragment[i].length = squashfs_read_data(s,
+ msblk->fragment[i].data,
-+ start_block, length, NULL))) {
++ start_block, length, NULL,
++ sblk->block_size))) {
+ ERROR("Unable to read fragment cache block "
+ "[%llx]\n", start_block);
+ msblk->fragment[i].locked = 0;
@@ -966,6 +988,10 @@
+{
+ struct squashfs_sb_info *msblk = s->s_fs_info;
+ struct squashfs_super_block *sblk = &msblk->sblk;
++ unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments);
++
++ if (length == 0)
++ return 1;
+
+ /* Allocate fragment index table */
+ if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES
@@ -974,13 +1000,9 @@
+ return 0;
+ }
+
-+ if (SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments) &&
-+ !squashfs_read_data(s, (char *)
-+ msblk->fragment_index,
-+ sblk->fragment_table_start,
-+ SQUASHFS_FRAGMENT_INDEX_BYTES
-+ (sblk->fragments) |
-+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++ if (!squashfs_read_data(s, (char *) msblk->fragment_index,
++ sblk->fragment_table_start, length |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {
+ ERROR("unable to read fragment index table\n");
+ return 0;
+ }
@@ -1072,9 +1094,11 @@
+ init_waitqueue_head(&msblk->waitq);
+ init_waitqueue_head(&msblk->fragment_wait_queue);
+
++ sblk->bytes_used = sizeof(struct squashfs_super_block);
+ if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
+ sizeof(struct squashfs_super_block) |
-+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL,
++ sizeof(struct squashfs_super_block))) {
+ SERROR("unable to read superblock\n");
+ goto failed_mount;
+ }
@@ -1102,6 +1126,15 @@
+ if(!supported_squashfs_filesystem(msblk, silent))
+ goto failed_mount;
+
++ /* Check the filesystem does not extend beyond the end of the
++ block device */
++ if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode))
++ goto failed_mount;
++
++ /* Check the root inode for sanity */
++ if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE)
++ goto failed_mount;
++
+ TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));
+ TRACE("Inodes are %scompressed\n",
+ SQUASHFS_UNCOMPRESSED_INODES
@@ -1171,7 +1204,9 @@
+ if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,
+ ((sblk->no_uids + sblk->no_guids) *
+ sizeof(unsigned int)) |
-+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL,
++ (sblk->no_uids + sblk->no_guids) *
++ sizeof(unsigned int))) {
+ ERROR("unable to read uid/gid table\n");
+ goto failed_mount;
+ }
@@ -1182,7 +1217,9 @@
+ if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,
+ ((sblk->no_uids + sblk->no_guids) *
+ sizeof(unsigned int)) |
-+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL,
++ (sblk->no_uids + sblk->no_guids) *
++ sizeof(unsigned int))) {
+ ERROR("unable to read uid/gid table\n");
+ goto failed_mount;
+ }
@@ -1608,7 +1645,8 @@
+ down(&msblk->read_page_mutex);
+
+ if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,
-+ block, bsize, NULL))) {
++ block, bsize, NULL,
++ msblk->read_size))) {
+ ERROR("Unable to read page, block %llx, size %x\n", block,
+ bsize);
+ up(&msblk->read_page_mutex);
@@ -1708,15 +1746,12 @@
+
+ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
+ PAGE_CACHE_SHIFT)) {
-+ pageaddr = kmap_atomic(page, KM_USER0);
+ block_list = NULL;
+ goto skip_read;
+ }
+
+ if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {
+ ERROR("Failed to allocate block_list\n");
-+ pageaddr = kmap_atomic(page, KM_USER0);
-+ block_list = NULL;
+ goto skip_read;
+ }
+
@@ -1728,11 +1763,12 @@
+
+ down(&msblk->read_page_mutex);
+ bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
-+ bsize, NULL);
-+ pageaddr = kmap_atomic(page, KM_USER0);
-+ if (bytes)
++ bsize, NULL, msblk->read_size);
++ if (bytes) {
++ pageaddr = kmap_atomic(page, KM_USER0);
+ memcpy(pageaddr, msblk->read_page, bytes);
-+ else
++ kunmap_atomic(pageaddr, KM_USER0);
++ } else
+ ERROR("Unable to read page, block %llx, size %x\n",
+ block, bsize);
+ up(&msblk->read_page_mutex);
@@ -1742,11 +1778,12 @@
+ SQUASHFS_I(inode)->
+ u.s1.fragment_start_block,
+ SQUASHFS_I(inode)-> u.s1.fragment_size);
-+ pageaddr = kmap_atomic(page, KM_USER0);
+ if (fragment) {
+ bytes = i_size_read(inode) & (sblk->block_size - 1);
++ pageaddr = kmap_atomic(page, KM_USER0);
+ memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->
+ u.s1.fragment_offset, bytes);
++ kunmap_atomic(pageaddr, KM_USER0);
+ release_cached_fragment(msblk, fragment);
+ } else
+ ERROR("Unable to read page, block %llx, size %x\n",
@@ -1756,6 +1793,7 @@
+ }
+
+skip_read:
++ pageaddr = kmap_atomic(page, KM_USER0);
+ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
+ kunmap_atomic(pageaddr, KM_USER0);
+ flush_dcache_page(page);
@@ -2258,7 +2296,7 @@
diff --new-file -urp linux-2.6.18/fs/squashfs/squashfs2_0.c linux-2.6.18-squashfs3.1/fs/squashfs/squashfs2_0.c
--- linux-2.6.18/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.18-squashfs3.1/fs/squashfs/squashfs2_0.c 2006-08-21 00:14:55.000000000 +0100
-@@ -0,0 +1,779 @@
+@@ -0,0 +1,780 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
@@ -2339,7 +2377,8 @@
+ sblk->fragment_table_start,
+ SQUASHFS_FRAGMENT_INDEX_BYTES_2
+ (sblk->fragments) |
-+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL,
++ SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) {
+ ERROR("unable to read fragment index table\n");
+ return 0;
+ }
@@ -3093,7 +3132,7 @@
+#define SQSH_EXTERN
+extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,
+ long long index, unsigned int length,
-+ long long *next_index);
++ long long *next_index, int srclength);
+extern int squashfs_get_cached_block(struct super_block *s, char *buffer,
+ long long block, unsigned int offset,
+ int length, long long *next_block,
@@ -4206,19 +4245,21 @@
memset(buf, 0xe5, size);
/*
-@@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start
+@@ -101,6 +105,20 @@ identify_ramdisk_image(int fd, int start
goto done;
}
+ /* squashfs is at block zero too */
+ if (squashfsb->s_magic == SQUASHFS_MAGIC) {
++ int bytes_used;
+ printk(KERN_NOTICE
+ "RAMDISK: squashfs filesystem found at block %d\n",
+ start_block);
+ if (squashfsb->s_major < 3)
-+ nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
++ bytes_used = squashfsb->bytes_used_2;
+ else
-+ nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
++ bytes_used = squashfsb->bytes_used;
++ nblocks = (bytes_used + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
+ goto done;
+ }
+
Reply to: