• David Woodhouse's avatar
    jffs2: Fix memory corruption in jffs2_read_inode_range() · 199bc9ff
    David Woodhouse authored
    In 2.6.23 kernel, commit a32ea1e1
    ("Fix read/truncate race") fixed a race in the generic code, and as a
    side effect, now do_generic_file_read() can ask us to readpage() past
    the i_size. This seems to be correctly handled by the block routines
    (e.g. block_read_full_page() fills the page with zeroes in case if
    somebody is trying to read past the last inode's block).
    
    JFFS2 doesn't handle this; it assumes that it won't be asked to read
    pages which don't exist -- and thus that there will be at least _one_
    valid 'frag' on the page it's being asked to read. It will fill any
    holes with the following memset:
    
      memset(buf, 0, min(end, frag->ofs + frag->size) - offset);
    
    When the 'closest smaller match' returned by jffs2_lookup_node_frag() is
    actually on a previous page and ends before 'offset', that results in:
    
      memset(buf, 0, <huge unsigned negative>);
    
    Hopefully, in most cases the corruption is fatal, and quickly causing
    random oopses, like this:
    
      root@10.0.0.4:~/ltp-fs-20090531# ./testcases/kernel/fs/ftest/ftest01
      Unable to handle kernel paging request for data at address 0x00000008
      Faulting instruction address: 0xc01cd980
      Oops: Kernel access of bad area, sig: 11 [#1]
      [...]
      NIP [c01cd980] rb_insert_color+0x38/0x184
      LR [c0043978] enqueue_hrtimer+0x88/0xc4
      Call Trace:
      [c6c63b60] [c004f9a8] tick_sched_timer+0xa0/0xe4 (unreliable)
      [c6c63b80] [c0043978] enqueue_hrtimer+0x88/0xc4
      [c6c63b90] [c0043a48] __run_hrtimer+0x94/0xbc
      [c6c63bb0] [c0044628] hrtimer_interrupt+0x140/0x2b8
      [c6c63c10] [c000f8e8] timer_interrupt+0x13c/0x254
      [c6c63c30] [c001352c] ret_from_except+0x0/0x14
      --- Exception: 901 at memset+0x38/0x5c
          LR = jffs2_read_inode_range+0x144/0x17c
      [c6c63cf0] [00000000] (null) (unreliable)
    
    This patch fixes the issue, plus fixes all LTP tests on NAND/UBI with
    JFFS2 filesystem that were failing since 2.6.23 (seems like the bug
    above also broke the truncation).
    Reported-By: default avatarAnton Vorontsov <avorontsov@ru.mvista.com>
    Tested-By: default avatarAnton Vorontsov <avorontsov@ru.mvista.com>
    Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
    Cc: stable@kernel.org
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    199bc9ff
read.c 6.85 KB