diff options
author | Anton Altaparmakov <aia21@cam.ac.uk> | 2014-09-22 01:53:03 +0100 |
---|---|---|
committer | Jiri Slaby <jslaby@suse.cz> | 2014-10-13 15:41:36 +0200 |
commit | 2db0c704fe90710368581c2dcf5d33105a9b9600 (patch) | |
tree | b7dc47dd3adf4137cfda1d8e0346faa897c2317d /net/wireless | |
parent | fa13e3ec566c51c84975730b34d9da3c1c412992 (diff) | |
download | lwn-2db0c704fe90710368581c2dcf5d33105a9b9600.tar.gz lwn-2db0c704fe90710368581c2dcf5d33105a9b9600.zip |
Fix nasty 32-bit overflow bug in buffer i/o code.
commit f2d5a94436cc7cc0221b9a81bba2276a25187dd3 upstream.
On 32-bit architectures, the legacy buffer_head functions are not always
handling the sector number with the proper 64-bit types, and will thus
fail on 4TB+ disks.
Any code that uses __getblk() (and thus bread(), breadahead(),
sb_bread(), sb_breadahead(), sb_getblk()), and calls it using a 64-bit
block on a 32-bit arch (where "long" is 32-bit) causes an inifinite loop
in __getblk_slow() with an infinite stream of errors logged to dmesg
like this:
__find_get_block_slow() failed. block=6740375944, b_blocknr=2445408648
b_state=0x00000020, b_size=512
device sda1 blocksize: 512
Note how in hex block is 0x191C1F988 and b_blocknr is 0x91C1F988 i.e. the
top 32-bits are missing (in this case the 0x1 at the top).
This is because grow_dev_page() is broken and has a 32-bit overflow due
to shifting the page index value (a pgoff_t - which is just 32 bits on
32-bit architectures) left-shifted as the block number. But the top
bits to get lost as the pgoff_t is not type cast to sector_t / 64-bit
before the shift.
This patch fixes this issue by type casting "index" to sector_t before
doing the left shift.
Note this is not a theoretical bug but has been seen in the field on a
4TiB hard drive with logical sector size 512 bytes.
This patch has been verified to fix the infinite loop problem on 3.17-rc5
kernel using a 4TB disk image mounted using "-o loop". Without this patch
doing a "find /nt" where /nt is an NTFS volume causes the inifinite loop
100% reproducibly whilst with the patch it works fine as expected.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Diffstat (limited to 'net/wireless')
0 files changed, 0 insertions, 0 deletions