Bug 216626 - fallocate using large files and setrlimit SIGXFSZ on a 32 bit boundary does not produce SIGXFSZ
Summary: fallocate using large files and setrlimit SIGXFSZ on a 32 bit boundary does n...
Status: NEW
Alias: None
Product: File System
Classification: Unclassified
Component: VFS (show other bugs)
Hardware: All Linux
: P1 normal
Assignee: fs_vfs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-10-25 16:46 UTC by Colin Ian King
Modified: 2022-11-17 09:45 UTC (History)
1 user (show)

See Also:
Kernel Version: 4.x to 6.0+
Subsystem:
Regression: No
Bisected commit-id:


Attachments
C source to reproduce the fallocate/SIGXFSZ issue (873 bytes, text/plain)
2022-10-25 16:46 UTC, Colin Ian King
Details

Description Colin Ian King 2022-10-25 16:46:18 UTC
Created attachment 303085 [details]
C source to reproduce the fallocate/SIGXFSZ issue

This is a corner case on 32 bit systems when using large file offsets, fallocate and setrlimit. Issue found on ext4, probably also on other file systems(?).

Setting the RLIMIT_FSIZE with setrlimit to 0xffffffff and then fallocating 1 or more bytes at the offset of 0xffffffff should make the fallocate fail with EFBIG and generate a SIGXFSZ signal. On 64 bit platforms this works, on 32 bit platforms such as i386 4.15 kernels through to linux 6.0 it fails to generate EFBIG errors and SIGXFSZ.

Attached is a test program to illustrate the problem. It sets the file size limit and allocates 1024 bytes at the boundary file size limit for 3 offsets:

On 64 bit systems we get the expected results:
got signal SIGXFSZ
offset: 65536 (0x10000), fallocate returned: -1
got signal SIGXFSZ
offset: 4294966271 (0xfffffbff), fallocate returned: -1
got signal SIGXFSZ
offset: 4294967295 (0xffffffff), fallocate returned: -1

On 32 bit systems the code fails on the 0xffffffff offset:

got signal SIGXFSZ
offset: 65536 (0x10000), fallocate returned: -1
got signal SIGXFSZ
offset: 4294966271 (0xfffffbff), fallocate returned: -1
offset: 4294967295 (0xffffffff), fallocate returned: 0

Attached is the reproducer.

I found this while developing a file limit boundary test case in stress-ng and discovered it breaks on all 32 bit kernels (armhf, i386, etc), even with recent 5.15 and 6.0 kernels.

attached is a simple reproducer
Comment 1 Colin Ian King 2022-10-26 12:05:07 UTC
Tested and fails also on m68k Linux 4.16
Comment 2 Colin Ian King 2022-10-26 14:08:41 UTC
Tested and fails on m68k with ext4 and btrfs; occurs across arches and across file systems.
Comment 3 Christian Brauner 2022-10-31 09:44:17 UTC
Hey Colin,

This looks to be intentional? Afaict, the -EFBIG might ceome directly from vfs_fallocate():

	/* Check for wrap through zero too */
	if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0))
		return -EFBIG;

and you should see the same behavior for 64bit if you pass in -1 as offset:

brauner@wittgenstein|~/Downloads
> sudo ./fallocate
got signal SIGXFSZ
offset: 65536 (0x10000), fallocate returned: -1
got signal SIGXFSZ
offset: 4294966271 (0xfffffbff), fallocate returned: -1
offset: 18446744073709551615 (0xffffffffffffffff), fallocate returned: -1
Comment 4 Colin Ian King 2022-11-17 09:45:46 UTC
The behavior for 32 bit is not what I expected, 

offset: 4294967295 (0xffffffff), fallocate returned: 0

allocating at the boundary is OK, where as at 0xfffffbff it fails. I'd expect at the boundary for it to fail too.

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