12025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2a9c909ceSAndy Lutomirski /*
3a9c909ceSAndy Lutomirski * syscall_nt.c - checks syscalls with NT set
4a9c909ceSAndy Lutomirski * Copyright (c) 2014-2015 Andrew Lutomirski
5a9c909ceSAndy Lutomirski *
6a9c909ceSAndy Lutomirski * Some obscure user-space code requires the ability to make system calls
7a9c909ceSAndy Lutomirski * with FLAGS.NT set. Make sure it works.
8a9c909ceSAndy Lutomirski */
9a9c909ceSAndy Lutomirski
10a9c909ceSAndy Lutomirski #include <stdio.h>
11a9c909ceSAndy Lutomirski #include <unistd.h>
12a318beeaSAndy Lutomirski #include <string.h>
13a318beeaSAndy Lutomirski #include <signal.h>
14a318beeaSAndy Lutomirski #include <err.h>
15a9c909ceSAndy Lutomirski #include <sys/syscall.h>
16a9c909ceSAndy Lutomirski
17cced0b24SAndy Lutomirski #include "helpers.h"
18a9c909ceSAndy Lutomirski
19a318beeaSAndy Lutomirski static unsigned int nerrs;
20a318beeaSAndy Lutomirski
sethandler(int sig,void (* handler)(int,siginfo_t *,void *),int flags)21a318beeaSAndy Lutomirski static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
22a318beeaSAndy Lutomirski int flags)
23a318beeaSAndy Lutomirski {
24a318beeaSAndy Lutomirski struct sigaction sa;
25a318beeaSAndy Lutomirski memset(&sa, 0, sizeof(sa));
26a318beeaSAndy Lutomirski sa.sa_sigaction = handler;
27a318beeaSAndy Lutomirski sa.sa_flags = SA_SIGINFO | flags;
28a318beeaSAndy Lutomirski sigemptyset(&sa.sa_mask);
29a318beeaSAndy Lutomirski if (sigaction(sig, &sa, 0))
30a318beeaSAndy Lutomirski err(1, "sigaction");
31a318beeaSAndy Lutomirski }
32a318beeaSAndy Lutomirski
sigtrap(int sig,siginfo_t * si,void * ctx_void)33a318beeaSAndy Lutomirski static void sigtrap(int sig, siginfo_t *si, void *ctx_void)
34a318beeaSAndy Lutomirski {
35a318beeaSAndy Lutomirski }
36a318beeaSAndy Lutomirski
do_it(unsigned long extraflags)37a318beeaSAndy Lutomirski static void do_it(unsigned long extraflags)
38a318beeaSAndy Lutomirski {
39a318beeaSAndy Lutomirski unsigned long flags;
40a318beeaSAndy Lutomirski
41a318beeaSAndy Lutomirski set_eflags(get_eflags() | extraflags);
42a318beeaSAndy Lutomirski syscall(SYS_getpid);
43a318beeaSAndy Lutomirski flags = get_eflags();
44a61fa279SAndy Lutomirski set_eflags(X86_EFLAGS_IF | X86_EFLAGS_FIXED);
45a318beeaSAndy Lutomirski if ((flags & extraflags) == extraflags) {
46a318beeaSAndy Lutomirski printf("[OK]\tThe syscall worked and flags are still set\n");
47a318beeaSAndy Lutomirski } else {
48a318beeaSAndy Lutomirski printf("[FAIL]\tThe syscall worked but flags were cleared (flags = 0x%lx but expected 0x%lx set)\n",
49a318beeaSAndy Lutomirski flags, extraflags);
50a318beeaSAndy Lutomirski nerrs++;
51a318beeaSAndy Lutomirski }
52a318beeaSAndy Lutomirski }
53a318beeaSAndy Lutomirski
main(void)54a318beeaSAndy Lutomirski int main(void)
55a9c909ceSAndy Lutomirski {
56a9c909ceSAndy Lutomirski printf("[RUN]\tSet NT and issue a syscall\n");
57a318beeaSAndy Lutomirski do_it(X86_EFLAGS_NT);
58a318beeaSAndy Lutomirski
59e4ef7de1SAndy Lutomirski printf("[RUN]\tSet AC and issue a syscall\n");
60e4ef7de1SAndy Lutomirski do_it(X86_EFLAGS_AC);
61e4ef7de1SAndy Lutomirski
62e4ef7de1SAndy Lutomirski printf("[RUN]\tSet NT|AC and issue a syscall\n");
63e4ef7de1SAndy Lutomirski do_it(X86_EFLAGS_NT | X86_EFLAGS_AC);
64e4ef7de1SAndy Lutomirski
65a318beeaSAndy Lutomirski /*
66a318beeaSAndy Lutomirski * Now try it again with TF set -- TF forces returns via IRET in all
67a318beeaSAndy Lutomirski * cases except non-ptregs-using 64-bit full fast path syscalls.
68a318beeaSAndy Lutomirski */
69a318beeaSAndy Lutomirski
70a318beeaSAndy Lutomirski sethandler(SIGTRAP, sigtrap, 0);
71a318beeaSAndy Lutomirski
72e4ef7de1SAndy Lutomirski printf("[RUN]\tSet TF and issue a syscall\n");
73e4ef7de1SAndy Lutomirski do_it(X86_EFLAGS_TF);
74e4ef7de1SAndy Lutomirski
75a318beeaSAndy Lutomirski printf("[RUN]\tSet NT|TF and issue a syscall\n");
76a318beeaSAndy Lutomirski do_it(X86_EFLAGS_NT | X86_EFLAGS_TF);
77a318beeaSAndy Lutomirski
78e4ef7de1SAndy Lutomirski printf("[RUN]\tSet AC|TF and issue a syscall\n");
79e4ef7de1SAndy Lutomirski do_it(X86_EFLAGS_AC | X86_EFLAGS_TF);
80e4ef7de1SAndy Lutomirski
81e4ef7de1SAndy Lutomirski printf("[RUN]\tSet NT|AC|TF and issue a syscall\n");
82e4ef7de1SAndy Lutomirski do_it(X86_EFLAGS_NT | X86_EFLAGS_AC | X86_EFLAGS_TF);
83e4ef7de1SAndy Lutomirski
84*3c73b81aSAndy Lutomirski /*
85*3c73b81aSAndy Lutomirski * Now try DF. This is evil and it's plausible that we will crash
86*3c73b81aSAndy Lutomirski * glibc, but glibc would have to do something rather surprising
87*3c73b81aSAndy Lutomirski * for this to happen.
88*3c73b81aSAndy Lutomirski */
89*3c73b81aSAndy Lutomirski printf("[RUN]\tSet DF and issue a syscall\n");
90*3c73b81aSAndy Lutomirski do_it(X86_EFLAGS_DF);
91*3c73b81aSAndy Lutomirski
92*3c73b81aSAndy Lutomirski printf("[RUN]\tSet TF|DF and issue a syscall\n");
93*3c73b81aSAndy Lutomirski do_it(X86_EFLAGS_TF | X86_EFLAGS_DF);
94*3c73b81aSAndy Lutomirski
95a318beeaSAndy Lutomirski return nerrs == 0 ? 0 : 1;
96a9c909ceSAndy Lutomirski }
97