| Title: | Linux 2.6.x minix_bmap denial of service |
| Description: |
Linux 2.6.x minix filesystem code fails to properly handle corrupted data
structures, leading to an exploitable denial of service issue when a crafted
fs stream is being mounted.
Note: Many of these DoS related issues are actually caused by integer overflow and signedness problems, although, as these are extremely common (in the Linux kernel, that is), it became a tedious task to track them all. Have fun grep'ing around. |
| Author/Contributor: | |
| References: | |
| Proof of concept or exploit: |
The following minix filesystem image can be used to reproduce the bug:
MOKB-17-11-2006.img.bz2 Use a loopback device to mount it: bunzip2 MOKB-17-11-2006.img.bz2 && mount -t minix -o loop MOKB-17-11-2006.img /media/test
|
| Debugging information: |
The bug has been found using the Linux version of fsfuzzer on a Fedora Core 6 installation, with up to date packages as of 16-11-2006. No operation except mount itself is necessary to trigger the bug. The architecture used to conduct the tests is IA32/x86, SMP enabled.
[root@fedora ~]# uname -a
Linux fedora 2.6.18-1.2798.fc6 #1 SMP Mon Oct 16 14:37:32 EDT 2006 i686 i686 i386 GNU/Linux
MINIX-fs: mounting unchecked file system, running fsck is recommended
Buffer I/O error on device loop0, logical block 53248
Buffer I/O error on device loop0, logical block 53248
Buffer I/O error on device loop0, logical block 63744
Buffer I/O error on device loop0, logical block 63744
Buffer I/O error on device loop0, logical block 29952
Buffer I/O error on device loop0, logical block 29952
Buffer I/O error on device loop0, logical block 8960
Buffer I/O error on device loop0, logical block 8960
Buffer I/O error on device loop0, logical block 33024
Buffer I/O error on device loop0, logical block 33024
minix_bmap: block>big
minix_bmap: block>big
minix_bmap: block>big
minix_bmap: block>big
minix_bmap: block>big
minix_bmap: block>big
minix_bmap: block>big
minix_bmap: block>big
minix_bmap: block>big
minix_bmap: block>big
minix_bmap: block>big
minix_bmap: block>big
minix_bmap: block>big
minix_bmap: block>big
minix_bmap: block>big
minix_bmap: block>big
(... infinite loop ....)
334 static sector_t minix_bmap(struct address_space *mapping, sector_t block)
335 {
336 return generic_block_bmap(mapping,block,minix_get_block);
337 }
338 static const struct address_space_operations minix_aops = {
339 .readpage = minix_readpage,
340 .writepage = minix_writepage,
341 .sync_page = block_sync_page,
342 .prepare_write = minix_prepare_write,
343 .commit_write = generic_commit_write,
344 .bmap = minix_bmap
345 };
23 static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
24 {
25 int n = 0;
26
27 if (block < 0) {
28 printk("minix_bmap: block<0\n");
29 } else if (block >= (minix_sb(inode->i_sb)->s_max_size/BLOCK_SIZE)) {
30 printk("minix_bmap: block>big\n");
31 } else if (block < 7) {
32 offsets[n++] = block;
33 } else if ((block -= 7) < 256) {
34 offsets[n++] = 7;
35 offsets[n++] = block;
36 } else if ((block -= 256) < 256*256) {
37 offsets[n++] = 8;
38 offsets[n++] = block>>8;
39 offsets[n++] = block & 255;
40 } else {
41 block -= 256*256;
42 offsets[n++] = 9;
43 offsets[n++] = block>>16;
44 offsets[n++] = (block>>8) & 255;
45 offsets[n++] = block & 255;
46 }
47 return n;
27 #define BLOCK_SIZE_BITS 10
28 #define BLOCK_SIZE (1< |