[LTP] [PATCH ltp 1/2] Add Intel umip(User Mode Instruction Prevention) basic function tests
Pengfei Xu
pengfei.xu@intel.com
Wed Oct 31 06:50:34 CET 2018
umip is one Intel security function, which protect(#GP exception)
below instructions in user mode:
* SGDT - Store Global Descriptor Table
* SIDT - Store Interrupt Descriptor Table
* SLDT - Store Local Descriptor Table
* SMSW - Store Machine Status Word
* STR - Store Task Register
Add test code and scripts.
Signed-off-by: Pengfei Xu <pengfei.xu@intel.com>
---
testcases/kernel/security/umip/.gitignore | 1 +
testcases/kernel/security/umip/Makefile | 9 ++
testcases/kernel/security/umip/umip_common.sh | 56 +++++++++
testcases/kernel/security/umip/umip_func.sh | 74 +++++++++++
testcases/kernel/security/umip/umip_gp_test.c | 171 ++++++++++++++++++++++++++
5 files changed, 311 insertions(+)
create mode 100644 testcases/kernel/security/umip/.gitignore
create mode 100644 testcases/kernel/security/umip/Makefile
create mode 100755 testcases/kernel/security/umip/umip_common.sh
create mode 100755 testcases/kernel/security/umip/umip_func.sh
create mode 100644 testcases/kernel/security/umip/umip_gp_test.c
diff --git a/testcases/kernel/security/umip/.gitignore b/testcases/kernel/security/umip/.gitignore
new file mode 100644
index 000000000..9e7022c59
--- /dev/null
+++ b/testcases/kernel/security/umip/.gitignore
@@ -0,0 +1 @@
+umip_gp_test
diff --git a/testcases/kernel/security/umip/Makefile b/testcases/kernel/security/umip/Makefile
new file mode 100644
index 000000000..972536c92
--- /dev/null
+++ b/testcases/kernel/security/umip/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+top_srcdir ?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+INSTALL_TARGETS := *.sh
+
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/security/umip/umip_common.sh b/testcases/kernel/security/umip/umip_common.sh
new file mode 100755
index 000000000..d3d674127
--- /dev/null
+++ b/testcases/kernel/security/umip/umip_common.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+#
+# testcases/security/umip/umip_func.sh
+#
+# Copyright (c) 2018, Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# Authors: Pengfei Xu - pengfei.xu@intel.com
+#
+# History: Oct 23 2018 - created
+#
+# Description: it's for umip test common function scripts
+#
+
+. tst_test.sh
+
+# check kernel config already set or not
+kconfig_check()
+{
+ config_content="$1"
+ result=""
+
+ if [ -r "/boot/config-$(uname -r)" ]; then
+ result=$(grep -E "^$config_content" "/boot/config-$(uname -r)")
+ # for clear linux, kernel config saved in /lib/kernel/
+ elif [ -r "/lib/kernel/config-$(uname -r)" ]; then
+ result=$(grep -E "^$config_content" "/lib/kernel/config-$(uname -r)")
+ elif [ -r "/proc/config.gz" ]; then
+ result=$(zcat "/proc/config.gz" | grep -E "^$config_content")
+ else
+ tst_res TINFO "No config file readable on this system"
+ return 1
+ fi
+ [ -n "$result" ] || return 1
+ return 0
+}
+
+# check /proc/cpuinfo contain test function or not
+cpu_info_check()
+{
+ cpu_func="$1"
+
+ [ -n "$cpu_func" ] || tst_brk TWARN "no cpu info check item"
+ grep -q "$cpu_func" /proc/cpuinfo || return 1
+ tst_res TINFO "/proc/cpuinfo contain '$cpu_func'"
+ return 0
+}
diff --git a/testcases/kernel/security/umip/umip_func.sh b/testcases/kernel/security/umip/umip_func.sh
new file mode 100755
index 000000000..1113d609d
--- /dev/null
+++ b/testcases/kernel/security/umip/umip_func.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+#
+# testcases/security/umip/umip_func.sh
+#
+# Copyright (c) 2018, Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# Authors: Pengfei Xu - pengfei.xu@intel.com
+#
+# History: Oct 23 2018 - created
+#
+# Description: it's for Intel User Mode Instruction Prevention(UMIP)
+# function test, below instructions should be GP exception blocked if
+# Current Privilege Level (CPL) is greater than 0.
+# UMIP instructions protected instructions as below:
+# * SGDT - Store Global Descriptor Table
+# * SIDT - Store Interrupt Descriptor Table
+# * SLDT - Store Local Descriptor Table
+# * SMSW - Store Machine Status Word
+# * STR - Store Task Register
+# kconfig requirement: CONFIG_X86_INTEL_UMIP=y
+# cpu requirement: /proc/cpuinfo need contain umip
+
+TST_CNT=1
+TST_SETUP=setup
+TST_TESTFUNC=do_test
+TST_POS_ARGS=2
+TST_USAGE=usage
+TST_NEEDS_ROOT=1
+
+. tst_test.sh
+. umip_common.sh
+
+bin_name="$1"
+parm="$2"
+
+usage() {
+ cat <<__EOF
+ usage: ./$0 [bin_name][parm]
+ bin_name: Test cpu bin name like umip_gp_test and so on
+ parm: Test bin file parameter like 'g' and so on
+__EOF
+}
+
+# kernel config should set CONFIG_X86_INTEL_UMIP=y
+# /proc/cpuinfo should contain umip
+setup()
+{
+ func_name="umip"
+ config_umip="CONFIG_X86_INTEL_UMIP=y"
+
+ kconfig_check "$config_umip" \
+ || tst_brk TCONF "kernel config not set $config_umip"
+ cpu_info_check "$func_name" \
+ || tst_brk TCONF "/proc/cpuinfo no umip function"
+}
+
+# umip protect instruction should be blocked when user execute
+do_test()
+{
+ tst_res TINFO "Test $bin_name $parm"
+ EXPECT_FAIL "$bin_name" "$parm"
+}
+
+tst_run
diff --git a/testcases/kernel/security/umip/umip_gp_test.c b/testcases/kernel/security/umip/umip_gp_test.c
new file mode 100644
index 000000000..ae1068a60
--- /dev/null
+++ b/testcases/kernel/security/umip/umip_gp_test.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/*
+ * testcases/security/umip/umip_gp_test.c
+ * Copyright (C) 2018 Intel Corporation
+ * Author: Pengfei, Xu <pengfei.xu@intel.com>
+ */
+
+/*
+ * This test is for Intel User-Mode Execution Prevention(umip) test
+ *
+ * umip is a security feature present in new Intel Processors.
+ * If enabled, it prevents the execution of certain instructions
+ * if the Current Privilege Level (CPL) is greater than 0.
+ * If these instructions were executed while in CPL > 0, user space
+ * applications could not access to system-wide settings such as
+ * the global and local descriptor tables, the segment selectors to
+ * the current task state and the local descriptor table.
+ * UMIP is enabled by default at boot.
+ *
+ * History: Oct 23 2018 - created
+ * - Tested sgdt, sidt, sldt, smsw and str by asm in C
+ * all above 5 instruction should be #GP(general protection)
+ * exception in UMIP supproted and enabled platform, if
+ * disabled UMIP, will show instruction store results
+ * - Add parameter for each instruction test
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define GDT_LEN 10
+#define IDT_LEN 10
+
+void usage(void)
+{
+ printf("Usage: [g][i][l][m][t][a]\n");
+ printf("g Test sgdt\n");
+ printf("i Test sidt\n");
+ printf("l Test sldt\n");
+ printf("m Test smsw\n");
+ printf("t Test str\n");
+ printf("a Test all\n");
+}
+
+static void asm_sgdt(void)
+{
+ int i;
+ unsigned char val[GDT_LEN];
+
+ memset(val, 0, sizeof(val));
+
+ printf("RESULTS SGDT save at [%p]\n", val);
+ printf("Initial val:0x");
+ for (i = 0; i < GDT_LEN; i++)
+ printf("%02x", val[i]);
+
+ asm volatile("sgdt %0\n" : "=m" (val));
+ printf("\nSGDT results in val:\n");
+ printf("val:0x");
+ for (i = 0; i < GDT_LEN; i++)
+ printf("%02x", val[i]);
+ printf("\nDone.\n");
+}
+
+static void asm_sidt(void)
+{
+ int i;
+ unsigned char val[IDT_LEN];
+
+ memset(val, 0, sizeof(val));
+
+ printf("RESULTS SIDT save at [%p]\n", val);
+ printf("Initial val:0x");
+ for (i = 0; i < IDT_LEN; i++)
+ printf("%02x", val[i]);
+ asm volatile("sidt %0\n" : "=m" (val));
+ printf("\nSIDT results in val:\n");
+ printf("val:0x");
+ for (i = 0; i < GDT_LEN; i++)
+ printf("%02x", val[i]);
+ printf("\nDone.\n");
+}
+
+static void asm_sldt(void)
+{
+ unsigned long val;
+
+ printf("RESULTS SLDT save at [%p]\n", &val);
+ printf("Initial val:0x%lx", val);
+ asm volatile("sldt %0\n" : "=m" (val));
+
+ printf("\nSLDT results in val:\n");
+ printf("val:0x%lx", val);
+ printf("\nDone.\n");
+}
+
+static void asm_smsw(void)
+{
+ unsigned long val;
+
+ printf("RESULTS SMSW save at [%p]\n", &val);
+ printf("Initial val:0x%lx", val);
+ asm volatile("smsw %0\n" : "=m" (val));
+
+ printf("\nSMSW results in val:\n");
+ printf("val:0x%lx", val);
+ printf("\nDone.\n");
+}
+
+static void asm_str(void)
+{
+ unsigned long val;
+
+ printf("RESULTS STR save at [%p]\n", &val);
+ printf("Initial val:0x%lx", val);
+ asm volatile("str %0\n" : "=m" (val));
+
+ printf("\nSTR results in val:\n");
+ printf("val:0x%lx", val);
+ printf("\nDone.\n");
+}
+
+int main(int argc, char *argv[])
+{
+ char parm;
+
+ if (argc == 1) {
+ usage();
+ exit(1);
+ }
+ else {
+ if (sscanf(argv[1], "%c", &parm) == 1) {
+ printf("1 parameters: parm=%c\n", parm);
+ }
+ else {
+ printf("Get parameter failed.\n");
+ exit(1);
+ }
+ }
+
+ switch (parm) {
+ case 'a':
+ printf("Test all.\n");
+ asm_sgdt();
+ asm_sidt();
+ asm_sldt();
+ asm_smsw();
+ asm_str();
+ break;
+ case 'g':
+ asm_sgdt();
+ break;
+ case 'i':
+ asm_sidt();
+ break;
+ case 'l':
+ asm_sldt();
+ break;
+ case 'm':
+ asm_smsw();
+ break;
+ case 't':
+ asm_str();
+ break;
+ default:
+ usage();
+ exit(1);
+ }
+}
--
2.14.1
More information about the ltp
mailing list