Commit 38606c07 authored by Anton Altaparmakov's avatar Anton Altaparmakov

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.
parent 182147c1
......@@ -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.
......
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
......
......@@ -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
......
......@@ -1370,9 +1370,35 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
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. */
};
......@@ -21,11 +21,38 @@
#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 = {};
......
......@@ -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 @@ static BOOL is_boot_sector_ntfs(const struct super_block *sb,
}
/**
* 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.");
......
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