kern/138465: [patch] add data verification to tools/regression/sockets/sendfile

Bruce Cran bruce at cran.org.uk
Tue Sep 1 22:00:12 UTC 2009


>Number:         138465
>Category:       kern
>Synopsis:       [patch] add data verification to tools/regression/sockets/sendfile
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Sep 01 22:00:11 UTC 2009
>Closed-Date:
>Last-Modified:
>Originator:     Bruce Cran
>Release:        8.0-BETA3
>Organization:
>Environment:
FreeBSD gluon.draftnet 8.0-BETA3 FreeBSD 8.0-BETA3 #1: Mon Aug 31 08:45:18 BST 2009     brucec at gluon.draftnet:/usr/obj/usr/src/sys/GENERIC  i386
>Description:
Data corruption is known to occur when a file stored in a tmpfs filesystem is transferred using sendfile(2). The attached patch adds a step to verify that the data hasn't been corrupted by adding an MD5 checksum field to the header in tools/regression/sockets/sendfile.
>How-To-Repeat:

>Fix:


Patch attached with submission follows:

diff -r -U3 sendfile.orig/Makefile sendfile/Makefile
--- sendfile.orig/Makefile	2009-08-03 09:13:06.000000000 +0100
+++ sendfile/Makefile	2009-09-01 20:37:37.000000000 +0100
@@ -5,5 +5,6 @@
 PROG=	sendfile
 NO_MAN=
 WARNS?=	6
+LDADD = -lmd
 
 .include <bsd.prog.mk>
diff -r -U3 sendfile.orig/sendfile.c sendfile/sendfile.c
--- sendfile.orig/sendfile.c	2009-08-03 09:13:06.000000000 +0100
+++ sendfile/sendfile.c	2009-09-01 22:50:05.000000000 +0100
@@ -34,6 +34,7 @@
 
 #include <err.h>
 #include <limits.h>
+#include <md5.h>
 #include <signal.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -57,11 +58,15 @@
 	u_int32_t	th_header_length;
 	u_int32_t	th_offset;
 	u_int32_t	th_length;
+	char		th_md5[33];
 };
 
 pid_t	child_pid, parent_pid;
 int	listen_socket;
 int	file_fd;
+char	path[PATH_MAX];
+
+void cleanup(void);
 
 static int
 test_th(struct test_header *th, u_int32_t *header_length, u_int32_t *offset,
@@ -105,7 +110,9 @@
 	u_int32_t header_length, offset, length, counter;
 	struct test_header th;
 	ssize_t len;
-	char ch;
+	char buf[10240];
+	MD5_CTX md5ctx;
+	char *rxmd5;
 
 	len = read(accept_socket, &th, sizeof(th));
 	if (len < 0)
@@ -116,19 +123,30 @@
 	if (test_th(&th, &header_length, &offset, &length) == 0)
 		errx(1, "test_th: bad");
 
+	MD5Init(&md5ctx);
+
 	counter = 0;
 	while (1) {
-		len = read(accept_socket, &ch, sizeof(ch));
+		len = read(accept_socket, buf, sizeof(buf));
 		if (len < 0)
 			err(1, "read");
 		if (len == 0)
 			break;
-		counter++;
-		/* XXXRW: Validate byte here. */
+		counter += len;
+		MD5Update(&md5ctx, buf, len);
 	}
+
 	if (counter != header_length + length)
 		errx(1, "receive_test: expected (%d, %d) received %d",
 		    header_length, length, counter);
+
+	rxmd5 = MD5End(&md5ctx, NULL);
+	
+	if (memcmp(th.th_md5, rxmd5, 33) != 0)
+		err(1, "receive_test: expected %s, received %s",
+		    th.th_md5, rxmd5);
+
+	free(rxmd5);
 }
 
 static void
@@ -171,12 +189,13 @@
 init_th(struct test_header *th, u_int32_t header_length, u_int32_t offset,
     u_int32_t length)
 {
-
 	bzero(th, sizeof(*th));
 	th->th_magic = htonl(TEST_MAGIC);
 	th->th_header_length = htonl(header_length);
 	th->th_offset = htonl(offset);
 	th->th_length = htonl(length);
+
+	MD5FileChunk(path, th->th_md5, offset, length);
 }
 
 static void
@@ -196,6 +215,14 @@
 	if (len != 0)
 		errx(1, "lseek: %zd", len);
 
+	if (length == 0)
+	{
+		struct stat st;
+		if (fstat(file_fd, &st) < 0)
+			err(1, "fstat");
+		length = st.st_size - offset;
+	}
+
 	init_th(&th, header_length, offset, length);
 
 	len = write(connect_socket, &th, sizeof(th));
@@ -311,14 +338,23 @@
 	(void)kill(child_pid, SIGKILL);
 }
 
+void
+cleanup(void)
+{
+	if (*path != '\0')
+		unlink(path);
+}
+
 int
 main(void)
 {
-	char path[PATH_MAX], *page_buffer;
+	char *page_buffer;
 	struct sockaddr_in sin;
 	int pagesize;
 	ssize_t len;
 
+	*path = '\0';
+
 	pagesize = getpagesize();
 	page_buffer = malloc(TEST_PAGES * pagesize);
 	if (page_buffer == NULL)
@@ -337,7 +373,7 @@
 
 	snprintf(path, PATH_MAX, "/tmp/sendfile.XXXXXXXXXXXX");
 	file_fd = mkstemp(path);
-	(void)unlink(path);
+	atexit(cleanup);
 
 	len = write(file_fd, page_buffer, TEST_PAGES * pagesize);
 	if (len < 0)


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list