md5sum fails with message "Invalid argument" on 4,294,967,295-byte files in FAT32 - tracked down to Ubuntu incompatible change to kernel's fread and stdio stream
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
linux (Ubuntu) |
Fix Released
|
Medium
|
Joseph Salisbury | ||
Yakkety |
Fix Released
|
Medium
|
Joseph Salisbury | ||
Zesty |
Fix Released
|
Medium
|
Joseph Salisbury |
Bug Description
Bug discovered in the threads at http://
=== Message 1 ===
--- Bug ---
In a FAT32 file system, if one runs md5sum on a 4,294,967,294-byte file (one byte less than the maximum file size) it succeeds, but if one runs md5sum on a 4,294,967,295-byte file (the maximum file size) it fails with error message "Invalid argument".
--- How to reproduce the bug ---
Create a FAT32 file system in a file "tmp.fs":
truncate -s 9G tmp.fs
mkfs.vfat -F 32 tmp.fs
Mount at "/tmp/mounted_tmp/" the file system in file "tmp.fs":
sudo mkdir /tmp/mounted_tmp/
sudo mount -o loop,rw,
Create two files in "/tmp/mounted_
cd /tmp/mounted_tmp/
truncate -s 4294967294 file_1
truncate -s 4294967295 file_2
Run md5sum on the two files "file_1" and "file_2":
md5sum file_1
md5sum file_2
The outputs should be respectively (notice that the second output is an error message):
541249e3205a
md5sum: file_2: Invalid argument
Unmount the file system at "/tmp/mounted_
cd ..
sudo umount /tmp/mounted_tmp/
sudo rmdir /tmp/mounted_tmp/
Remove the file "tmp.fs".
--- Notes ---
Tested with md5sum 8.25 running on an updated Ubuntu 16.10 with kernel 4.8.0-30-generic.
The same bug affects sha1sum, sha224sum, sha256sum, sha384sum, and sha512sum, but not crc32.
=== Message 2 ===
...
> --- How to reproduce the bug ---
...
I can't repro this with any md5sum version on 4.2.5-300.
So I'm guessing a kernel regression.
Can you strace -o /tmp/md5sum.strace md5sum file_2,
and look towards the end of the strace file to identify the syscall returning EINVAL?
In any case I'd direct the issue towards the kernel folks.
...
=== Message 3 ===
> Can you strace -o /tmp/md5sum.strace md5sum file_2,
> and look towards the end of the strace file to identify the syscall
> returning EINVAL?
It is the seventh and eighth lines below:
...
read(3, "\0\0\0\
read(3, "\0\0\0\
read(3, "\0\0\0\
read(3, "\0\0\0\
read(3, "\0\0\0\
read(3, 0x25c12b0, 8192) = -1 EINVAL (Invalid argument)
read(3, 0x25c12b0, 8192) = -1 EINVAL (Invalid argument)
write(2, "md5sum: ", 8) = 8
write(2, "file_2", 6) = 6
open(
fstat(4, {st_mode=
read(4, "# Locale name alias data base.\n#"..., 4096) = 2995
read(4, "", 4096) = 0
close(4) = 0
open(
open(
open(
fstat(4, {st_mode=
mmap(NULL, 3537, PROT_READ, MAP_PRIVATE, 4, 0) = 0x7f53d8d0a000
close(4) = 0
open(
write(2, ": Invalid argument", 18) = 18
write(2, "\n", 1) = 1
lseek(3, 0, SEEK_CUR) = 4294967295
close(3) = 0
close(1) = 0
close(2) = 0
exit_group(1) = ?
+++ exited with 1 +++
=== Message 4 ===
...
> read(3, "\0\0\0\
OK we've read all we can, but to verify md5sum will do:
fread(buffer + 32767, 1, 1, stream)
Then the stdio stream will issue the underlying read()s
I'm not too sure where there are two reads here,
but they shouldn't be returning EINVAL, but just
returning 0 to indicate EOF.
> read(3, 0x25c12b0, 8192) = -1 EINVAL (Invalid argument)
> read(3, 0x25c12b0, 8192) = -1 EINVAL (Invalid argument)
So it's a kernel bug as suspected.
...
=== Message 5 ===
...
Hm, tested on debian/testing with v4.8 vanilla (+ debian gcc PIE fix).
However, I couldn't reproduce it.
# truncate -s 9G tmp.fs
# mkfs.vfat -F 32 tmp.fs
mkfs.fat 4.0 (2016-05-06)
# mount -o loop,rw,
# cd m
# truncate -s 4294967294 file_1
# truncate -s 4294967295 file_2
# md5sum file_1
541249e3205
# md5sum file_2
c654ebc4b34
Can you try v4.8 vanilla?
...
=== Message 6 ===
...
I tested with kernel 4.8.0-040800-
I tested with kernel 4.8.0-30-generic from an updated Ubuntu 16.10 and I can reproduce the bug.
=== Message 7 ===
...
With quick check, ubuntu seems to added incompatible change. This should be
reported to ubuntu.
@@ -1674,6 +1687,10 @@
unsigned int prev_offset;
int error = 0;
+ if (unlikely(*ppos >= inode->
+ return -EINVAL;
+ iov_iter_
+
tags: | added: kernel-da-key |
Changed in linux (Ubuntu): | |
importance: | Undecided → Medium |
status: | Incomplete → Triaged |
Changed in linux (Ubuntu Yakkety): | |
importance: | Undecided → Medium |
status: | New → Triaged |
assignee: | nobody → Joseph Salisbury (jsalisbury) |
Changed in linux (Ubuntu Zesty): | |
assignee: | nobody → Joseph Salisbury (jsalisbury) |
Refiling against the kernel as both of your links suggest