Commit af5eb745 authored by Anton Altaparmakov's avatar Anton Altaparmakov Committed by Linus Torvalds

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: default avatarAnton Altaparmakov <anton@tuxera.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 9fbf0c08
...@@ -460,6 +460,8 @@ Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. ...@@ -460,6 +460,8 @@ Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
2.1.30: 2.1.30:
- Fix writev() (it kept writing the first segment over and over again - Fix writev() (it kept writing the first segment over and over again
instead of moving onto subsequent segments). instead of moving onto subsequent segments).
- Fix crash in ntfs_mft_record_alloc() when mapping the new extent mft
record failed.
2.1.29: 2.1.29:
- Fix a deadlock when mounting read-write. - Fix a deadlock when mounting read-write.
2.1.28: 2.1.28:
......
/** /**
* mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project. * mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project.
* *
* Copyright (c) 2001-2006 Anton Altaparmakov * Copyright (c) 2001-2011 Anton Altaparmakov and Tuxera Inc.
* Copyright (c) 2002 Richard Russon * Copyright (c) 2002 Richard Russon
* *
* This program/include file is free software; you can redistribute it and/or * This program/include file is free software; you can redistribute it and/or
...@@ -2576,6 +2576,8 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode, ...@@ -2576,6 +2576,8 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode,
flush_dcache_page(page); flush_dcache_page(page);
SetPageUptodate(page); SetPageUptodate(page);
if (base_ni) { if (base_ni) {
MFT_RECORD *m_tmp;
/* /*
* Setup the base mft record in the extent mft record. This * Setup the base mft record in the extent mft record. This
* completes initialization of the allocated extent mft record * completes initialization of the allocated extent mft record
...@@ -2588,11 +2590,11 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode, ...@@ -2588,11 +2590,11 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode,
* attach it to the base inode @base_ni and map, pin, and lock * attach it to the base inode @base_ni and map, pin, and lock
* its, i.e. the allocated, mft record. * its, i.e. the allocated, mft record.
*/ */
m = map_extent_mft_record(base_ni, bit, &ni); m_tmp = map_extent_mft_record(base_ni, bit, &ni);
if (IS_ERR(m)) { if (IS_ERR(m_tmp)) {
ntfs_error(vol->sb, "Failed to map allocated extent " ntfs_error(vol->sb, "Failed to map allocated extent "
"mft record 0x%llx.", (long long)bit); "mft record 0x%llx.", (long long)bit);
err = PTR_ERR(m); err = PTR_ERR(m_tmp);
/* Set the mft record itself not in use. */ /* Set the mft record itself not in use. */
m->flags &= cpu_to_le16( m->flags &= cpu_to_le16(
~le16_to_cpu(MFT_RECORD_IN_USE)); ~le16_to_cpu(MFT_RECORD_IN_USE));
...@@ -2603,6 +2605,7 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode, ...@@ -2603,6 +2605,7 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode,
ntfs_unmap_page(page); ntfs_unmap_page(page);
goto undo_mftbmp_alloc; goto undo_mftbmp_alloc;
} }
BUG_ON(m != m_tmp);
/* /*
* Make sure the allocated mft record is written out to disk. * Make sure the allocated mft record is written out to disk.
* No need to set the inode dirty because the caller is going * No need to set the inode dirty because the caller is going
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment