Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * vdso_restorer.c - tests vDSO-based signal restore
0004  * Copyright (c) 2015 Andrew Lutomirski
0005  *
0006  * This makes sure that sa_restorer == NULL keeps working on 32-bit
0007  * configurations.  Modern glibc doesn't use it under any circumstances,
0008  * so it's easy to overlook breakage.
0009  *
0010  * 64-bit userspace has never supported sa_restorer == NULL, so this is
0011  * 32-bit only.
0012  */
0013 
0014 #define _GNU_SOURCE
0015 
0016 #include <err.h>
0017 #include <stdio.h>
0018 #include <dlfcn.h>
0019 #include <string.h>
0020 #include <signal.h>
0021 #include <unistd.h>
0022 #include <syscall.h>
0023 #include <sys/syscall.h>
0024 
0025 /* Open-code this -- the headers are too messy to easily use them. */
0026 struct real_sigaction {
0027     void *handler;
0028     unsigned long flags;
0029     void *restorer;
0030     unsigned int mask[2];
0031 };
0032 
0033 static volatile sig_atomic_t handler_called;
0034 
0035 static void handler_with_siginfo(int sig, siginfo_t *info, void *ctx_void)
0036 {
0037     handler_called = 1;
0038 }
0039 
0040 static void handler_without_siginfo(int sig)
0041 {
0042     handler_called = 1;
0043 }
0044 
0045 int main()
0046 {
0047     int nerrs = 0;
0048     struct real_sigaction sa;
0049 
0050     void *vdso = dlopen("linux-vdso.so.1",
0051                 RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
0052     if (!vdso)
0053         vdso = dlopen("linux-gate.so.1",
0054                   RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
0055     if (!vdso) {
0056         printf("[SKIP]\tFailed to find vDSO.  Tests are not expected to work.\n");
0057         return 0;
0058     }
0059 
0060     memset(&sa, 0, sizeof(sa));
0061     sa.handler = handler_with_siginfo;
0062     sa.flags = SA_SIGINFO;
0063     sa.restorer = NULL; /* request kernel-provided restorer */
0064 
0065     printf("[RUN]\tRaise a signal, SA_SIGINFO, sa.restorer == NULL\n");
0066 
0067     if (syscall(SYS_rt_sigaction, SIGUSR1, &sa, NULL, 8) != 0)
0068         err(1, "raw rt_sigaction syscall");
0069 
0070     raise(SIGUSR1);
0071 
0072     if (handler_called) {
0073         printf("[OK]\tSA_SIGINFO handler returned successfully\n");
0074     } else {
0075         printf("[FAIL]\tSA_SIGINFO handler was not called\n");
0076         nerrs++;
0077     }
0078 
0079     printf("[RUN]\tRaise a signal, !SA_SIGINFO, sa.restorer == NULL\n");
0080 
0081     sa.flags = 0;
0082     sa.handler = handler_without_siginfo;
0083     if (syscall(SYS_sigaction, SIGUSR1, &sa, 0) != 0)
0084         err(1, "raw sigaction syscall");
0085     handler_called = 0;
0086 
0087     raise(SIGUSR1);
0088 
0089     if (handler_called) {
0090         printf("[OK]\t!SA_SIGINFO handler returned successfully\n");
0091     } else {
0092         printf("[FAIL]\t!SA_SIGINFO handler was not called\n");
0093         nerrs++;
0094     }
0095 }