Home | History | Annotate | Download | only in x86
      1 /*
      2  * vdso_restorer.c - tests vDSO-based signal restore
      3  * Copyright (c) 2015 Andrew Lutomirski
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms and conditions of the GNU General Public License,
      7  * version 2, as published by the Free Software Foundation.
      8  *
      9  * This program is distributed in the hope it will be useful, but
     10  * WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * General Public License for more details.
     13  *
     14  * This makes sure that sa_restorer == NULL keeps working on 32-bit
     15  * configurations.  Modern glibc doesn't use it under any circumstances,
     16  * so it's easy to overlook breakage.
     17  *
     18  * 64-bit userspace has never supported sa_restorer == NULL, so this is
     19  * 32-bit only.
     20  */
     21 
     22 #define _GNU_SOURCE
     23 
     24 #include <err.h>
     25 #include <stdio.h>
     26 #include <string.h>
     27 #include <signal.h>
     28 #include <unistd.h>
     29 #include <syscall.h>
     30 #include <sys/syscall.h>
     31 
     32 /* Open-code this -- the headers are too messy to easily use them. */
     33 struct real_sigaction {
     34 	void *handler;
     35 	unsigned long flags;
     36 	void *restorer;
     37 	unsigned int mask[2];
     38 };
     39 
     40 static volatile sig_atomic_t handler_called;
     41 
     42 static void handler_with_siginfo(int sig, siginfo_t *info, void *ctx_void)
     43 {
     44 	handler_called = 1;
     45 }
     46 
     47 static void handler_without_siginfo(int sig)
     48 {
     49 	handler_called = 1;
     50 }
     51 
     52 int main()
     53 {
     54 	int nerrs = 0;
     55 	struct real_sigaction sa;
     56 
     57 	memset(&sa, 0, sizeof(sa));
     58 	sa.handler = handler_with_siginfo;
     59 	sa.flags = SA_SIGINFO;
     60 	sa.restorer = NULL;	/* request kernel-provided restorer */
     61 
     62 	if (syscall(SYS_rt_sigaction, SIGUSR1, &sa, NULL, 8) != 0)
     63 		err(1, "raw rt_sigaction syscall");
     64 
     65 	raise(SIGUSR1);
     66 
     67 	if (handler_called) {
     68 		printf("[OK]\tSA_SIGINFO handler returned successfully\n");
     69 	} else {
     70 		printf("[FAIL]\tSA_SIGINFO handler was not called\n");
     71 		nerrs++;
     72 	}
     73 
     74 	sa.flags = 0;
     75 	sa.handler = handler_without_siginfo;
     76 	if (syscall(SYS_sigaction, SIGUSR1, &sa, 0) != 0)
     77 		err(1, "raw sigaction syscall");
     78 	handler_called = 0;
     79 
     80 	raise(SIGUSR1);
     81 
     82 	if (handler_called) {
     83 		printf("[OK]\t!SA_SIGINFO handler returned successfully\n");
     84 	} else {
     85 		printf("[FAIL]\t!SA_SIGINFO handler was not called\n");
     86 		nerrs++;
     87 	}
     88 }
     89