Browse Source

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>
Anton Altaparmakov 14 years ago
parent
commit
af5eb745ef
2 changed files with 9 additions and 4 deletions
  1. 2 0
      Documentation/filesystems/ntfs.txt
  2. 7 4
      fs/ntfs/mft.c

+ 2 - 0
Documentation/filesystems/ntfs.txt

@@ -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:

+ 7 - 4
fs/ntfs/mft.c

@@ -1,7 +1,7 @@
 /**
 /**
  * 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 @@ mft_rec_already_initialized:
 	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 @@ mft_rec_already_initialized:
 		 * 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);
-		if (IS_ERR(m)) {
+		m_tmp = map_extent_mft_record(base_ni, bit, &ni);
+		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 @@ mft_rec_already_initialized:
 			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