linux/tools/testing/selftests/x86/vdso_restorer.c
<<
>>
Prefs
   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. */
  33struct real_sigaction {
  34        void *handler;
  35        unsigned long flags;
  36        void *restorer;
  37        unsigned int mask[2];
  38};
  39
  40static volatile sig_atomic_t handler_called;
  41
  42static void handler_with_siginfo(int sig, siginfo_t *info, void *ctx_void)
  43{
  44        handler_called = 1;
  45}
  46
  47static void handler_without_siginfo(int sig)
  48{
  49        handler_called = 1;
  50}
  51
  52int 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