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 <dlfcn.h>
  19#include <string.h>
  20#include <signal.h>
  21#include <unistd.h>
  22#include <syscall.h>
  23#include <sys/syscall.h>
  24
  25/* Open-code this -- the headers are too messy to easily use them. */
  26struct real_sigaction {
  27        void *handler;
  28        unsigned long flags;
  29        void *restorer;
  30        unsigned int mask[2];
  31};
  32
  33static volatile sig_atomic_t handler_called;
  34
  35static void handler_with_siginfo(int sig, siginfo_t *info, void *ctx_void)
  36{
  37        handler_called = 1;
  38}
  39
  40static void handler_without_siginfo(int sig)
  41{
  42        handler_called = 1;
  43}
  44
  45int main()
  46{
  47        int nerrs = 0;
  48        struct real_sigaction sa;
  49
  50        void *vdso = dlopen("linux-vdso.so.1",
  51                            RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
  52        if (!vdso)
  53                vdso = dlopen("linux-gate.so.1",
  54                              RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
  55        if (!vdso) {
  56                printf("[SKIP]\tFailed to find vDSO.  Tests are not expected to work.\n");
  57                return 0;
  58        }
  59
  60        memset(&sa, 0, sizeof(sa));
  61        sa.handler = handler_with_siginfo;
  62        sa.flags = SA_SIGINFO;
  63        sa.restorer = NULL;     /* request kernel-provided restorer */
  64
  65        printf("[RUN]\tRaise a signal, SA_SIGINFO, sa.restorer == NULL\n");
  66
  67        if (syscall(SYS_rt_sigaction, SIGUSR1, &sa, NULL, 8) != 0)
  68                err(1, "raw rt_sigaction syscall");
  69
  70        raise(SIGUSR1);
  71
  72        if (handler_called) {
  73                printf("[OK]\tSA_SIGINFO handler returned successfully\n");
  74        } else {
  75                printf("[FAIL]\tSA_SIGINFO handler was not called\n");
  76                nerrs++;
  77        }
  78
  79        printf("[RUN]\tRaise a signal, !SA_SIGINFO, sa.restorer == NULL\n");
  80
  81        sa.flags = 0;
  82        sa.handler = handler_without_siginfo;
  83        if (syscall(SYS_sigaction, SIGUSR1, &sa, 0) != 0)
  84                err(1, "raw sigaction syscall");
  85        handler_called = 0;
  86
  87        raise(SIGUSR1);
  88
  89        if (handler_called) {
  90                printf("[OK]\t!SA_SIGINFO handler returned successfully\n");
  91        } else {
  92                printf("[FAIL]\t!SA_SIGINFO handler was not called\n");
  93                nerrs++;
  94        }
  95}
  96