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