linux/tools/testing/selftests/x86/vdso_restorer.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * vdso_restorer.c - tests vDSO-based signal restore
   4 * Copyright (c) 2015 Andrew Lutomirski
   5 *
   6 * This makes sure that sa_restorer == NULL keeps working on 32-bit
   7 * configurations.  Modern glibc doesn't use it under any circumstances,
   8 * so it's easy to overlook breakage.
   9 *
  10 * 64-bit userspace has never supported sa_restorer == NULL, so this is
  11 * 32-bit only.
  12 */
  13
  14#define _GNU_SOURCE
  15
  16#include <err.h>
  17#include <stdio.h>
  18#include <string.h>
  19#include <signal.h>
  20#include <unistd.h>
  21#include <syscall.h>
  22#include <sys/syscall.h>
  23
  24/* Open-code this -- the headers are too messy to easily use them. */
  25struct real_sigaction {
  26        void *handler;
  27        unsigned long flags;
  28        void *restorer;
  29        unsigned int mask[2];
  30};
  31
  32static volatile sig_atomic_t handler_called;
  33
  34static void handler_with_siginfo(int sig, siginfo_t *info, void *ctx_void)
  35{
  36        handler_called = 1;
  37}
  38
  39static void handler_without_siginfo(int sig)
  40{
  41        handler_called = 1;
  42}
  43
  44int main()
  45{
  46        int nerrs = 0;
  47        struct real_sigaction sa;
  48
  49        memset(&sa, 0, sizeof(sa));
  50        sa.handler = handler_with_siginfo;
  51        sa.flags = SA_SIGINFO;
  52        sa.restorer = NULL;     /* request kernel-provided restorer */
  53
  54        if (syscall(SYS_rt_sigaction, SIGUSR1, &sa, NULL, 8) != 0)
  55                err(1, "raw rt_sigaction syscall");
  56
  57        raise(SIGUSR1);
  58
  59        if (handler_called) {
  60                printf("[OK]\tSA_SIGINFO handler returned successfully\n");
  61        } else {
  62                printf("[FAIL]\tSA_SIGINFO handler was not called\n");
  63                nerrs++;
  64        }
  65
  66        sa.flags = 0;
  67        sa.handler = handler_without_siginfo;
  68        if (syscall(SYS_sigaction, SIGUSR1, &sa, 0) != 0)
  69                err(1, "raw sigaction syscall");
  70        handler_called = 0;
  71
  72        raise(SIGUSR1);
  73
  74        if (handler_called) {
  75                printf("[OK]\t!SA_SIGINFO handler returned successfully\n");
  76        } else {
  77                printf("[FAIL]\t!SA_SIGINFO handler was not called\n");
  78                nerrs++;
  79        }
  80}
  81