1 /* $NetBSD: t_x86_pte.c,v 1.2 2020/04/26 11:56:38 maxv Exp $ */ 2 3 /* 4 * Copyright (c) 2020 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Maxime Villard. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __COPYRIGHT("@(#) Copyright (c) 2020\ 34 The NetBSD Foundation, inc. All rights reserved."); 35 __RCSID("$NetBSD: t_x86_pte.c,v 1.2 2020/04/26 11:56:38 maxv Exp $"); 36 37 #include <sys/types.h> 38 #include <sys/module.h> 39 #include <sys/sysctl.h> 40 #include <err.h> 41 #include <errno.h> 42 #include <atf-c.h> 43 44 #define mib_name "kern.x86_pte_test.test" 45 #define MODULE_PATH "/usr/tests/modules/x86_pte_tester/x86_pte_tester.kmod" 46 #define MODULE_NAME "x86_pte_tester" 47 48 static struct { 49 size_t n_rwx; 50 size_t n_shstk; 51 bool kernel_map_with_low_ptes; 52 bool pte_is_user_accessible; 53 size_t n_user_space_is_kernel; 54 size_t n_kernel_space_is_user; 55 size_t n_svs_g_bit_set; 56 } x86_pte_results; 57 58 static void 59 fetch_results(void) 60 { 61 static bool fetched = false; 62 size_t len = sizeof(x86_pte_results); 63 char module_name[] = MODULE_NAME; 64 modctl_load_t params = { 65 .ml_filename = MODULE_PATH, 66 .ml_flags = MODCTL_NO_PROP, 67 }; 68 int rv; 69 70 if (fetched) 71 return; 72 73 if (modctl(MODCTL_LOAD, ¶ms) != 0) 74 atf_tc_skip("loading '%s' module failed.", MODULE_NAME); 75 76 rv = sysctlbyname(mib_name, &x86_pte_results, &len, 0, 0); 77 ATF_REQUIRE_EQ(rv, 0); 78 79 if (modctl(MODCTL_UNLOAD, module_name) != 0) 80 warn("failed to unload module '%s'", MODULE_NAME); 81 82 fetched = true; 83 } 84 85 /* -------------------------------------------------------------------------- */ 86 87 ATF_TC(rwx); 88 ATF_TC_HEAD(rwx, tc) 89 { 90 atf_tc_set_md_var(tc, "descr", 91 "ensure there is no RWX page in the kernel"); 92 } 93 ATF_TC_BODY(rwx, tc) 94 { 95 fetch_results(); 96 ATF_REQUIRE_EQ(x86_pte_results.n_rwx, 0); 97 } 98 99 /* -------------------------------------------------------------------------- */ 100 101 ATF_TC(shstk); 102 ATF_TC_HEAD(shstk, tc) 103 { 104 atf_tc_set_md_var(tc, "descr", 105 "ensure there is no SHSTK page in the kernel"); 106 } 107 ATF_TC_BODY(shstk, tc) 108 { 109 fetch_results(); 110 atf_tc_expect_fail("there are %zu SHSTK pages", 111 x86_pte_results.n_shstk); 112 ATF_REQUIRE_EQ(x86_pte_results.n_shstk, 0); 113 } 114 115 /* -------------------------------------------------------------------------- */ 116 117 ATF_TC(kernel_map_with_low_ptes); 118 ATF_TC_HEAD(kernel_map_with_low_ptes, tc) 119 { 120 atf_tc_set_md_var(tc, "descr", 121 "ensure the kernel map has no user mapping"); 122 } 123 ATF_TC_BODY(kernel_map_with_low_ptes, tc) 124 { 125 fetch_results(); 126 ATF_REQUIRE_EQ(x86_pte_results.kernel_map_with_low_ptes, false); 127 } 128 129 /* -------------------------------------------------------------------------- */ 130 131 ATF_TC(pte_is_user_accessible); 132 ATF_TC_HEAD(pte_is_user_accessible, tc) 133 { 134 atf_tc_set_md_var(tc, "descr", 135 "ensure the PTE space does not have user permissions"); 136 } 137 ATF_TC_BODY(pte_is_user_accessible, tc) 138 { 139 fetch_results(); 140 ATF_REQUIRE_EQ(x86_pte_results.pte_is_user_accessible, false); 141 } 142 143 /* -------------------------------------------------------------------------- */ 144 145 ATF_TC(user_space_is_kernel); 146 ATF_TC_HEAD(user_space_is_kernel, tc) 147 { 148 atf_tc_set_md_var(tc, "descr", 149 "ensure no page in the user space has kernel permissions"); 150 } 151 ATF_TC_BODY(user_space_is_kernel, tc) 152 { 153 fetch_results(); 154 ATF_REQUIRE_EQ(x86_pte_results.n_user_space_is_kernel, 0); 155 } 156 157 /* -------------------------------------------------------------------------- */ 158 159 ATF_TC(kernel_space_is_user); 160 ATF_TC_HEAD(kernel_space_is_user, tc) 161 { 162 atf_tc_set_md_var(tc, "descr", 163 "ensure no page in the kernel space has user permissions"); 164 } 165 ATF_TC_BODY(kernel_space_is_user, tc) 166 { 167 fetch_results(); 168 ATF_REQUIRE_EQ(x86_pte_results.n_kernel_space_is_user, 0); 169 } 170 171 /* -------------------------------------------------------------------------- */ 172 173 ATF_TC(svs_g_bit_set); 174 ATF_TC_HEAD(svs_g_bit_set, tc) 175 { 176 atf_tc_set_md_var(tc, "descr", 177 "ensure that no page in the SVS map has the G bit set"); 178 } 179 ATF_TC_BODY(svs_g_bit_set, tc) 180 { 181 fetch_results(); 182 if (x86_pte_results.n_svs_g_bit_set != (size_t)-1) { 183 ATF_REQUIRE_EQ(x86_pte_results.n_svs_g_bit_set, 0); 184 } else { 185 atf_tc_skip("SVS is disabled."); 186 } 187 } 188 189 /* -------------------------------------------------------------------------- */ 190 191 ATF_TP_ADD_TCS(tp) 192 { 193 ATF_TP_ADD_TC(tp, rwx); 194 ATF_TP_ADD_TC(tp, shstk); 195 ATF_TP_ADD_TC(tp, kernel_map_with_low_ptes); 196 ATF_TP_ADD_TC(tp, pte_is_user_accessible); 197 ATF_TP_ADD_TC(tp, user_space_is_kernel); 198 ATF_TP_ADD_TC(tp, kernel_space_is_user); 199 ATF_TP_ADD_TC(tp, svs_g_bit_set); 200 201 return atf_no_error(); 202 } 203