1a9c909ceSAndy Lutomirski /*
2a9c909ceSAndy Lutomirski  * syscall_nt.c - checks syscalls with NT set
3a9c909ceSAndy Lutomirski  * Copyright (c) 2014-2015 Andrew Lutomirski
4a9c909ceSAndy Lutomirski  *
5a9c909ceSAndy Lutomirski  * This program is free software; you can redistribute it and/or modify
6a9c909ceSAndy Lutomirski  * it under the terms and conditions of the GNU General Public License,
7a9c909ceSAndy Lutomirski  * version 2, as published by the Free Software Foundation.
8a9c909ceSAndy Lutomirski  *
9a9c909ceSAndy Lutomirski  * This program is distributed in the hope it will be useful, but
10a9c909ceSAndy Lutomirski  * WITHOUT ANY WARRANTY; without even the implied warranty of
11a9c909ceSAndy Lutomirski  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12a9c909ceSAndy Lutomirski  * General Public License for more details.
13a9c909ceSAndy Lutomirski  *
14a9c909ceSAndy Lutomirski  * Some obscure user-space code requires the ability to make system calls
15a9c909ceSAndy Lutomirski  * with FLAGS.NT set.  Make sure it works.
16a9c909ceSAndy Lutomirski  */
17a9c909ceSAndy Lutomirski 
18a9c909ceSAndy Lutomirski #include <stdio.h>
19a9c909ceSAndy Lutomirski #include <unistd.h>
20a9c909ceSAndy Lutomirski #include <sys/syscall.h>
21a9c909ceSAndy Lutomirski #include <asm/processor-flags.h>
22a9c909ceSAndy Lutomirski 
23a9c909ceSAndy Lutomirski #ifdef __x86_64__
24a9c909ceSAndy Lutomirski # define WIDTH "q"
25a9c909ceSAndy Lutomirski #else
26a9c909ceSAndy Lutomirski # define WIDTH "l"
27a9c909ceSAndy Lutomirski #endif
28a9c909ceSAndy Lutomirski 
29a9c909ceSAndy Lutomirski static unsigned long get_eflags(void)
30a9c909ceSAndy Lutomirski {
31a9c909ceSAndy Lutomirski 	unsigned long eflags;
32a9c909ceSAndy Lutomirski 	asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags));
33a9c909ceSAndy Lutomirski 	return eflags;
34a9c909ceSAndy Lutomirski }
35a9c909ceSAndy Lutomirski 
36a9c909ceSAndy Lutomirski static void set_eflags(unsigned long eflags)
37a9c909ceSAndy Lutomirski {
38a9c909ceSAndy Lutomirski 	asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH
39a9c909ceSAndy Lutomirski 		      : : "rm" (eflags) : "flags");
40a9c909ceSAndy Lutomirski }
41a9c909ceSAndy Lutomirski 
42a9c909ceSAndy Lutomirski int main()
43a9c909ceSAndy Lutomirski {
44a9c909ceSAndy Lutomirski 	printf("[RUN]\tSet NT and issue a syscall\n");
45a9c909ceSAndy Lutomirski 	set_eflags(get_eflags() | X86_EFLAGS_NT);
46a9c909ceSAndy Lutomirski 	syscall(SYS_getpid);
47a9c909ceSAndy Lutomirski 	if (get_eflags() & X86_EFLAGS_NT) {
48a9c909ceSAndy Lutomirski 		printf("[OK]\tThe syscall worked and NT is still set\n");
49a9c909ceSAndy Lutomirski 		return 0;
50a9c909ceSAndy Lutomirski 	} else {
51a9c909ceSAndy Lutomirski 		printf("[FAIL]\tThe syscall worked but NT was cleared\n");
52a9c909ceSAndy Lutomirski 		return 1;
53a9c909ceSAndy Lutomirski 	}
54a9c909ceSAndy Lutomirski }
55