Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp2315932imm; Thu, 7 Jun 2018 08:39:39 -0700 (PDT) X-Google-Smtp-Source: ADUXVKJdNrx1aodkD8Q8837EnrVkfxHkTlkUHpVJirRuU/xv6EEAhvZpR8VF9Dj1XeegFpNUA9bz X-Received: by 2002:a17:902:4b:: with SMTP id 69-v6mr2616914pla.178.1528385979278; Thu, 07 Jun 2018 08:39:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1528385979; cv=none; d=google.com; s=arc-20160816; b=gJjugBiGKuwLAjNmlHQpSix4QpTRK/kp8t8fmyqp3d5OsN3tJObEUNnXqvcq3ZAAyI tQpW2NpovL1MnWdWGQEym1luoLK9+0fd35dOjt6QdJHRQapjni7t1ygdiNdNnjvnmSLZ Mg7EqYymzkIyqF+vNi0+MmanJ0Qs1v9GFAGA7oLjSFkvkcr9hH9TGq53thZr6B+Unx7N ywTSIT+xxoHVpI5WkY4CuSq7ONU8kQ3V2NTA/8bAq7sqrox+5KOC7+enV+KI7R7R5Hcb ZHhcoIPUimEVl5II5NpfIyFNNXwdSHZtZSq74FvQmj9wCHKL2ouS+inCBHGp3m9xuauF HVeA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:to:from:arc-authentication-results; bh=SSunv5I7PGu6ThmIPT5HqkLNEgN7YNAqZY3HGYfbg10=; b=HboPJRctUqD5zWuUhU8WGXyycIQ7VsOcR7nPaG6gAdAUcfbSIYR40lHtDIeB2C58ds MGMNl8YJHjvqu4S3hlVSTxekmE2ICSyU4a7+KlbG6oyzEenGSDNHpyQiTl9KpBoNlEqq aQRQotMOGBm0GCQu1eHejEdLuXMt9nRXKseraLsmNe9DyndqjjgKff7d5yzcLWH/jetp fwPXBb4xf8DKHhx3WJF/K3PiA+nzlXALRAQWaT5oCA3tqQrKZPw1tY/IVFGJP+ApKF9k XbjJiedXGhcjvaNQCPjSrppoHoggXNl8NWXFZMx6GTRLdcSV4rDrGzQMiKxCJuRr3Og8 jnCQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a6-v6si28420277pgd.579.2018.06.07.08.39.22; Thu, 07 Jun 2018 08:39:39 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934802AbeFGPhC (ORCPT + 99 others); Thu, 7 Jun 2018 11:37:02 -0400 Received: from mga17.intel.com ([192.55.52.151]:61237 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933832AbeFGOmc (ORCPT ); Thu, 7 Jun 2018 10:42:32 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Jun 2018 07:42:30 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.49,486,1520924400"; d="scan'208";a="235505954" Received: from 2b52.sc.intel.com ([143.183.136.51]) by fmsmga006.fm.intel.com with ESMTP; 07 Jun 2018 07:42:30 -0700 From: Yu-cheng Yu To: linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-mm@kvack.org, linux-arch@vger.kernel.org, x86@kernel.org, "H. Peter Anvin" , Thomas Gleixner , Ingo Molnar , "H.J. Lu" , Vedvyas Shanbhogue , "Ravi V. Shankar" , Dave Hansen , Andy Lutomirski , Jonathan Corbet , Oleg Nesterov , Arnd Bergmann , Mike Kravetz Subject: [PATCH 6/7] tools: Add cetcmd Date: Thu, 7 Jun 2018 07:38:54 -0700 Message-Id: <20180607143855.3681-7-yu-cheng.yu@intel.com> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180607143855.3681-1-yu-cheng.yu@intel.com> References: <20180607143855.3681-1-yu-cheng.yu@intel.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: "H.J. Lu" Introduce CET command-line utility. This utility allows system admin to enable/disable CET features and set default shadow stack size. Signed-off-by: H.J. Lu --- tools/Makefile | 13 +-- tools/arch/x86/include/uapi/asm/elf_property.h | 16 +++ tools/arch/x86/include/uapi/asm/prctl.h | 33 ++++++ tools/cet/.gitignore | 1 + tools/cet/Makefile | 11 ++ tools/cet/cetcmd.c | 134 +++++++++++++++++++++++++ tools/include/uapi/asm/elf_property.h | 4 + tools/include/uapi/asm/prctl.h | 4 + 8 files changed, 210 insertions(+), 6 deletions(-) create mode 100644 tools/arch/x86/include/uapi/asm/elf_property.h create mode 100644 tools/arch/x86/include/uapi/asm/prctl.h create mode 100644 tools/cet/.gitignore create mode 100644 tools/cet/Makefile create mode 100644 tools/cet/cetcmd.c create mode 100644 tools/include/uapi/asm/elf_property.h create mode 100644 tools/include/uapi/asm/prctl.h diff --git a/tools/Makefile b/tools/Makefile index be02c8b904db..bdca71e61d22 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -10,6 +10,7 @@ help: @echo 'Possible targets:' @echo '' @echo ' acpi - ACPI tools' + @echo ' cet - Intel CET tools' @echo ' cgroup - cgroup tools' @echo ' cpupower - a tool for all things x86 CPU power' @echo ' firewire - the userspace part of nosy, an IEEE-1394 traffic sniffer' @@ -59,7 +60,7 @@ acpi: FORCE cpupower: FORCE $(call descend,power/$@) -cgroup firewire hv guest spi usb virtio vm bpf iio gpio objtool leds wmi: FORCE +cet cgroup firewire hv guest spi usb virtio vm bpf iio gpio objtool leds wmi: FORCE $(call descend,$@) liblockdep: FORCE @@ -91,7 +92,7 @@ freefall: FORCE kvm_stat: FORCE $(call descend,kvm/$@) -all: acpi cgroup cpupower gpio hv firewire liblockdep \ +all: acpi cet cgroup cpupower gpio hv firewire liblockdep \ perf selftests spi turbostat usb \ virtio vm bpf x86_energy_perf_policy \ tmon freefall iio objtool kvm_stat wmi @@ -102,7 +103,7 @@ acpi_install: cpupower_install: $(call descend,power/$(@:_install=),install) -cgroup_install firewire_install gpio_install hv_install iio_install perf_install spi_install usb_install virtio_install vm_install bpf_install objtool_install wmi_install: +cet_install cgroup_install firewire_install gpio_install hv_install iio_install perf_install spi_install usb_install virtio_install vm_install bpf_install objtool_install wmi_install: $(call descend,$(@:_install=),install) liblockdep_install: @@ -123,7 +124,7 @@ freefall_install: kvm_stat_install: $(call descend,kvm/$(@:_install=),install) -install: acpi_install cgroup_install cpupower_install gpio_install \ +install: acpi_install cet_install cgroup_install cpupower_install gpio_install \ hv_install firewire_install iio_install liblockdep_install \ perf_install selftests_install turbostat_install usb_install \ virtio_install vm_install bpf_install x86_energy_perf_policy_install \ @@ -136,7 +137,7 @@ acpi_clean: cpupower_clean: $(call descend,power/cpupower,clean) -cgroup_clean hv_clean firewire_clean spi_clean usb_clean virtio_clean vm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean: +cet_clean cgroup_clean hv_clean firewire_clean spi_clean usb_clean virtio_clean vm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean: $(call descend,$(@:_clean=),clean) liblockdep_clean: @@ -170,7 +171,7 @@ freefall_clean: build_clean: $(call descend,build,clean) -clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean \ +clean: acpi_clean cet_clean cgroup_clean cpupower_clean hv_clean firewire_clean \ perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \ vm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \ diff --git a/tools/arch/x86/include/uapi/asm/elf_property.h b/tools/arch/x86/include/uapi/asm/elf_property.h new file mode 100644 index 000000000000..343a871b8fc1 --- /dev/null +++ b/tools/arch/x86/include/uapi/asm/elf_property.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _UAPI_ASM_X86_ELF_PROPERTY_H +#define _UAPI_ASM_X86_ELF_PROPERTY_H + +/* + * pr_type + */ +#define GNU_PROPERTY_X86_FEATURE_1_AND (0xc0000002) + +/* + * Bits for GNU_PROPERTY_X86_FEATURE_1_AND + */ +#define GNU_PROPERTY_X86_FEATURE_1_SHSTK (0x00000002) +#define GNU_PROPERTY_X86_FEATURE_1_IBT (0x00000001) + +#endif /* _UAPI_ASM_X86_ELF_PROPERTY_H */ diff --git a/tools/arch/x86/include/uapi/asm/prctl.h b/tools/arch/x86/include/uapi/asm/prctl.h new file mode 100644 index 000000000000..fef476d2d2f6 --- /dev/null +++ b/tools/arch/x86/include/uapi/asm/prctl.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _ASM_X86_PRCTL_H +#define _ASM_X86_PRCTL_H + +#define ARCH_SET_GS 0x1001 +#define ARCH_SET_FS 0x1002 +#define ARCH_GET_FS 0x1003 +#define ARCH_GET_GS 0x1004 + +#define ARCH_GET_CPUID 0x1011 +#define ARCH_SET_CPUID 0x1012 + +#define ARCH_MAP_VDSO_X32 0x2001 +#define ARCH_MAP_VDSO_32 0x2002 +#define ARCH_MAP_VDSO_64 0x2003 + +#define ARCH_CET_STATUS 0x3001 +#define ARCH_CET_DISABLE 0x3002 +#define ARCH_CET_LOCK 0x3003 +#define ARCH_CET_EXEC 0x3004 +#define ARCH_CET_ALLOC_SHSTK 0x3005 +#define ARCH_CET_PUSH_SHSTK 0x3006 +#define ARCH_CET_LEGACY_BITMAP 0x3007 + +/* + * Settings for ARCH_CET_EXEC + */ +#define CET_EXEC_ELF_PROPERTY 0 +#define CET_EXEC_ALWAYS_OFF 1 +#define CET_EXEC_ALWAYS_ON 2 +#define CET_EXEC_MAX CET_EXEC_ALWAYS_ON + +#endif /* _ASM_X86_PRCTL_H */ diff --git a/tools/cet/.gitignore b/tools/cet/.gitignore new file mode 100644 index 000000000000..bd100f593454 --- /dev/null +++ b/tools/cet/.gitignore @@ -0,0 +1 @@ +cetcmd diff --git a/tools/cet/Makefile b/tools/cet/Makefile new file mode 100644 index 000000000000..fae42b84d796 --- /dev/null +++ b/tools/cet/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Makefile for CET tools + +CFLAGS = -O2 -g -Wall -Wextra -I../include/uapi + +all: cetcmd +%: %.c + $(CC) $(CFLAGS) -o $@ $^ + +clean: + $(RM) cetcmd diff --git a/tools/cet/cetcmd.c b/tools/cet/cetcmd.c new file mode 100644 index 000000000000..dbbfb5267c1f --- /dev/null +++ b/tools/cet/cetcmd.c @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum command_line_switch { + OPTION_ELF_PROPERTY = 150, + OPTION_ALWAYS_OFF, + OPTION_ALWAYS_ON, + OPTION_SHSTK_SIZE +}; + +static const struct option options[] = { + {"property", no_argument, 0, OPTION_ELF_PROPERTY}, + {"off", no_argument, 0, OPTION_ALWAYS_OFF}, + {"on", no_argument, 0, OPTION_ALWAYS_ON}, + {"shstk-size", required_argument, 0, OPTION_SHSTK_SIZE}, + {"feature", required_argument, 0, 'f'}, + {"help", no_argument, 0, 'h'}, + {0, no_argument, 0, 0} +}; + +__attribute__((__noreturn__)) +static void +usage(FILE *stream, int exit_status) +{ + fprintf(stream, "Usage: %s -- command [args]\n", + program_invocation_short_name); + fprintf(stream, " Run command with CET features\n"); + fprintf(stream, " The options are:\n"); + fprintf(stream, + "\t--property Enable CET features based on ELF property note\n" + "\t--off Always disable CET features\n" + "\t--on Always enable CET features\n" + "\t-f, --feature [ibt|shstk] Control CET [IBT|SHSTK] feature\n" + "\t--shstk-size SIZE Set shadow stack size\n" + "\t-h --help Display this information\n"); + + exit(exit_status); +} + +extern int arch_prctl(int, unsigned long *); + +int +main(int argc, char *const *argv, char *const *envp) +{ + int c; + unsigned long values[3] = {0, -1, 0}; + unsigned long status[3]; + unsigned long shstk_size = -1; + char **args; + size_t i, num_of_args; + + while ((c = getopt_long(argc, argv, "f:h", + options, (int *) 0)) != EOF) { + switch (c) { + case OPTION_ELF_PROPERTY: + values[1] = CET_EXEC_ELF_PROPERTY; + break; + + case OPTION_ALWAYS_OFF: + values[1] = CET_EXEC_ALWAYS_OFF; + break; + + case OPTION_ALWAYS_ON: + values[1] = CET_EXEC_ALWAYS_ON; + break; + + case OPTION_SHSTK_SIZE: + shstk_size = strtol(optarg, NULL, 0); + break; + + case 'f': + if (strcasecmp(optarg, "ibt") == 0) + values[0] = GNU_PROPERTY_X86_FEATURE_1_IBT; + else if (strcasecmp(optarg, "shstk") == 0) + values[0] = GNU_PROPERTY_X86_FEATURE_1_SHSTK; + else + usage(stderr, EXIT_FAILURE); + break; + + case 'h': + usage(stdout, EXIT_SUCCESS); + + default: + usage(stderr, EXIT_FAILURE); + } + } + + if ((optind + 1) > argc || + (values[1] == (unsigned long)-1 && + shstk_size == (unsigned long)-1)) + usage(stderr, EXIT_FAILURE); + + /* If --shstk-size isn't used, get the current shadow stack size. */ + if (shstk_size == (unsigned long)-1) { + if (arch_prctl(ARCH_CET_STATUS, status) < 0) + error(EXIT_FAILURE, errno, "arch_prctl failed\n"); + shstk_size = status[2]; + } + + /* If --property/--off/--on aren't used, clear all features. */ + if (values[1] == (unsigned long)-1) { + values[0] = 0; + values[1] = 0; + } else { + if (values[0] == 0) + values[0] = (GNU_PROPERTY_X86_FEATURE_1_IBT | + GNU_PROPERTY_X86_FEATURE_1_SHSTK); + } + + values[2] = shstk_size; + if (arch_prctl(ARCH_CET_EXEC, values) < 0) + error(EXIT_FAILURE, errno, "arch_prctl failed\n"); + + num_of_args = argc - optind + 1; + args = malloc(num_of_args * sizeof(char *)); + if (args == NULL) + error(EXIT_FAILURE, errno, "malloc failed\n"); + + for (i = 0; i < num_of_args; i++) + args[i] = argv[optind + i]; + args[i] = NULL; + + return execvpe(argv[optind], args, envp); +} diff --git a/tools/include/uapi/asm/elf_property.h b/tools/include/uapi/asm/elf_property.h new file mode 100644 index 000000000000..1281b4e1a578 --- /dev/null +++ b/tools/include/uapi/asm/elf_property.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#if defined(__i386__) || defined(__x86_64__) +#include "../../arch/x86/include/uapi/asm/elf_property.h" +#endif \ No newline at end of file diff --git a/tools/include/uapi/asm/prctl.h b/tools/include/uapi/asm/prctl.h new file mode 100644 index 000000000000..b0894b828b06 --- /dev/null +++ b/tools/include/uapi/asm/prctl.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#if defined(__i386__) || defined(__x86_64__) +#include "../../arch/x86/include/uapi/asm/prctl.h" +#endif \ No newline at end of file -- 2.15.1