diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2013-05-24 15:55:08 -0700 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2013-05-30 14:35:05 +0100 |
commit | 01aab5ff3033fd6778f9cf7b044da9afef5b2f54 (patch) | |
tree | f0c81d50d6a1107350decb8230c20c0391ea6a44 /fs | |
parent | 2114b0ee38405ced73040bc1228c6cd42ecac8e2 (diff) | |
download | lwn-01aab5ff3033fd6778f9cf7b044da9afef5b2f54.tar.gz lwn-01aab5ff3033fd6778f9cf7b044da9afef5b2f54.zip |
fat: fix possible overflow for fat_clusters
commit 7b92d03c3239f43e5b86c9cc9630f026d36ee995 upstream.
Intermediate value of fat_clusters can be overflowed on 32bits arch.
Reported-by: Krzysztof Strasburger <strasbur@chkw386.ch.pwr.wroc.pl>
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fat/inode.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 808cac7edcfb..fc33ca12f5b0 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -1238,6 +1238,19 @@ static int fat_read_root(struct inode *inode) return 0; } +static unsigned long calc_fat_clusters(struct super_block *sb) +{ + struct msdos_sb_info *sbi = MSDOS_SB(sb); + + /* Divide first to avoid overflow */ + if (sbi->fat_bits != 12) { + unsigned long ent_per_sec = sb->s_blocksize * 8 / sbi->fat_bits; + return ent_per_sec * sbi->fat_length; + } + + return sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits; +} + /* * Read the super block of an MS-DOS FS. */ @@ -1434,7 +1447,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12; /* check that FAT table does not overflow */ - fat_clusters = sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits; + fat_clusters = calc_fat_clusters(sb); total_clusters = min(total_clusters, fat_clusters - FAT_START_ENT); if (total_clusters > MAX_FAT(sb)) { if (!silent) |