diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/testing/selftests/x86/Makefile | 2 | ||||
-rw-r--r-- | tools/testing/selftests/x86/syscall_nt.c | 54 |
2 files changed, 55 insertions, 1 deletions
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index 986e7cbf118f..29089b24d18b 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile | |||
@@ -4,7 +4,7 @@ include ../lib.mk | |||
4 | 4 | ||
5 | .PHONY: all all_32 all_64 warn_32bit_failure clean | 5 | .PHONY: all all_32 all_64 warn_32bit_failure clean |
6 | 6 | ||
7 | TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs ldt_gdt | 7 | TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs ldt_gdt syscall_nt |
8 | TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn | 8 | TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn |
9 | 9 | ||
10 | TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) | 10 | TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) |
diff --git a/tools/testing/selftests/x86/syscall_nt.c b/tools/testing/selftests/x86/syscall_nt.c new file mode 100644 index 000000000000..60c06af4646a --- /dev/null +++ b/tools/testing/selftests/x86/syscall_nt.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * syscall_nt.c - checks syscalls with NT set | ||
3 | * Copyright (c) 2014-2015 Andrew Lutomirski | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * General Public License for more details. | ||
13 | * | ||
14 | * Some obscure user-space code requires the ability to make system calls | ||
15 | * with FLAGS.NT set. Make sure it works. | ||
16 | */ | ||
17 | |||
18 | #include <stdio.h> | ||
19 | #include <unistd.h> | ||
20 | #include <sys/syscall.h> | ||
21 | #include <asm/processor-flags.h> | ||
22 | |||
23 | #ifdef __x86_64__ | ||
24 | # define WIDTH "q" | ||
25 | #else | ||
26 | # define WIDTH "l" | ||
27 | #endif | ||
28 | |||
29 | static unsigned long get_eflags(void) | ||
30 | { | ||
31 | unsigned long eflags; | ||
32 | asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags)); | ||
33 | return eflags; | ||
34 | } | ||
35 | |||
36 | static void set_eflags(unsigned long eflags) | ||
37 | { | ||
38 | asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH | ||
39 | : : "rm" (eflags) : "flags"); | ||
40 | } | ||
41 | |||
42 | int main() | ||
43 | { | ||
44 | printf("[RUN]\tSet NT and issue a syscall\n"); | ||
45 | set_eflags(get_eflags() | X86_EFLAGS_NT); | ||
46 | syscall(SYS_getpid); | ||
47 | if (get_eflags() & X86_EFLAGS_NT) { | ||
48 | printf("[OK]\tThe syscall worked and NT is still set\n"); | ||
49 | return 0; | ||
50 | } else { | ||
51 | printf("[FAIL]\tThe syscall worked but NT was cleared\n"); | ||
52 | return 1; | ||
53 | } | ||
54 | } | ||