Module Name: src Committed By: maxv Date: Sun Apr 26 11:56:38 UTC 2020
Modified Files: src/tests/modules: t_x86_pte.c src/tests/modules/x86_pte_tester: x86_pte_tester.c Log Message: Split in sub-tests for clarity, and add a new test, marked as expected failure for now. To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.2 src/tests/modules/t_x86_pte.c cvs rdiff -u -r1.1 -r1.2 src/tests/modules/x86_pte_tester/x86_pte_tester.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/modules/t_x86_pte.c diff -u src/tests/modules/t_x86_pte.c:1.1 src/tests/modules/t_x86_pte.c:1.2 --- src/tests/modules/t_x86_pte.c:1.1 Sun Apr 26 09:08:40 2020 +++ src/tests/modules/t_x86_pte.c Sun Apr 26 11:56:38 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: t_x86_pte.c,v 1.1 2020/04/26 09:08:40 maxv Exp $ */ +/* $NetBSD: t_x86_pte.c,v 1.2 2020/04/26 11:56:38 maxv Exp $ */ /* * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -32,7 +32,7 @@ #include <sys/cdefs.h> __COPYRIGHT("@(#) Copyright (c) 2020\ The NetBSD Foundation, inc. All rights reserved."); -__RCSID("$NetBSD: t_x86_pte.c,v 1.1 2020/04/26 09:08:40 maxv Exp $"); +__RCSID("$NetBSD: t_x86_pte.c,v 1.2 2020/04/26 11:56:38 maxv Exp $"); #include <sys/types.h> #include <sys/module.h> @@ -45,88 +45,158 @@ __RCSID("$NetBSD: t_x86_pte.c,v 1.1 2020 #define MODULE_PATH "/usr/tests/modules/x86_pte_tester/x86_pte_tester.kmod" #define MODULE_NAME "x86_pte_tester" -static bool module_loaded; +static struct { + size_t n_rwx; + size_t n_shstk; + bool kernel_map_with_low_ptes; + bool pte_is_user_accessible; + size_t n_user_space_is_kernel; + size_t n_kernel_space_is_user; + size_t n_svs_g_bit_set; +} x86_pte_results; static void -load_module(void) +fetch_results(void) { -#ifndef SKIP_MODULE - if (module_loaded) - return; - + static bool fetched = false; + size_t len = sizeof(x86_pte_results); + char module_name[] = MODULE_NAME; modctl_load_t params = { .ml_filename = MODULE_PATH, .ml_flags = MODCTL_NO_PROP, }; + int rv; - if (modctl(MODCTL_LOAD, ¶ms) != 0) { - warn("failed to load module '%s'", MODULE_PATH); - } else { - module_loaded = true; - } -#else - module_loaded = true; -#endif /* ! SKIP_MODULE */ + if (fetched) + return; + + if (modctl(MODCTL_LOAD, ¶ms) != 0) + atf_tc_skip("loading '%s' module failed.", MODULE_NAME); + + rv = sysctlbyname(mib_name, &x86_pte_results, &len, 0, 0); + ATF_REQUIRE_EQ(rv, 0); + + if (modctl(MODCTL_UNLOAD, module_name) != 0) + warn("failed to unload module '%s'", MODULE_NAME); + + fetched = true; } -static void -unload_module(void) +/* -------------------------------------------------------------------------- */ + +ATF_TC(rwx); +ATF_TC_HEAD(rwx, tc) { -#ifndef SKIP_MODULE - char module_name[] = MODULE_NAME; + atf_tc_set_md_var(tc, "descr", + "ensure there is no RWX page in the kernel"); +} +ATF_TC_BODY(rwx, tc) +{ + fetch_results(); + ATF_REQUIRE_EQ(x86_pte_results.n_rwx, 0); +} - if (modctl(MODCTL_UNLOAD, module_name) != 0) { - warn("failed to unload module '%s'", MODULE_NAME); - } else { - module_loaded = false; - } -#endif /* ! SKIP_MODULE */ +/* -------------------------------------------------------------------------- */ + +ATF_TC(shstk); +ATF_TC_HEAD(shstk, tc) +{ + atf_tc_set_md_var(tc, "descr", + "ensure there is no SHSTK page in the kernel"); } +ATF_TC_BODY(shstk, tc) +{ + fetch_results(); + atf_tc_expect_fail("there are %zu SHSTK pages", + x86_pte_results.n_shstk); + ATF_REQUIRE_EQ(x86_pte_results.n_shstk, 0); +} + +/* -------------------------------------------------------------------------- */ -ATF_TC_WITH_CLEANUP(x86_pte); -ATF_TC_HEAD(x86_pte, tc) +ATF_TC(kernel_map_with_low_ptes); +ATF_TC_HEAD(kernel_map_with_low_ptes, tc) { atf_tc_set_md_var(tc, "descr", - "testing the PTEs for correctness"); + "ensure the kernel map has no user mapping"); } -ATF_TC_BODY(x86_pte, tc) +ATF_TC_BODY(kernel_map_with_low_ptes, tc) { - struct { - size_t n_rwx; - bool kernel_map_with_low_ptes; - bool pte_is_user_accessible; - size_t n_user_space_is_kernel; - size_t n_kernel_space_is_user; - size_t n_svs_g_bit_set; - } results; - size_t len = sizeof(results); - int rv; + fetch_results(); + ATF_REQUIRE_EQ(x86_pte_results.kernel_map_with_low_ptes, false); +} - load_module(); - if (!module_loaded) { - atf_tc_skip("loading '%s' module failed.", MODULE_NAME); - } +/* -------------------------------------------------------------------------- */ - rv = sysctlbyname(mib_name, &results, &len, 0, 0); - ATF_REQUIRE_EQ(rv, 0); +ATF_TC(pte_is_user_accessible); +ATF_TC_HEAD(pte_is_user_accessible, tc) +{ + atf_tc_set_md_var(tc, "descr", + "ensure the PTE space does not have user permissions"); +} +ATF_TC_BODY(pte_is_user_accessible, tc) +{ + fetch_results(); + ATF_REQUIRE_EQ(x86_pte_results.pte_is_user_accessible, false); +} - ATF_REQUIRE_EQ(results.n_rwx, 0); - ATF_REQUIRE_EQ(results.kernel_map_with_low_ptes, false); - ATF_REQUIRE_EQ(results.pte_is_user_accessible, false); - ATF_REQUIRE_EQ(results.n_user_space_is_kernel, 0); - ATF_REQUIRE_EQ(results.n_kernel_space_is_user, 0); - if (results.n_svs_g_bit_set != (size_t)-1) { - ATF_REQUIRE_EQ(results.n_svs_g_bit_set, 0); - } +/* -------------------------------------------------------------------------- */ + +ATF_TC(user_space_is_kernel); +ATF_TC_HEAD(user_space_is_kernel, tc) +{ + atf_tc_set_md_var(tc, "descr", + "ensure no page in the user space has kernel permissions"); +} +ATF_TC_BODY(user_space_is_kernel, tc) +{ + fetch_results(); + ATF_REQUIRE_EQ(x86_pte_results.n_user_space_is_kernel, 0); } -ATF_TC_CLEANUP(x86_pte, tc) + +/* -------------------------------------------------------------------------- */ + +ATF_TC(kernel_space_is_user); +ATF_TC_HEAD(kernel_space_is_user, tc) +{ + atf_tc_set_md_var(tc, "descr", + "ensure no page in the kernel space has user permissions"); +} +ATF_TC_BODY(kernel_space_is_user, tc) { - unload_module(); + fetch_results(); + ATF_REQUIRE_EQ(x86_pte_results.n_kernel_space_is_user, 0); } +/* -------------------------------------------------------------------------- */ + +ATF_TC(svs_g_bit_set); +ATF_TC_HEAD(svs_g_bit_set, tc) +{ + atf_tc_set_md_var(tc, "descr", + "ensure that no page in the SVS map has the G bit set"); +} +ATF_TC_BODY(svs_g_bit_set, tc) +{ + fetch_results(); + if (x86_pte_results.n_svs_g_bit_set != (size_t)-1) { + ATF_REQUIRE_EQ(x86_pte_results.n_svs_g_bit_set, 0); + } else { + atf_tc_skip("SVS is disabled."); + } +} + +/* -------------------------------------------------------------------------- */ + ATF_TP_ADD_TCS(tp) { - ATF_TP_ADD_TC(tp, x86_pte); + ATF_TP_ADD_TC(tp, rwx); + ATF_TP_ADD_TC(tp, shstk); + ATF_TP_ADD_TC(tp, kernel_map_with_low_ptes); + ATF_TP_ADD_TC(tp, pte_is_user_accessible); + ATF_TP_ADD_TC(tp, user_space_is_kernel); + ATF_TP_ADD_TC(tp, kernel_space_is_user); + ATF_TP_ADD_TC(tp, svs_g_bit_set); return atf_no_error(); } Index: src/tests/modules/x86_pte_tester/x86_pte_tester.c diff -u src/tests/modules/x86_pte_tester/x86_pte_tester.c:1.1 src/tests/modules/x86_pte_tester/x86_pte_tester.c:1.2 --- src/tests/modules/x86_pte_tester/x86_pte_tester.c:1.1 Sun Apr 26 09:08:41 2020 +++ src/tests/modules/x86_pte_tester/x86_pte_tester.c Sun Apr 26 11:56:38 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: x86_pte_tester.c,v 1.1 2020/04/26 09:08:41 maxv Exp $ */ +/* $NetBSD: x86_pte_tester.c,v 1.2 2020/04/26 11:56:38 maxv Exp $ */ /* * Copyright (c) 2016 The NetBSD Foundation, Inc. @@ -56,6 +56,7 @@ static struct { } coord; struct { size_t n_rwx; + size_t n_shstk; bool kernel_map_with_low_ptes; bool pte_is_user_accessible; size_t n_user_space_is_kernel; @@ -220,6 +221,38 @@ count_krwx(pd_entry_t pde, size_t slot, } /* + * Rule: the number of kernel SHSTK pages should be zero. + */ +static walk_type +count_kshstk(pd_entry_t pde, size_t slot, int lvl) +{ + if (lvl == NLEVEL && slot < 256) { + return WALK_SKIP; + } + + if (is_flag(pde, PTE_PS) || lvl == 1) { + if (!is_flag(pde, PTE_W) && is_flag(pde, PTE_D)) { + if (lvl == 4) { + tester_ctx.results.n_shstk += (NBPD_L4 / PAGE_SIZE); + } else if (lvl == 3) { + tester_ctx.results.n_shstk += (NBPD_L3 / PAGE_SIZE); + } else if (lvl == 2) { + tester_ctx.results.n_shstk += (NBPD_L2 / PAGE_SIZE); + } else if (lvl == 1) { + tester_ctx.results.n_shstk += (NBPD_L1 / PAGE_SIZE); + } + } + return WALK_SKIP; + } + + if (!is_flag(pde, PTE_W)) { + return WALK_SKIP; + } + + return WALK_NEXT; +} + +/* * Rule: the lower half of the kernel map must be zero. */ static walk_type @@ -362,6 +395,7 @@ x86_pte_run_scans(void) /* Scan the kernel map. */ pa0 = (paddr_t)kpm->pm_pdirpa[0]; scan_tree(pa0, &count_krwx); + scan_tree(pa0, &count_kshstk); scan_tree(pa0, &check_kernel_map); }