Bug 33771 - bug in sendfile implementation if nbytes != 0 and struct sf_hdtr *hdtr->headers != NULL
Summary: bug in sendfile implementation if nbytes != 0 and struct sf_hdtr *hdtr->heade...
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: Unspecified
Hardware: Any Any
: Normal Affects Only Me
Assignee: dg
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2002-01-10 20:00 UTC by Vladislav Shabanov
Modified: 2002-12-19 13:43 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Vladislav Shabanov 2002-01-10 20:00:10 UTC
sendfile does the following:

if (uap->hdtr != NULL) {
    ....
  if (hdtr.headers != NULL) {
     ...
     error = writev(p, &nuap);
     sbytes += p->p_retval[0];
    }
 }

if we have headers, sbytes > 0

next, in the main loop we do the following:

...
  if (uap->nbytes && xfsize > (uap->nbytes - sbytes))
     xfsize = uap->nbytes - sbytes;

in this code we think that sbytes accumulates only
file`s contents. Therefore, the last NNN bytes of 
file will be forgotten. (NNN = p->p_retval[0] fron writev)

Fix: 

use separate counter for the header size:

off_t off, xfsize, sbytes = 0, sbytes1 = 0;

....

		if (hdtr.headers != NULL) {
			nuap.fd = uap->s;
			nuap.iovp = hdtr.headers;
			nuap.iovcnt = hdtr.hdr_cnt;
			error = writev(p, &nuap);
			if (error)
				goto done;
			sbytes1 = p->p_retval[0];
		}

....

done:
	if (uap->sbytes != NULL) {
           sbytes += sbytes1;
           copyout(&sbytes, uap->sbytes, sizeof(off_t));
	}
How-To-Repeat: .
Comment 1 Maxim Konovalov 2002-01-22 15:59:32 UTC
Here is a patch:

Index: uipc_syscalls.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.65.2.9
diff -u -r1.65.2.9 uipc_syscalls.c
--- uipc_syscalls.c	2001/07/31 10:49:39	1.65.2.9
+++ uipc_syscalls.c	2002/01/22 15:01:42
@@ -1532,10 +1532,11 @@
 	struct vm_page *pg;
 	struct writev_args nuap;
 	struct sf_hdtr hdtr;
-	off_t off, xfsize, sbytes = 0;
+	off_t off, xfsize, hdtr_size, sbytes = 0;
 	int error = 0, s;

 	vp = NULL;
+	hdtr_size = 0;
 	/*
 	 * Do argument checking. Must be a regular file in, stream
 	 * type and connected socket out, positive offset.
@@ -1591,7 +1592,7 @@
 			error = writev(p, &nuap);
 			if (error)
 				goto done;
-			sbytes += p->p_retval[0];
+			hdtr_size += p->p_retval[0];
 		}
 	}

@@ -1831,11 +1832,12 @@
 			error = writev(p, &nuap);
 			if (error)
 				goto done;
-			sbytes += p->p_retval[0];
+			hdtr_size += p->p_retval[0];
 	}

 done:
 	if (uap->sbytes != NULL) {
+		sbytes += hdtr_size;
 		copyout(&sbytes, uap->sbytes, sizeof(off_t));
 	}
 	if (vp)

-- 
Maxim Konovalov, MAcomnet, Internet-Intranet Dept., system engineer
phone: +7 (095) 796-9079, mailto: maxim@macomnet.ru
Comment 2 Sheldon Hearn freebsd_committer freebsd_triage 2002-01-29 12:58:32 UTC
Responsible Changed
From-To: freebsd-bugs->dg

David, this looks closely related to the work you're discussing 
with Alfred in connection with sendfile().
Comment 3 Maxim Konovalov freebsd_committer freebsd_triage 2002-12-19 13:40:22 UTC
State Changed
From-To: open->closed

alfred fixed this bug in rev. 1.103 and rev. 1.65.2.10 
src/sys/kern/uipc_syscalls.c in -CURRENT and -STABLE six months ago.