Bug 189981 - md5sum fails with message "Invalid argument" on 4,294,967,295-byte files in FAT32 - tracked down to kernel's fread and stdio stream
Summary: md5sum fails with message "Invalid argument" on 4,294,967,295-byte files in F...
Status: RESOLVED INVALID
Alias: None
Product: File System
Classification: Unclassified
Component: FAT/VFAT/MSDOS (show other bugs)
Hardware: Intel Linux
: P1 low
Assignee: OGAWA Hirofumi
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-12-09 21:03 UTC by Jaime Gaspar
Modified: 2016-12-11 23:11 UTC (History)
1 user (show)

See Also:
Kernel Version: 4.8.0-30-generic
Subsystem:
Regression: No
Bisected commit-id:


Attachments

Description Jaime Gaspar 2016-12-09 21:03:26 UTC
Bug discovered in the thread at http://lists.gnu.org/archive/html/bug-coreutils/2016-12/msg00008.html partially quoted below (with the permission of the persons involved).


=== 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,uid=1000,gid=1000 tmp.fs /tmp/mounted_tmp/
Create two files in "/tmp/mounted_tmp/", file "file_1" with 4,294,967,294 bytes and file "file_2" with 4,294,967,295 bytes:
   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):
   541249e3205af07b4a03f891185f64a0  file_1
   md5sum: file_2: Invalid argument
Unmount the file system at "/tmp/mounted_tmp/":
   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.fc23.x86_64
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\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 32768) = 32768
   read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 32768) = 32768
   read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 32768) = 32768
   read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 32768) = 32768
   read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 32768) = 32767
   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("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 4
   fstat(4, {st_mode=S_IFREG|0644, st_size=2995, ...}) = 0
   read(4, "# Locale name alias data base.\n#"..., 4096) = 2995
   read(4, "", 4096)                       = 0
   close(4)                                = 0
   open("/usr/share/locale/en_GB/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
   open("/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
   open("/usr/share/locale-langpack/en_GB/LC_MESSAGES/libc.mo", O_RDONLY) = 4
   fstat(4, {st_mode=S_IFREG|0644, st_size=3537, ...}) = 0
   mmap(NULL, 3537, PROT_READ, MAP_PRIVATE, 4, 0) = 0x7f53d8d0a000
   close(4)                                = 0
   open("/usr/share/locale-langpack/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
   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\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,
>    32768) = 32767

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.
...
Comment 1 OGAWA Hirofumi 2016-12-09 23:57:03 UTC
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,uid=1000,gid=1000 tmp.fs m
    # cd m
    # truncate -s 4294967294 file_1
    # truncate -s 4294967295 file_2
    # md5sum file_1
    541249e3205af07b4a03f891185f64a0  file_1
    # md5sum file_2
    c654ebc4b3472cfa01ade24bbbbc6d3e  file_2

Can you try v4.8 vanilla?

Thanks.
Comment 2 OGAWA Hirofumi 2016-12-10 00:16:52 UTC
bugzilla-daemon@bugzilla.kernel.org writes:

> The outputs should be respectively (notice that the second output is an error
> message):
>    541249e3205af07b4a03f891185f64a0  file_1
>    md5sum: file_2: Invalid argument

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,uid=1000,gid=1000 tmp.fs m
    # cd m
    # truncate -s 4294967294 file_1
    # truncate -s 4294967295 file_2
    # md5sum file_1
    541249e3205af07b4a03f891185f64a0  file_1
    # md5sum file_2
    c654ebc4b3472cfa01ade24bbbbc6d3e  file_2

Can you try v4.8 vanilla?

Thanks.
Comment 3 Jaime Gaspar 2016-12-11 22:05:26 UTC
> Hm, tested on debian/testing with v4.8 vanilla (+ debian gcc PIE fix).
> However, I couldn't reproduce it.
...
> Can you try v4.8 vanilla?

I tested with kernel 4.8.0-040800-generic from http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.8/ and I cannot reproduce the bug.
I tested with kernel 4.8.0-30-generic from an updated Ubuntu 16.10 and I can reproduce the bug.
Comment 4 OGAWA Hirofumi 2016-12-11 23:11:55 UTC
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->i_sb->s_maxbytes))
+		return -EINVAL;
+	iov_iter_truncate(iter, inode->i_sb->s_maxbytes);
+

Note You need to log in before you can comment on or make changes to this bug.