0001
0002
0003
0004
0005
0006
0007
0008 #define _GNU_SOURCE
0009
0010 #include <stdlib.h>
0011 #include <stdio.h>
0012 #include <string.h>
0013 #include <sched.h>
0014 #include <signal.h>
0015 #include <err.h>
0016 #include <unistd.h>
0017 #include <stdint.h>
0018 #include <sys/wait.h>
0019
0020 #include "../kselftest.h" /* For __cpuid_count() */
0021
0022 static inline int xsave_enabled(void)
0023 {
0024 unsigned int eax, ebx, ecx, edx;
0025
0026 __cpuid_count(0x1, 0x0, eax, ebx, ecx, edx);
0027
0028
0029 return ecx & (1U << 27);
0030 }
0031
0032 static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
0033 int flags)
0034 {
0035 struct sigaction sa;
0036
0037 memset(&sa, 0, sizeof(sa));
0038 sa.sa_sigaction = handler;
0039 sa.sa_flags = SA_SIGINFO | flags;
0040 sigemptyset(&sa.sa_mask);
0041 if (sigaction(sig, &sa, 0))
0042 err(1, "sigaction");
0043 }
0044
0045 static void sigusr1(int sig, siginfo_t *info, void *uc_void)
0046 {
0047 ucontext_t *uc = uc_void;
0048 uint8_t *fpstate = (uint8_t *)uc->uc_mcontext.fpregs;
0049 uint64_t *xfeatures = (uint64_t *)(fpstate + 512);
0050
0051 printf("\tWreck XSTATE header\n");
0052
0053 *(xfeatures + 2) = 0xfffffff;
0054 }
0055
0056 static void sigsegv(int sig, siginfo_t *info, void *uc_void)
0057 {
0058 printf("\tGot SIGSEGV\n");
0059 }
0060
0061 int main(void)
0062 {
0063 cpu_set_t set;
0064
0065 sethandler(SIGUSR1, sigusr1, 0);
0066 sethandler(SIGSEGV, sigsegv, 0);
0067
0068 if (!xsave_enabled()) {
0069 printf("[SKIP] CR4.OSXSAVE disabled.\n");
0070 return 0;
0071 }
0072
0073 CPU_ZERO(&set);
0074 CPU_SET(0, &set);
0075
0076
0077
0078
0079
0080 sched_setaffinity(getpid(), sizeof(set), &set);
0081
0082 printf("[RUN]\tSend ourselves a signal\n");
0083 raise(SIGUSR1);
0084
0085 printf("[OK]\tBack from the signal. Now schedule.\n");
0086 pid_t child = fork();
0087 if (child < 0)
0088 err(1, "fork");
0089 if (child == 0)
0090 return 0;
0091 if (child)
0092 waitpid(child, NULL, 0);
0093 printf("[OK]\tBack in the main thread.\n");
0094
0095
0096
0097
0098
0099
0100
0101 return 0;
0102 }