Module Name:    src
Committed By:   kamil
Date:           Sun Mar 10 22:34:14 UTC 2019

Modified Files:
        src/sys/kern: subr_kcov.c
        src/tests/modules: t_kcov.c

Log Message:
Introduce enhancements to the kcov(4) code

Add new tests verifying dup2(2) scenarios:
 - kcov_dup2
 - kcov_basic_dup2_pc
 - kcov_basic_dup2_cmp

The dup2(2) trick is used by syzkaller and assert that it works.
All new tests pass.

While there add minor non-functional cleanup changes.


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/sys/kern/subr_kcov.c
cvs rdiff -u -r1.7 -r1.8 src/tests/modules/t_kcov.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/subr_kcov.c
diff -u src/sys/kern/subr_kcov.c:1.5 src/sys/kern/subr_kcov.c:1.6
--- src/sys/kern/subr_kcov.c:1.5	Sun Mar 10 17:51:00 2019
+++ src/sys/kern/subr_kcov.c	Sun Mar 10 22:34:14 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_kcov.c,v 1.5 2019/03/10 17:51:00 kamil Exp $	*/
+/*	$NetBSD: subr_kcov.c,v 1.6 2019/03/10 22:34:14 kamil Exp $	*/
 
 /*
  * Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -417,7 +417,7 @@ trace_cmp(uint64_t type, uint64_t arg1, 
 	}
 
 	if (kd->mode != KCOV_MODE_TRACE_CMP) {
-		/* PC tracing mode not enabled */
+		/* CMP tracing mode not enabled */
 		return;
 	}
 

Index: src/tests/modules/t_kcov.c
diff -u src/tests/modules/t_kcov.c:1.7 src/tests/modules/t_kcov.c:1.8
--- src/tests/modules/t_kcov.c:1.7	Sun Mar 10 17:51:00 2019
+++ src/tests/modules/t_kcov.c	Sun Mar 10 22:34:14 2019
@@ -57,6 +57,34 @@ open_kcov(void)
 	return fd;
 }
 
+static int
+pick_unassigned_fd(int greater_than_fd)
+{
+	int fd2;
+
+	fd2 = greater_than_fd;
+	do {
+		++fd2;
+	} while (fcntl(fd2, F_GETFL) != -1 || errno != EBADF);
+
+	return fd2;
+}
+
+ATF_TC_WITHOUT_HEAD(kcov_dup2);
+ATF_TC_BODY(kcov_dup2, tc)
+{
+	int fd1, fd2;
+	fd1 = open_kcov();
+
+	fd2 = pick_unassigned_fd(fd1);
+
+	/* Test the dup2(2) trick used by syzkaller */
+	ATF_REQUIRE_EQ(dup2(fd1, fd2), fd2);
+
+	close(fd1);
+	close(fd2);
+}
+
 ATF_TC_WITHOUT_HEAD(kcov_multiopen);
 ATF_TC_BODY(kcov_multiopen, tc)
 {
@@ -216,11 +244,7 @@ ATF_TC_BODY(kcov_enable, tc)
 	ATF_CHECK(ioctl(fd, KCOV_IOC_DISABLE) == 0);
 	ATF_CHECK(ioctl(fd, KCOV_IOC_DISABLE) == -1);
 
-	/* Re-enabling should also work */
-	ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0);
-	ATF_CHECK(ioctl(fd, KCOV_IOC_DISABLE) == 0);
-
-	/* Re-enablibling and changing mode should also work */
+	/* Re-enabling and changing mode should also work */
 	mode = KCOV_MODE_NONE;
 	ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0);
 	ATF_CHECK(ioctl(fd, KCOV_IOC_DISABLE) == 0);
@@ -262,14 +286,22 @@ ATF_TC_BODY(kcov_enable_no_disable_no_cl
 }
 
 static void *
-common_head(int *fdp)
+common_head_raw(bool fd_dup, int *fdp)
 {
 	void *data;
-	int fd;
+	int fd, fd2;
 	uint64_t size = PAGE_SIZE / KCOV_ENTRY_SIZE;
 
 	fd = open_kcov();
 
+	/* Test the dup2(2) trick used by syzkaller */
+	if (fd_dup) {
+		fd2 = pick_unassigned_fd(fd);
+		ATF_REQUIRE_EQ(dup2(fd, fd2), fd2);
+		close(fd);
+		fd = fd2;
+	}
+
 	ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_SETBUFSIZE, &size) == 0,
 	    "Unable to set the kcov buffer size");
 
@@ -280,6 +312,13 @@ common_head(int *fdp)
 	return data;
 }
 
+static void *
+common_head(int *fdp)
+{
+
+	return common_head_raw(false, fdp);
+}
+
 static void
 common_tail(int fd, kcov_int_t *data)
 {
@@ -291,12 +330,12 @@ common_tail(int fd, kcov_int_t *data)
 }
 
 static void
-kcov_basic(int mode)
+kcov_basic(bool fd_dup, int mode)
 {
 	kcov_int_t *buf;
 	int fd;
 
-	buf = common_head(&fd);
+	buf = common_head_raw(fd_dup, &fd);
 	ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0,
 	    "Unable to enable kcov ");
 
@@ -315,7 +354,7 @@ ATF_TC_WITHOUT_HEAD(kcov_basic_pc);
 ATF_TC_BODY(kcov_basic_pc, tc)
 {
 
-	kcov_basic(KCOV_MODE_TRACE_PC);
+	kcov_basic(false, KCOV_MODE_TRACE_PC);
 }
 
 ATF_TC_WITHOUT_HEAD(kcov_basic_cmp);
@@ -324,7 +363,23 @@ ATF_TC_BODY(kcov_basic_cmp, tc)
 
 	atf_tc_skip("XXX: GCC8 needed");
 
-	kcov_basic(KCOV_MODE_TRACE_CMP);
+	kcov_basic(false, KCOV_MODE_TRACE_CMP);
+}
+
+ATF_TC_WITHOUT_HEAD(kcov_basic_dup2_pc);
+ATF_TC_BODY(kcov_basic_dup2_pc, tc)
+{
+
+	kcov_basic(true, KCOV_MODE_TRACE_PC);
+}
+
+ATF_TC_WITHOUT_HEAD(kcov_basic_dup2_cmp);
+ATF_TC_BODY(kcov_basic_dup2_cmp, tc)
+{
+
+	atf_tc_skip("XXX: GCC8 needed");
+
+	kcov_basic(true, KCOV_MODE_TRACE_CMP);
 }
 
 ATF_TC_WITHOUT_HEAD(kcov_multienable_on_the_same_thread);
@@ -486,6 +541,7 @@ KCOV_MULTIPLE_THREADS(32)
 ATF_TP_ADD_TCS(tp)
 {
 
+	ATF_TP_ADD_TC(tp, kcov_dup2);
 	ATF_TP_ADD_TC(tp, kcov_multiopen);
 	ATF_TP_ADD_TC(tp, kcov_open_close_open);
 	ATF_TP_ADD_TC(tp, kcov_bufsize);
@@ -498,6 +554,8 @@ ATF_TP_ADD_TCS(tp)
 	ATF_TP_ADD_TC(tp, kcov_mmap_enable_thread_close);
 	ATF_TP_ADD_TC(tp, kcov_basic_pc);
 	ATF_TP_ADD_TC(tp, kcov_basic_cmp);
+	ATF_TP_ADD_TC(tp, kcov_basic_dup2_pc);
+	ATF_TP_ADD_TC(tp, kcov_basic_dup2_cmp);
 	ATF_TP_ADD_TC(tp, kcov_multienable_on_the_same_thread);
 	ATF_TP_ADD_TC(tp, kcov_buffer_access_from_custom_thread);
 	ATF_TP_ADD_TC(tp, kcov_thread);

Reply via email to