Skip to content

Commit effad57

Browse files
Eric Sandeengregkh
authored andcommitted
vfs: Fix EOVERFLOW testing in put_compat_statfs64
commit cc3a7bf upstream. Today, put_compat_statfs64() disallows nearly any field value over 2^32 if f_bsize is only 32 bits, but that makes no sense. compat_statfs64 is there for the explicit purpose of providing 64-bit fields for f_files, f_ffree, etc. And f_bsize is always only 32 bits. As a result, 32-bit userspace gets -EOVERFLOW for i.e. large file counts even with -D_FILE_OFFSET_BITS=64 set. In reality, only f_bsize and f_frsize can legitimately overflow (fields like f_type and f_namelen should never be large), so test only those fields. This bug was discussed at length some time ago, and this is the proposal Al suggested at https://lkml.org/lkml/2018/8/6/640. It seemed to get dropped amid the discussion of other related changes, but this part seems obviously correct on its own, so I've picked it up and sent it, for expediency. Fixes: 64d2ab3 ("vfs: fix put_compat_statfs64() does not handle errors") Signed-off-by: Eric Sandeen <[email protected]> Signed-off-by: Linus Torvalds <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent d976344 commit effad57

File tree

1 file changed

+4
-13
lines changed

1 file changed

+4
-13
lines changed

fs/statfs.c

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -304,19 +304,10 @@ COMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *,
304304
static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf)
305305
{
306306
struct compat_statfs64 buf;
307-
if (sizeof(ubuf->f_bsize) == 4) {
308-
if ((kbuf->f_type | kbuf->f_bsize | kbuf->f_namelen |
309-
kbuf->f_frsize | kbuf->f_flags) & 0xffffffff00000000ULL)
310-
return -EOVERFLOW;
311-
/* f_files and f_ffree may be -1; it's okay
312-
* to stuff that into 32 bits */
313-
if (kbuf->f_files != 0xffffffffffffffffULL
314-
&& (kbuf->f_files & 0xffffffff00000000ULL))
315-
return -EOVERFLOW;
316-
if (kbuf->f_ffree != 0xffffffffffffffffULL
317-
&& (kbuf->f_ffree & 0xffffffff00000000ULL))
318-
return -EOVERFLOW;
319-
}
307+
308+
if ((kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
309+
return -EOVERFLOW;
310+
320311
memset(&buf, 0, sizeof(struct compat_statfs64));
321312
buf.f_type = kbuf->f_type;
322313
buf.f_bsize = kbuf->f_bsize;

0 commit comments

Comments
 (0)