Bug 10548

Summary: hfs+ oops on image without extends
Product: File System Reporter: Eric Sesterhenn (snakebyte)
Component: HFS/HFSPLUSAssignee: Roman Zippel (zippel)
Status: RESOLVED CODE_FIX    
Severity: normal CC: akpm
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 2.6.24 Tree: Mainline
Regression: ---
Attachments: Corrupted image

Description Eric Sesterhenn 2008-04-24 08:06:19 UTC
Distribution: Ubuntu
Problem Description:

mounting a corrupted hfs+ image generated the following oops for me:

[   82.552962] Buffer I/O error on device loop0, logical block 10158082
[   82.553076] Buffer I/O error on device loop0, logical block 10158082
[   82.553168] BUG: unable to handle kernel NULL pointer dereference at 0000002c
[   82.553253] IP: [<c026734e>] hfsplus_releasepage+0x3e/0x140
[   82.553368] Oops: 0000 [#1] PREEMPT DEBUG_PAGEALLOC
[   82.553447] Modules linked in: nfsd exportfs
[   82.553600] 
[   82.553684] Pid: 4052, comm: mount Not tainted (2.6.25-03562-g3dc5063 #23)
[   82.553711] EIP: 0060:[<c026734e>] EFLAGS: 00010246 CPU: 0
[   82.553739] EIP is at hfsplus_releasepage+0x3e/0x140
[   82.553765] EAX: c9da02c0 EBX: c10affc0 ECX: c0267310 EDX: cf1ad7f0
[   82.553850] ESI: 00000000 EDI: cf5d2f08 EBP: c9ef2a94 ESP: c9ef2a7c
[   82.553876]  DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068
[   82.553903] Process mount (pid: 4052, ti=c9ef2000 task=c8976000 task.ti=c9ef2000)
[   82.553928] Stack: c10affc0 cf5d2f08 00000002 c10affc0 00000000 cf5d2f08 c9ef2aa4 c015a29e 
[   82.554297]        cf5d2f08 00001000 c9ef2ac4 c01a0c56 00000000 c10affc0 cf5d2f08 c01a0bb0 
[   82.554524]        00000001 c10affc0 c9ef2ad0 c0160fd9 c10affc0 c9ef2adc c0161474 00000000 
[   82.554524] Call Trace:
[   82.554524]  [<c015a29e>] ? try_to_release_page+0x2e/0x50
[   82.554524]  [<c01a0c56>] ? block_invalidatepage+0xa6/0xc0
[   82.554524]  [<c01a0bb0>] ? block_invalidatepage+0x0/0xc0
[   82.554524]  [<c0160fd9>] ? do_invalidatepage+0x19/0x20
[   82.554524]  [<c0161474>] ? truncate_complete_page+0x44/0x50
[   82.554524]  [<c016153a>] ? truncate_inode_pages_range+0xba/0x320
[   82.554524]  [<c01914cf>] ? generic_drop_inode+0xef/0x160
[   82.554524]  [<c01617ba>] ? truncate_inode_pages+0x1a/0x20
[   82.554524]  [<c019152f>] ? generic_drop_inode+0x14f/0x160
[   82.554524]  [<c019089f>] ? iput+0x5f/0x70
[   82.554524]  [<c026b088>] ? hfsplus_btree_open+0x1d8/0x270
[   82.554524]  [<c0266b02>] ? hfsplus_fill_super+0x252/0x5f0
[   82.554524]  [<c0109637>] ? native_sched_clock+0x67/0xb0
[   82.554524]  [<c0109637>] ? native_sched_clock+0x67/0xb0
[   82.554524]  [<c0109637>] ? native_sched_clock+0x67/0xb0
[   82.554524]  [<c0704da8>] ? __mutex_unlock_slowpath+0xa8/0x140
[   82.554524]  [<c0146764>] ? trace_hardirqs_on+0xc4/0x150
[   82.554524]  [<c0704e48>] ? mutex_unlock+0x8/0x10
[   82.554524]  [<c01a45d9>] ? do_open+0x1d9/0x2c0
[   82.554524]  [<c0109637>] ? native_sched_clock+0x67/0xb0
[   82.554524]  [<c01a4736>] ? __blkdev_get+0x76/0x90
[   82.554524]  [<c0146fe5>] ? __lock_acquire+0x395/0x1020
[   82.554524]  [<c0477db6>] ? vsnprintf+0x426/0x5a0
[   82.554524]  [<c0477fcd>] ? snprintf+0x1d/0x20
[   82.554524]  [<c01bbd7b>] ? disk_name+0x3b/0xc0
[   82.554524]  [<c017febe>] ? get_sb_bdev+0xee/0x120
[   82.554524]  [<c0190030>] ? d_materialise_unique+0x0/0x290
[   82.554524]  [<c01944dd>] ? alloc_vfsmnt+0xdd/0x120
[   82.554524]  [<c0266082>] ? hfsplus_get_sb+0x22/0x30
[   82.554524]  [<c02668b0>] ? hfsplus_fill_super+0x0/0x5f0
[   82.554524]  [<c017fa0a>] ? vfs_kern_mount+0x3a/0x90
[   82.554524]  [<c017fab9>] ? do_kern_mount+0x39/0xd0
[   82.554524]  [<c0195735>] ? do_new_mount+0x65/0x90
[   82.554524]  [<c01958ba>] ? do_mount+0x15a/0x1b0
[   82.554524]  [<c0146764>] ? trace_hardirqs_on+0xc4/0x150
[   82.554524]  [<c0706e49>] ? _spin_unlock_irqrestore+0x39/0x70
[   82.554524]  [<c013cefa>] ? down+0x2a/0x40
[   82.554524]  [<c019597f>] ? sys_mount+0x6f/0xb0
[   82.554524]  [<c0103d75>] ? sysenter_past_esp+0x6a/0xb1
[   82.554524]  =======================
[   82.554524] Code: 18 01 00 00 8b 40 20 83 f8 04 0f 84 df 00 00 00 83 f8 08 74 0d 83 f8 03 0f 84 df 00 00 00 0f 0b eb fe 8b 82 84 02 00 00 8b 70 10 <81> 7e 2c ff 0f 00 00 76 56 8b 45 e8 8d 7e 6c 8b 4e 30 8b 58 14 
[   82.554524] EIP: [<c026734e>] hfsplus_releasepage+0x3e/0x140 SS:ESP 0068:c9ef2a7c
[   82.573238] ---[ end trace 778e504de7e3b1e3 ]---


The problem is that we call hfs_btree_open() from hfsplus_fill_super() to set HFSPLUS_SB(sb).[ext_tree|cat_tree]
Both trees are still NULL at this moment. If hfs_btree_open() fails for any reason it calls iput() on the page, which
gets to hfsplus_releasepage() which tries to access HFSPLUS_SB(sb).* which is still NULL and oopses while dereferencing it.

The following patch fixes this issue for me and the mount command fails properly with
[   96.707880] hfs: failed to load extents file


--- inode.c.orig        2008-03-18 12:53:17.000000000 +0100
+++ inode.c     2008-03-18 13:15:42.000000000 +0100
@@ -65,6 +65,10 @@ static int hfsplus_releasepage(struct pa
                BUG();
                return 0;
        }
+
+       if (!tree)
+               return 0;
+
        if (tree->node_size >= PAGE_CACHE_SIZE) {
                nidx = page->index >> (tree->node_size_shift - PAGE_CACHE_SHIFT);
                spin_lock(&tree->hash_lock);
Comment 1 Eric Sesterhenn 2008-04-24 08:07:51 UTC
Created attachment 15891 [details]
Corrupted image
Comment 2 Andrew Morton 2008-05-06 14:19:51 UTC
Please email a patch to myself, linux-kernel and
Roman Zippel as per Documentation/SubmittingPatches

Handling patches via bugzilla is a huge pita.

Thanks.