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);