103 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Corrupt the XSTATE header in a signal frame4 *5 * Based on analysis and a test case from Thomas Gleixner.6 */7 8#define _GNU_SOURCE9 10#include <stdlib.h>11#include <stdio.h>12#include <string.h>13#include <sched.h>14#include <signal.h>15#include <err.h>16#include <unistd.h>17#include <stdint.h>18#include <sys/wait.h>19 20#include "../kselftest.h" /* For __cpuid_count() */21 22static inline int xsave_enabled(void)23{24 unsigned int eax, ebx, ecx, edx;25 26 __cpuid_count(0x1, 0x0, eax, ebx, ecx, edx);27 28 /* Is CR4.OSXSAVE enabled ? */29 return ecx & (1U << 27);30}31 32static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),33 int flags)34{35 struct sigaction sa;36 37 memset(&sa, 0, sizeof(sa));38 sa.sa_sigaction = handler;39 sa.sa_flags = SA_SIGINFO | flags;40 sigemptyset(&sa.sa_mask);41 if (sigaction(sig, &sa, 0))42 err(1, "sigaction");43}44 45static void sigusr1(int sig, siginfo_t *info, void *uc_void)46{47 ucontext_t *uc = uc_void;48 uint8_t *fpstate = (uint8_t *)uc->uc_mcontext.fpregs;49 uint64_t *xfeatures = (uint64_t *)(fpstate + 512);50 51 printf("\tWreck XSTATE header\n");52 /* Wreck the first reserved bytes in the header */53 *(xfeatures + 2) = 0xfffffff;54}55 56static void sigsegv(int sig, siginfo_t *info, void *uc_void)57{58 printf("\tGot SIGSEGV\n");59}60 61int main(void)62{63 cpu_set_t set;64 65 sethandler(SIGUSR1, sigusr1, 0);66 sethandler(SIGSEGV, sigsegv, 0);67 68 if (!xsave_enabled()) {69 printf("[SKIP] CR4.OSXSAVE disabled.\n");70 return 0;71 }72 73 CPU_ZERO(&set);74 CPU_SET(0, &set);75 76 /*77 * Enforce that the child runs on the same CPU78 * which in turn forces a schedule.79 */80 sched_setaffinity(getpid(), sizeof(set), &set);81 82 printf("[RUN]\tSend ourselves a signal\n");83 raise(SIGUSR1);84 85 printf("[OK]\tBack from the signal. Now schedule.\n");86 pid_t child = fork();87 if (child < 0)88 err(1, "fork");89 if (child == 0)90 return 0;91 if (child)92 waitpid(child, NULL, 0);93 printf("[OK]\tBack in the main thread.\n");94 95 /*96 * We could try to confirm that extended state is still preserved97 * when we schedule. For now, the only indication of failure is98 * a warning in the kernel logs.99 */100 101 return 0;102}103