RHEL Engineering is moving the tracking of its product development work on RHEL 6 through RHEL 9 to Red Hat Jira (issues.redhat.com). If you're a Red Hat customer, please continue to file support cases via the Red Hat customer portal. If you're not, please head to the "RHEL project" in Red Hat Jira and file new tickets here. Individual Bugzilla bugs in the statuses "NEW", "ASSIGNED", and "POST" are being migrated throughout September 2023. Bugs of Red Hat partners with an assigned Engineering Partner Manager (EPM) are migrated in late September as per pre-agreed dates. Bugs against components "kernel", "kernel-rt", and "kpatch" are only migrated if still in "NEW" or "ASSIGNED". If you cannot log in to RH Jira, please consult article #7032570. That failing, please send an e-mail to the RH Jira admins at rh-issues@redhat.com to troubleshoot your issue as a user management inquiry. The email creates a ServiceNow ticket with Red Hat. Individual Bugzilla bugs that are migrated will be moved to status "CLOSED", resolution "MIGRATED", and set with "MigratedToJIRA" in "Keywords". The link to the successor Jira issue will be found under "Links", have a little "two-footprint" icon next to it, and direct you to the "RHEL project" in Red Hat Jira (issue links are of type "https://issues.redhat.com/browse/RHEL-XXXX", where "X" is a digit). This same link will be available in a blue banner at the top of the page informing you that that bug has been migrated.
Bug 1758001 - fix compat statfs64() returning EOVERFLOW for when _FILE_OFFSET_BITS=64
Summary: fix compat statfs64() returning EOVERFLOW for when _FILE_OFFSET_BITS=64
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat Enterprise Linux 7
Classification: Red Hat
Component: kernel
Version: 7.8
Hardware: Unspecified
OS: Unspecified
high
urgent
Target Milestone: rc
: ---
Assignee: Eric Sandeen
QA Contact: Kun Wang
URL:
Whiteboard:
: 1650928 (view as bug list)
Depends On: 1757902
Blocks: 1775677 1775678
TreeView+ depends on / blocked
 
Reported: 2019-10-02 22:58 UTC by Frank Sorenson
Modified: 2023-09-07 20:43 UTC (History)
19 users (show)

Fixed In Version: kernel-3.10.0-1109.el7
Doc Type: If docs needed, set a value
Doc Text:
Clone Of: 1757902
: 1775677 1775678 (view as bug list)
Environment:
Last Closed: 2020-03-31 19:33:37 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)
updated reproducer (2.33 KB, text/x-csrc)
2019-10-03 20:07 UTC, Frank Sorenson
no flags Details


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHSA-2020:1016 0 None None None 2020-03-31 19:34:27 UTC

Description Frank Sorenson 2019-10-02 22:58:32 UTC
+++ This bug was initially created as a clone of Bug #1757902 +++

Description of problem:
fix compat statfs64() returning EOVERFLOW for when _FILE_OFFSET_BITS=64

When compiled on 32-bit with -D_FILE_OFFSET_BITS=64, the statfs64 struct has both 32-bit and 64-bit fields.  A test of field size for the 32-bit fields erroneously also enables a check of 32-bit overflow on the 64-bit fields as well, resulting in statfs64 incorrectly returning EOVERFLOW.

Some upstream discussion of this issue occurred in 2017 and 2018 (for example, see https://patchwork.kernel.org/patch/9987759/), however no fix was applied, so the bug still exists upstream.

Version-Release number of selected component (if applicable):


How reproducible:

Test program compiled as 32-bit executable, run against a 'large' filesystem. Compiled with _FILE_OFFSET_BITS=64

Steps to Reproduce:
Diags and repro done with test 'hello world' program, which reproduces the same behavior- steps taken from Customer repro and verified:


// 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("/mnt/backup",&statbuf);
    cout << "errno " << errno << endl;
    return 0; 
} 


^Repro program notice it works when compiled 64-bit but fails even when 32-bit is compiled with largefile support

[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


Actual results:

Even with 'Large File Support ' (_FILE_OFFSET_BITS=64) program returns Errno 75 (EOVERFLOW)

Expected results:

Previously, the the _FILE_OFFSET_BITS=64 flag would allow the program to run. 


Additional info:

--- Additional comment from Eric Sandeen on 2019-10-02 13:46:37 CDT ---

It would be worth stating the details of a filesystem which will cause the problem, and which field is causing the overflow for the customer.  From reading the attached cases I assume it's f_files / f_ffree, but please confirm.

--- Additional comment from Eric Sandeen on 2019-10-02 14:18:49 CDT ---

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?

--- Additional comment from Chris Hudson on 2019-10-02 14:29:19 CDT ---

Thanks for the attention to this one. Our strategic partner, IBM Netezza claims that this is very impactful to their customer base and hinders certain backup functionality within their product.

Here is somewhat of an impact statement from the customer, for reference:
---
This is a major issue for us, and a major regression in RhelOS itself. All 32-bit applications that use statvfs, statfs, etc to calculate how much freespace is on a filesystem (a typical usecase) will not work on some large filesystems on rhel7 onward. We are compiling with _FILE_OFFSET_BITS=64 which should allow our application to support these filesystems as it has in the past. This is affecting our customers in a major way, as they are unable to run their backups. We expect 24*7 support to work on resolving this whether that be providing a kernel fix or an acceptable workaround for calculating free space on this filesystem as we're doing here
            int ret = statvfs(basedir.c_str(),&statbuf);
            int64 freebytes = (int64)statbuf.f_bavail * (int64)statbuf.f_bsize;
---

I have asked for a bit more history as to how things got to this point as I would expect something like this to be discovered in Netezza's QE. But it sounds like it is out in the wild and truly impacting their customers.

I have a call with this team in half an hour. Will report back with anything new that comes out of the discussion.

-Chris

--- Additional comment from Eric Sandeen on 2019-10-02 14:56:38 CDT ---

(In reply to Chris Hudson from comment #3)
> Thanks for the attention to this one.

Sure.  The kernel code in put_compat_statfs64 seems obviously broken, and needs to be fixed.  (FWIW, it's broken now in RHEL7 as well.)

I just wanted to be sure we had a clear understanding of how the customer actually hit it, and we weren't inferring anything in error.

--- Additional comment from Eric Sandeen on 2019-10-02 14:59:20 CDT ---

Just as a note, RHEL7 kernel-3.10.0-585.el7 and later (i.e. RHEL7.4+) appears to also have this flaw.

--- Additional comment from Michael DeRoy on 2019-10-02 15:17:34 CDT ---

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

--- Additional comment from Frank Sorenson on 2019-10-02 15:21:37 CDT ---

per comment 5, adding Regression

--- Additional comment from Frank Sorenson on 2019-10-02 15:23:29 CDT ---

me--  not a regression for rhel8

--- Additional comment from Eric Sandeen on 2019-10-02 15:55:45 CDT ---

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.

--- Additional comment from Eric Sandeen on 2019-10-02 16:19:09 CDT ---

I've sent a patch upstream:

https://lkml.org/lkml/2019/10/2/891

Comment 3 Frank Sorenson 2019-10-03 20:07:14 UTC
Created attachment 1622407 [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

Comment 4 Frank Sorenson 2019-10-03 20:20:08 UTC
*** Bug 1650928 has been marked as a duplicate of this bug. ***

Comment 5 Frank Sorenson 2019-10-04 13:42:13 UTC
(In reply to Frank Sorenson from comment #3)
> Reproducer updated:
...
>  * test both statfs() and statfs64()

this should have read statfs() and fstatfs()

sorry

Comment 12 Glen Newell 2019-10-15 17:11:22 UTC
Eric-

We sent them a patch and it sounds like it works: 

 Created By: Michael DeRoy  (10/15/2019 7:52 AM)

The patch fixed the test I uploaded which reproduces the issue for us..the syscall no longer errors on 32-bit. How long will it take for this patch to get into production? Is it possible for Redhat to provide us with a supported patch we can install if our customers face this issue?


and the TAMs reply:

 Created By: Christopher Hudson  (10/15/2019 9:34 AM) Last Modified By: Christopher Hudson  (10/15/2019 9:34 AM)

::Internal::

That's good news - thanks for driving this. If IBM would like an accelerated fix, then I would say let's go through the process and let them know that they will need to patch again within 30 days of the supported patch being released (which they would need to communicate to their customers).

I guess alternatively, if the z-stream + backport is going to come out quickly, maybe they would be OK waiting. This is the kernel, so patching once vs. twice is a much better scenario when considering production workloads.

-Chris

Comment 20 Jan Stancek 2019-11-03 15:44:11 UTC
Patch(es) committed on kernel-3.10.0-1109.el7

Comment 33 errata-xmlrpc 2020-03-31 19:33:37 UTC
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:1016


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