Bug #9669
closedExtra zeros sent by sendfile()
100%
Description
sendfile()
sometimes sends more bytes than there is actually in the source file (in_fd
). When this happens there are extra zeros sent that are not in the source file.
Files
Updated by Marcel Telka over 4 years ago
Reproduction steps
To reproduce the issue compile the attached test.c
using the following commands:
# gcc -Wall -m32 test.c -o test-32 -lsocket -lsendfile # gcc -Wall -m32 -D_FILE_OFFSET_BITS=64 test.c -o test-32-lf -lsocket -lsendfile # gcc -Wall -m64 test.c -o test-64 -lsocket -lsendfile
Then you need two machines. For my tests I use machines t4
and t5
. At t5
I run the testing program, while t4
is used to connect to port 2345 at t5
to receive the file sent by t5
.
The first case is the correct case (IOW, there are no extra zeros sent):
root@t5:~# ./test-32-lf sendfile call: off = 0, len = 8192 sendfile: ret = 6, off = 6, errno = 0 sendfile call: off = 20, len = 8192 sendfile: ret = 0, off = 20, errno = 0 root@t5:~#
root@t4:~# telnet t5 2345 2>/dev/null | god -t x1z 0000000 54 72 79 69 6e 67 20 31 30 2e 30 2e 31 30 30 2e >Trying 10.0.100.< 0000020 35 2e 2e 2e 0a 43 6f 6e 6e 65 63 74 65 64 20 74 >5....Connected t< 0000040 6f 20 74 35 2e 0a 45 73 63 61 70 65 20 63 68 61 >o t5..Escape cha< 0000060 72 61 63 74 65 72 20 69 73 20 27 5e 5d 27 2e 0a >racter is '^]'..< 0000100 48 65 6c 6c 6f 0a >Hello.< 0000106 root@t4:~#
Now two broken cases:
root@t5:~# ./test-32 sendfile call: off = 0, len = 8192 sendfile: ret = 8192, off = 8192, errno = 0 sendfile call: off = 20, len = 8192 sendfile: ret = 8192, off = 8212, errno = 0 root@t5:~#
root@t4:~# telnet t5 2345 2>/dev/null | god -t x1z 0000000 54 72 79 69 6e 67 20 31 30 2e 30 2e 31 30 30 2e >Trying 10.0.100.< 0000020 35 2e 2e 2e 0a 43 6f 6e 6e 65 63 74 65 64 20 74 >5....Connected t< 0000040 6f 20 74 35 2e 0a 45 73 63 61 70 65 20 63 68 61 >o t5..Escape cha< 0000060 72 61 63 74 65 72 20 69 73 20 27 5e 5d 27 2e 0a >racter is '^]'..< 0000100 48 65 6c 6c 6f 0a 00 00 00 00 00 00 00 00 00 00 >Hello...........< 0000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >................< * 0040100 root@t4:~#
root@t5:~# ./test-64 sendfile call: off = 0, len = 8192 sendfile: ret = 8192, off = 8192, errno = 0 sendfile call: off = 20, len = 8192 sendfile: ret = 8192, off = 8212, errno = 0 root@t5:~#
root@t4:~# telnet t5 2345 2>/dev/null | god -t x1z 0000000 54 72 79 69 6e 67 20 31 30 2e 30 2e 31 30 30 2e >Trying 10.0.100.< 0000020 35 2e 2e 2e 0a 43 6f 6e 6e 65 63 74 65 64 20 74 >5....Connected t< 0000040 6f 20 74 35 2e 0a 45 73 63 61 70 65 20 63 68 61 >o t5..Escape cha< 0000060 72 61 63 74 65 72 20 69 73 20 27 5e 5d 27 2e 0a >racter is '^]'..< 0000100 48 65 6c 6c 6f 0a 00 00 00 00 00 00 00 00 00 00 >Hello...........< 0000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >................< * 0040100 root@t4:~#
Updated by Marcel Telka over 4 years ago
Root cause
The problem is in the sendvec_chunk()
function here:
960 if (segmapit) { 961 boolean_t nowait; 962 963 nowait = (sfv->sfv_flag & SFV_NOWAIT) != 0; 964 error = snf_segmap(fp, readvp, sfv_off, 965 (u_offset_t)sfv_len, (ssize_t *)&cnt, 966 nowait); 967 releasef(sfv->sfv_fd); 968 *count += cnt; 969 if (error) 970 return (error); 971 sfv++; 972 continue; 973 }
There is missing check for the file length and adjust of the sfv_len
according to the actual file length before the snf_segmap()
call. Similar check is already in sosendfile64()
where the snf_segmap()
is called too.
Updated by Marcel Telka over 4 years ago
Updated by Marcel Telka over 4 years ago
- Status changed from In Progress to Pending RTI
Updated by Electric Monk over 4 years ago
- Status changed from Pending RTI to Closed
- % Done changed from 0 to 100
git commit 8cd3131235b232e4d63be3cf95ce9be87907e74f
commit 8cd3131235b232e4d63be3cf95ce9be87907e74f Author: Marcel Telka <marcel@telka.sk> Date: 2018-08-06T19:38:36.000Z 9669 Extra zeros sent by sendfile() Reviewed by: Robert Mustacchi <rm@joyent.com> Approved by: Richard Lowe <richlowe@richlowe.net>