NTFS: Fix invalid pointer dereference in ntfs_mft_record_alloc().

In ntfs_mft_record_alloc() when mapping the new extent mft record with
map_extent_mft_record() we overwrite @m with the return value and on
error, we then try to use the old @m but that is no longer there as @m
now contains an error code instead so we crash when dereferencing the
error code as if it were a pointer.

The simple fix is to use a temporary variable to store the return value
thus preserving the original @m for later use. This is a backport from
the commercial Tuxera-NTFS driver and is well tested...

Thanks go to Julia Lawall for pointing this out (whilst I had fixed it
in the commercial driver I had failed to fix it in the Linux kernel).

Signed-off-by: Anton Altaparmakov <anton@tuxera.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Anton Altaparmakov and committed by Linus Torvalds af5eb745 9fbf0c08

+9 -4
+2
Documentation/filesystems/ntfs.txt
··· 460 460 2.1.30: 461 461 - Fix writev() (it kept writing the first segment over and over again 462 462 instead of moving onto subsequent segments). 463 + - Fix crash in ntfs_mft_record_alloc() when mapping the new extent mft 464 + record failed. 463 465 2.1.29: 464 466 - Fix a deadlock when mounting read-write. 465 467 2.1.28:
+7 -4
fs/ntfs/mft.c
··· 1 1 /** 2 2 * mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project. 3 3 * 4 - * Copyright (c) 2001-2006 Anton Altaparmakov 4 + * Copyright (c) 2001-2011 Anton Altaparmakov and Tuxera Inc. 5 5 * Copyright (c) 2002 Richard Russon 6 6 * 7 7 * This program/include file is free software; you can redistribute it and/or ··· 2576 2576 flush_dcache_page(page); 2577 2577 SetPageUptodate(page); 2578 2578 if (base_ni) { 2579 + MFT_RECORD *m_tmp; 2580 + 2579 2581 /* 2580 2582 * Setup the base mft record in the extent mft record. This 2581 2583 * completes initialization of the allocated extent mft record ··· 2590 2588 * attach it to the base inode @base_ni and map, pin, and lock 2591 2589 * its, i.e. the allocated, mft record. 2592 2590 */ 2593 - m = map_extent_mft_record(base_ni, bit, &ni); 2594 - if (IS_ERR(m)) { 2591 + m_tmp = map_extent_mft_record(base_ni, bit, &ni); 2592 + if (IS_ERR(m_tmp)) { 2595 2593 ntfs_error(vol->sb, "Failed to map allocated extent " 2596 2594 "mft record 0x%llx.", (long long)bit); 2597 - err = PTR_ERR(m); 2595 + err = PTR_ERR(m_tmp); 2598 2596 /* Set the mft record itself not in use. */ 2599 2597 m->flags &= cpu_to_le16( 2600 2598 ~le16_to_cpu(MFT_RECORD_IN_USE)); ··· 2605 2603 ntfs_unmap_page(page); 2606 2604 goto undo_mftbmp_alloc; 2607 2605 } 2606 + BUG_ON(m != m_tmp); 2608 2607 /* 2609 2608 * Make sure the allocated mft record is written out to disk. 2610 2609 * No need to set the inode dirty because the caller is going