]> git.neil.brown.name Git - history.git/commitdiff
NTFS: 2.0.21 - Check for, and refuse to work with too large files/directories/volumes.
authorAnton Altaparmakov <aia21@cantab.net>
Mon, 15 Jul 2002 23:22:58 +0000 (00:22 +0100)
committerAnton Altaparmakov <aia21@cantab.net>
Mon, 15 Jul 2002 23:22:58 +0000 (00:22 +0100)
- Limit volume size at mount time to 2TiB on architectures where
  unsigned long is 32-bits (fs/ntfs/super.c::parse_ntfs_boot_sector()).
  This is the most we can do without overflowing the 32-bit limit of
  the block device size imposed on us by sb_bread() and sb_getblk()
  for the time being.
- Limit file/directory size at open() time to 16TiB on architectures
  where unsigned long is 32-bits (fs/ntfs/file.c::ntfs_file_open() and
  fs/ntfs/dir.c::ntfs_dir_open()). This is the most we can do without
  overflowing the page cache page index.

Documentation/filesystems/ntfs.txt
fs/ntfs/ChangeLog
fs/ntfs/Makefile
fs/ntfs/dir.c
fs/ntfs/file.c
fs/ntfs/super.c

index 8b46088b1265a08757013883edbce2e58a6af656..52f10c999094e38db5b0959a7766b8c219599f4e 100644 (file)
@@ -247,6 +247,11 @@ ChangeLog
 
 Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
 
+2.0.21:
+       These only affect 32-bit architectures:
+       - Check for, and refuse to mount too large volumes (maximum is 2TiB).
+       - Check for, and refuse to open too large files and directories
+         (maximum is 16TiB).
 2.0.20:
        - Support non-resident directory index bitmaps. This means we now cope
          with huge directories without problems.
index 030c0e205eb31b3237613ec66704e16d498fb1d9..3698607d0642c2c63ea7b086e88a50d6840c4d79 100644 (file)
@@ -1,14 +1,19 @@
 ToDo:
        - Find and fix bugs.
-       - W.r.t. s_maxbytes still need to be careful on reading/truncating as
-         there are dragons lurking in the details, e.g. read_inode() currently
-         does no checks for file size wrt s_maxbytes. So what happens when a
-         user open()s a file with i_size > s_maxbytes? Should read_inode()
-         truncate the visible i_size? Will the user just get -E2BIG (or
-         whatever) on open()? Or will (s)he be able to open() but lseek() and
-         read() will fail when s_maxbytes is reached? -> Investigate this.
        - Enable NFS exporting of NTFS.
 
+2.0.21 - Check for, and refuse to work with too large files/directories/volumes.
+
+       - Limit volume size at mount time to 2TiB on architectures where
+         unsigned long is 32-bits (fs/ntfs/super.c::parse_ntfs_boot_sector()).
+         This is the most we can do without overflowing the 32-bit limit of
+         the block device size imposed on us by sb_bread() and sb_getblk()
+         for the time being.
+       - Limit file/directory size at open() time to 16TiB on architectures
+         where unsigned long is 32-bits (fs/ntfs/file.c::ntfs_file_open() and
+         fs/ntfs/dir.c::ntfs_dir_open()). This is the most we can do without
+         overflowing the page cache page index.
+
 2.0.20 - Support non-resident directory index bitmaps, fix page leak in readdir.
 
        - Move the directory index bitmap to use an attribute inode instead of
index 9153ec60a42b31d107509eba7c7b3870e21fd7a0..1edd6826d015be76dd43d621e968bfb8fa1b454a 100644 (file)
@@ -5,7 +5,7 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o
 ntfs-objs := aops.o attrib.o compress.o debug.o dir.o file.o inode.o mft.o \
             mst.o namei.o super.o sysctl.o time.o unistr.o upcase.o
 
-EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.20\"
+EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.21\"
 
 ifeq ($(CONFIG_NTFS_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
index 546cbf0f58bec5be6877ff4e89916925501f6383..4a32e16a093a2a12fcf9f8e033243323c7161403 100644 (file)
@@ -1370,9 +1370,35 @@ err_out:
        return err;
 }
 
+/**
+ * ntfs_dir_open - called when an inode is about to be opened
+ * @vi:                inode to be opened
+ * @filp:      file structure describing the inode
+ *
+ * Limit directory size to the page cache limit on architectures where unsigned
+ * long is 32-bits. This is the most we can do for now without overflowing the
+ * page cache page index. Doing it this way means we don't run into problems
+ * because of existing too large directories. It would be better to allow the
+ * user to read the accessible part of the directory but I doubt very much
+ * anyone is going to hit this check on a 32-bit architecture, so there is no
+ * point in adding the extra complexity required to support this.
+ *
+ * On 64-bit architectures, the check is hopefully optimized away by the
+ * compiler.
+ */
+static int ntfs_dir_open(struct inode *vi, struct file *filp)
+{
+       if (sizeof(unsigned long) < 8) {
+               if (vi->i_size > MAX_LFS_FILESIZE)
+                       return -EFBIG;
+       }
+       return 0;
+}
+
 struct file_operations ntfs_dir_ops = {
        llseek:         generic_file_llseek,    /* Seek inside directory. */
        read:           generic_read_dir,       /* Return -EISDIR. */
        readdir:        ntfs_readdir,           /* Read directory contents. */
+       open:           ntfs_dir_open,          /* Open directory. */
 };
 
index ed25512516223b9af677d2750c4984c464d8779a..698aef36db6f2fda2d95c998d8f6a767a36f2a5a 100644 (file)
 
 #include "ntfs.h"
 
+/**
+ * ntfs_file_open - called when an inode is about to be opened
+ * @vi:                inode to be opened
+ * @filp:      file structure describing the inode
+ *
+ * Limit file size to the page cache limit on architectures where unsigned long
+ * is 32-bits. This is the most we can do for now without overflowing the page
+ * cache page index. Doing it this way means we don't run into problems because
+ * of existing too large files. It would be better to allow the user to read
+ * the beginning of the file but I doubt very much anyone is going to hit this
+ * check on a 32-bit architecture, so there is no point in adding the extra
+ * complexity required to support this.
+ *
+ * On 64-bit architectures, the check is hopefully optimized away by the
+ * compiler.
+ *
+ * After the check passes, just call generic_file_open() to do its work.
+ */
+static int ntfs_file_open(struct inode *vi, struct file *filp)
+{
+       if (sizeof(unsigned long) < 8) {
+               if (vi->i_size > MAX_LFS_FILESIZE)
+                       return -EFBIG;
+       }
+       return generic_file_open(vi, filp);
+}
+
 struct file_operations ntfs_file_ops = {
-       llseek:                 generic_file_llseek,    /* Seek inside file. */
-       read:                   generic_file_read,      /* Read from file. */
-       mmap:                   generic_file_mmap,      /* Mmap file. */
-       open:                   generic_file_open,      /* Open file. */
+       llseek:         generic_file_llseek,    /* Seek inside file. */
+       read:           generic_file_read,      /* Read from file. */
+       mmap:           generic_file_mmap,      /* Mmap file. */
+       open:           ntfs_file_open,         /* Open file. */
 };
 
 struct inode_operations ntfs_file_inode_ops = {};
index 74587a8eee6690a2f12f0db07d0a19a1edbdbb8a..3454200fc42e1bf26f97a05a1f08c0ce926f11d5 100644 (file)
@@ -2,7 +2,7 @@
  * super.c - NTFS kernel super block handling. Part of the Linux-NTFS project.
  *
  * Copyright (c) 2001,2002 Anton Altaparmakov.
- * Copyright (C) 2001,2002 Richard Russon.
+ * Copyright (c) 2001,2002 Richard Russon.
  *
  * This program/include file is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as published
@@ -413,7 +413,7 @@ not_ntfs:
 }
 
 /**
- * read_boot_sector - read the NTFS boot sector of a device
+ * read_ntfs_boot_sector - read the NTFS boot sector of a device
  * @sb:                super block of device to read the boot sector from
  * @silent:    if true, suppress all output
  *
@@ -613,6 +613,20 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
        }
        vol->nr_clusters = ll;
        ntfs_debug("vol->nr_clusters = 0x%Lx", (long long)vol->nr_clusters);
+       /*
+        * On an architecture where unsigned long is 32-bits, we restrict the
+        * volume size to 2TiB (2^41). On a 64-bit architecture, the compiler
+        * will hopefully optimize the whole check away.
+        */
+       if (sizeof(unsigned long) < 8) {
+               if ((ll << vol->cluster_size_bits) >= (1ULL << 41)) {
+                       ntfs_error(vol->sb, "Volume size (%LuTiB) is too large "
+                                       "for this architecture. Maximim "
+                                       "supported is 2TiB. Sorry.",
+                                       ll >> (40 - vol->cluster_size_bits));
+                       return FALSE;
+               }
+       }
        ll = sle64_to_cpu(b->mft_lcn);
        if (ll >= vol->nr_clusters) {
                ntfs_error(vol->sb, "MFT LCN is beyond end of volume. Weird.");