Project

General

Profile

Actions

Bug #9669

closed

Extra zeros sent by sendfile()

Added by Marcel Telka about 3 years ago. Updated almost 3 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
kernel
Start date:
2018-07-23
Due date:
% Done:

100%

Estimated time:
Difficulty:
Medium
Tags:
needs-triage
Gerrit CR:

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

test.c (1.7 KB) test.c Marcel Telka, 2018-07-23 03:23 PM
Actions #1

Updated by Marcel Telka about 3 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:~#
Actions #2

Updated by Marcel Telka about 3 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.

Actions #4

Updated by Marcel Telka almost 3 years ago

  • Status changed from In Progress to Pending RTI
Actions #5

Updated by Electric Monk almost 3 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>

Actions

Also available in: Atom PDF