View Issue Details

IDProjectCategoryView StatusLast Update
0018122CentOS-7kernelpublic2021-03-23 23:33
Reporterizbyshev Assigned To 
PrioritynormalSeverityminorReproducibilityalways
Status newResolutionopen 
Product Version7.8-2003 
Summary0018122: sendfile() to a pipe fails with EFBIG after transferring INT_MAX bytes
DescriptionThis a copy of https://bugzilla.redhat.com/show_bug.cgi?id=1930795. That report hasn't received a response and is private without me having the ability to change that, so I've decided to make a public report as well for any folks that may stumble in this bug.

sendfile() to a pipe fails with EFBIG after the total number of transferred bytes reaches INT_MAX. See steps to reproduce.

I got this issue with my software running on a customer site with RHEL 7.8, but could reproduce it on the CentOS 7 (kernel 3.10.0-1160.15.2.el7).

I couldn't reproduce this on kernels from other distros of similar time frame, so I looked further. And judging by the changelog of CentOS 7 kernel package, a possible culprit is the fix for https://bugzilla.redhat.com/show_bug.cgi?id=1163792. I don't know the patch contents, but it appears to have added `generic_write_checks()` before[1]. But that function checks O_LARGEFILE on the file[2] for large positions, and, surprisingly, pipes do maintain a position in this case[3], so eventually the check fails with EFBIG.

[1] https://elixir.bootlin.com/linux/v3.10/source/fs/splice.c#L1113
[2] https://elixir.bootlin.com/linux/v3.10/source/mm/filemap.c#L2123
[3] https://elixir.bootlin.com/linux/v3.10/source/fs/splice.c#L1067
Steps To ReproduceDownload the attached Python 2 script and run:

$ dd if=/dev/zero of=big-file bs=1M count=2048
$ python test-sendfile.py <big-file | cat >/dev/null
1073741824
1073741823
-1
Error: 27
TagsNo tags attached.
abrt_hash
URL

Activities

izbyshev

izbyshev

2021-03-23 23:33

reporter  

test-sendfile.py (239 bytes)   
import ctypes, sys
libc = ctypes.CDLL('libc.so.6', use_errno=True)
while 1:
	nb = libc.sendfile(1, 0, None, 2**30)
	print >>sys.stderr, nb 
	if nb <= 0:
		print >>sys.stderr, "Done" if nb == 0 else "Error: %s" % ctypes.get_errno()
		break
test-sendfile.py (239 bytes)   

Issue History

Date Modified Username Field Change
2021-03-23 23:33 izbyshev New Issue
2021-03-23 23:33 izbyshev File Added: test-sendfile.py