root/tools/testing/selftests/x86/syscall_nt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_eflags
  2. set_eflags
  3. sethandler
  4. sigtrap
  5. do_it
  6. main

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * syscall_nt.c - checks syscalls with NT set
   4  * Copyright (c) 2014-2015 Andrew Lutomirski
   5  *
   6  * Some obscure user-space code requires the ability to make system calls
   7  * with FLAGS.NT set.  Make sure it works.
   8  */
   9 
  10 #include <stdio.h>
  11 #include <unistd.h>
  12 #include <string.h>
  13 #include <signal.h>
  14 #include <err.h>
  15 #include <sys/syscall.h>
  16 #include <asm/processor-flags.h>
  17 
  18 #ifdef __x86_64__
  19 # define WIDTH "q"
  20 #else
  21 # define WIDTH "l"
  22 #endif
  23 
  24 static unsigned int nerrs;
  25 
  26 static unsigned long get_eflags(void)
  27 {
  28         unsigned long eflags;
  29         asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags));
  30         return eflags;
  31 }
  32 
  33 static void set_eflags(unsigned long eflags)
  34 {
  35         asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH
  36                       : : "rm" (eflags) : "flags");
  37 }
  38 
  39 static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
  40                        int flags)
  41 {
  42         struct sigaction sa;
  43         memset(&sa, 0, sizeof(sa));
  44         sa.sa_sigaction = handler;
  45         sa.sa_flags = SA_SIGINFO | flags;
  46         sigemptyset(&sa.sa_mask);
  47         if (sigaction(sig, &sa, 0))
  48                 err(1, "sigaction");
  49 }
  50 
  51 static void sigtrap(int sig, siginfo_t *si, void *ctx_void)
  52 {
  53 }
  54 
  55 static void do_it(unsigned long extraflags)
  56 {
  57         unsigned long flags;
  58 
  59         set_eflags(get_eflags() | extraflags);
  60         syscall(SYS_getpid);
  61         flags = get_eflags();
  62         if ((flags & extraflags) == extraflags) {
  63                 printf("[OK]\tThe syscall worked and flags are still set\n");
  64         } else {
  65                 printf("[FAIL]\tThe syscall worked but flags were cleared (flags = 0x%lx but expected 0x%lx set)\n",
  66                        flags, extraflags);
  67                 nerrs++;
  68         }
  69 }
  70 
  71 int main(void)
  72 {
  73         printf("[RUN]\tSet NT and issue a syscall\n");
  74         do_it(X86_EFLAGS_NT);
  75 
  76         /*
  77          * Now try it again with TF set -- TF forces returns via IRET in all
  78          * cases except non-ptregs-using 64-bit full fast path syscalls.
  79          */
  80 
  81         sethandler(SIGTRAP, sigtrap, 0);
  82 
  83         printf("[RUN]\tSet NT|TF and issue a syscall\n");
  84         do_it(X86_EFLAGS_NT | X86_EFLAGS_TF);
  85 
  86         return nerrs == 0 ? 0 : 1;
  87 }

/* [<][>][^][v][top][bottom][index][help] */