2019-05-29 07:18:02 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2015-08-17 12:22:52 -07:00
/*
* syscall_nt . c - checks syscalls with NT set
* Copyright ( c ) 2014 - 2015 Andrew Lutomirski
*
* Some obscure user - space code requires the ability to make system calls
* with FLAGS . NT set . Make sure it works .
*/
# include <stdio.h>
# include <unistd.h>
2016-03-09 19:00:24 -08:00
# include <string.h>
# include <signal.h>
# include <err.h>
2015-08-17 12:22:52 -07:00
# include <sys/syscall.h>
2020-06-26 10:21:16 -07:00
# include "helpers.h"
2015-08-17 12:22:52 -07:00
2016-03-09 19:00:24 -08:00
static unsigned int nerrs ;
static void sethandler ( int sig , void ( * handler ) ( int , siginfo_t * , void * ) ,
int flags )
2015-08-17 12:22:52 -07:00
{
2016-03-09 19:00:24 -08:00
struct sigaction sa ;
memset ( & sa , 0 , sizeof ( sa ) ) ;
sa . sa_sigaction = handler ;
sa . sa_flags = SA_SIGINFO | flags ;
sigemptyset ( & sa . sa_mask ) ;
if ( sigaction ( sig , & sa , 0 ) )
err ( 1 , " sigaction " ) ;
}
static void sigtrap ( int sig , siginfo_t * si , void * ctx_void )
{
}
static void do_it ( unsigned long extraflags )
{
unsigned long flags ;
set_eflags ( get_eflags ( ) | extraflags ) ;
2015-08-17 12:22:52 -07:00
syscall ( SYS_getpid ) ;
2016-03-09 19:00:24 -08:00
flags = get_eflags ( ) ;
2020-06-26 10:21:15 -07:00
set_eflags ( X86_EFLAGS_IF | X86_EFLAGS_FIXED ) ;
2016-03-09 19:00:24 -08:00
if ( ( flags & extraflags ) = = extraflags ) {
printf ( " [OK] \t The syscall worked and flags are still set \n " ) ;
2015-08-17 12:22:52 -07:00
} else {
2016-03-09 19:00:24 -08:00
printf ( " [FAIL] \t The syscall worked but flags were cleared (flags = 0x%lx but expected 0x%lx set) \n " ,
flags , extraflags ) ;
nerrs + + ;
2015-08-17 12:22:52 -07:00
}
}
2016-03-09 19:00:24 -08:00
int main ( void )
{
printf ( " [RUN] \t Set NT and issue a syscall \n " ) ;
do_it ( X86_EFLAGS_NT ) ;
2020-06-26 10:21:14 -07:00
printf ( " [RUN] \t Set AC and issue a syscall \n " ) ;
do_it ( X86_EFLAGS_AC ) ;
printf ( " [RUN] \t Set NT|AC and issue a syscall \n " ) ;
do_it ( X86_EFLAGS_NT | X86_EFLAGS_AC ) ;
2016-03-09 19:00:24 -08:00
/*
* Now try it again with TF set - - TF forces returns via IRET in all
* cases except non - ptregs - using 64 - bit full fast path syscalls .
*/
sethandler ( SIGTRAP , sigtrap , 0 ) ;
2020-06-26 10:21:14 -07:00
printf ( " [RUN] \t Set TF and issue a syscall \n " ) ;
do_it ( X86_EFLAGS_TF ) ;
2016-03-09 19:00:24 -08:00
printf ( " [RUN] \t Set NT|TF and issue a syscall \n " ) ;
do_it ( X86_EFLAGS_NT | X86_EFLAGS_TF ) ;
2020-06-26 10:21:14 -07:00
printf ( " [RUN] \t Set AC|TF and issue a syscall \n " ) ;
do_it ( X86_EFLAGS_AC | X86_EFLAGS_TF ) ;
printf ( " [RUN] \t Set NT|AC|TF and issue a syscall \n " ) ;
do_it ( X86_EFLAGS_NT | X86_EFLAGS_AC | X86_EFLAGS_TF ) ;
2020-07-03 10:02:54 -07:00
/*
* Now try DF . This is evil and it ' s plausible that we will crash
* glibc , but glibc would have to do something rather surprising
* for this to happen .
*/
printf ( " [RUN] \t Set DF and issue a syscall \n " ) ;
do_it ( X86_EFLAGS_DF ) ;
printf ( " [RUN] \t Set TF|DF and issue a syscall \n " ) ;
do_it ( X86_EFLAGS_TF | X86_EFLAGS_DF ) ;
2016-03-09 19:00:24 -08:00
return nerrs = = 0 ? 0 : 1 ;
}