brintos

brintos / linux-shallow public Read only

0
0
Text · 2.1 KiB · cf9ce8f Raw
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