Bug 1757902
| Summary: | fix compat statfs64() returning EOVERFLOW for when _FILE_OFFSET_BITS=64 | ||||||
|---|---|---|---|---|---|---|---|
| Product: | Red Hat Enterprise Linux 8 | Reporter: | Glen Newell <gnewell> | ||||
| Component: | kernel | Assignee: | Eric Sandeen <esandeen> | ||||
| kernel sub component: | VFS | QA Contact: | Kun Wang <kunwan> | ||||
| Status: | CLOSED ERRATA | Docs Contact: | |||||
| Severity: | high | ||||||
| Priority: | high | CC: | aviro, chhudson, dhowells, dwysocha, esandeen, fsorenso, mkderoy, mszeredi, swhiteho, xzhou, yozone | ||||
| Version: | 8.2 | Keywords: | Reproducer | ||||
| Target Milestone: | rc | Flags: | pm-rhel:
mirror+
|
||||
| Target Release: | 8.0 | ||||||
| Hardware: | Unspecified | ||||||
| OS: | Unspecified | ||||||
| Whiteboard: | |||||||
| Fixed In Version: | kernel-4.18.0-148.el8 | Doc Type: | If docs needed, set a value | ||||
| Doc Text: | Story Points: | --- | |||||
| Clone Of: | |||||||
| : | 1758001 (view as bug list) | Environment: | |||||
| Last Closed: | 2020-04-28 16:28:55 UTC | Type: | Bug | ||||
| Regression: | --- | Mount Type: | --- | ||||
| Documentation: | --- | CRM: | |||||
| Verified Versions: | Category: | --- | |||||
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||
| Cloudforms Team: | --- | Target Upstream Version: | |||||
| Embargoed: | |||||||
| Bug Depends On: | |||||||
| Bug Blocks: | 1758001 | ||||||
| Attachments: |
|
||||||
|
Comment 1
Eric Sandeen
2019-10-02 18:46:37 UTC
This was essentially regressed by commit 64d2ab32efe3
viro had proposed:
---
So the whole put_compat_statfs64() thing should be
static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf)
{
struct compat_statfs64 buf;
if ((kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
return -EOVERFLOW;
memset(&buf, 0, sizeof(struct compat_statfs64));
buf.f_type = kbuf->f_type;
buf.f_bsize = kbuf->f_bsize;
buf.f_blocks = kbuf->f_blocks;
buf.f_bfree = kbuf->f_bfree;
buf.f_bavail = kbuf->f_bavail;
buf.f_files = kbuf->f_files;
buf.f_ffree = kbuf->f_ffree;
buf.f_namelen = kbuf->f_namelen;
buf.f_fsid.val[0] = kbuf->f_fsid.val[0];
buf.f_fsid.val[1] = kbuf->f_fsid.val[1];
buf.f_frsize = kbuf->f_frsize;
buf.f_flags = kbuf->f_flags;
if (copy_to_user(ubuf, &buf, sizeof(struct compat_statfs64)))
return -EFAULT;
return 0;
}
and that's it for compat_statfs64 bug
----
but that never went anywhere. Al, did it just get lost or was there some other concern?
Just as a note, RHEL7 kernel-3.10.0-585.el7 and later (i.e. RHEL7.4+) appears to also have this flaw. Thank you for looking at this. Here are the details I specified in the support ticket.
example filesystem was created with a number of inodes that is above the 32-bit integer max...we did this with a 2TB partition created with these options (our customer NAS had a large number of inodes and we were able to reproduce the issue this way)
mkfs.xfs -fn ftype=1 -b size=1024 -i maxpct=99 -i size=512 /dev/nvme0n1p3
a simple c++ program reproduces this issue
// Simple C++ program to display "Hello World"
// Header file for input output functions
#include <iostream>
#include <sys/statvfs.h>
#include <errno.h>
using namespace std;
// main function -
// where the execution of program begins
int main()
{
// prints hello world
cout<<"Hello World" << endl;
struct statvfs statbuf;
int ret = statvfs("/badfs",&statbuf);
cout << "errno " << errno << endl;
return 0;
}
[root@e1n1 mkderoy]# g++ test.cpp
[root@e1n1 mkderoy]# ./a.out
Hello World
errno 0
[root@e1n1 mkderoy]# g++ -m32 test.cpp
[root@e1n1 mkderoy]# ./a.out
Hello World
errno 75
and even with largefile support it dies
[root@e1n1 mkderoy]# g++ -m32 -D_FILE_OFFSET_BITS=64 test.cpp
[root@e1n1 mkderoy]# ./a.out
Hello World
errno 75
Compiling with -D_FILE_OFFSET_BITS=64 works on Rhel6 and not Rhel7
If the filesystem in question is XFS, and /IF/ the customer isn't actually using nearly 2^32 files, one option may be to use xfs_growfs to reduce the maximum percentage of space which is allowable for inode allocation:
-m Specify a new value for the maximum percentage of space in the
filesystem that can be allocated as inodes. In mkfs.xfs(8) this is
specified with -i maxpct=nn.
This will reduce the value reported in f_files and f_ffree, and a sufficiently small percentage value will reduce this to something that doesn't overflow.
I've sent a patch upstream: https://lkml.org/lkml/2019/10/2/891 Created attachment 1622406 [details]
updated reproducer
Reproducer updated:
* test both statfs() and statfs64()
* require expected compile-time options
* verify that at least one of the 64-bit fields would have overflowed a 32-bit value
* success/failure return value
# mount -t tmpfs -o nr_inodes=4294967297 tmpfs /mnt
# gcc compat_statfs.c -o compat_statfs -m32 -D_FILE_OFFSET_BITS=64
# ./compat_statfs /mnt
merged: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cc3a7bfe62b947b423fcb2cfe89fcba92bf48fa3 yes, I can do a test build. The RHEL 7 version of this bug is bz1758001 (In reply to Frank Sorenson from comment #12) > Created attachment 1622406 [details] > updated reproducer > > Reproducer updated: > * test both statfs() and statfs64() ugh. This should have been statfs() and fstatfs() Patch(es) available on kernel-4.18.0-148.el8 Since the problem described in this bug report should be resolved in a recent advisory, it has been closed with a resolution of ERRATA. For information on the advisory, and where to find the updated files, follow the link below. If the solution does not work for you, open a new bug report. https://access.redhat.com/errata/RHSA-2020:1769 |