Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Test that a syscall does not get restarted twice, handled by trap_norestart()
0004  *
0005  * Based on Al's description, and a test for the bug fixed in this commit:
0006  *
0007  * commit 9a81c16b527528ad307843be5571111aa8d35a80
0008  * Author: Al Viro <viro@zeniv.linux.org.uk>
0009  * Date:   Mon Sep 20 21:48:57 2010 +0100
0010  *
0011  *  powerpc: fix double syscall restarts
0012  *
0013  *  Make sigreturn zero regs->trap, make do_signal() do the same on all
0014  *  paths.  As it is, signal interrupting e.g. read() from fd 512 (==
0015  *  ERESTARTSYS) with another signal getting unblocked when the first
0016  *  handler finishes will lead to restart one insn earlier than it ought
0017  *  to.  Same for multiple signals with in-kernel handlers interrupting
0018  *  that sucker at the same time.  Same for multiple signals of any kind
0019  *  interrupting that sucker on 64bit...
0020  */
0021 #define _GNU_SOURCE
0022 #include <sys/types.h>
0023 #include <sys/wait.h>
0024 #include <sys/syscall.h>
0025 #include <unistd.h>
0026 #include <signal.h>
0027 #include <errno.h>
0028 #include <stdlib.h>
0029 #include <stdio.h>
0030 #include <string.h>
0031 
0032 #include "utils.h"
0033 
0034 static void SIGUSR1_handler(int sig)
0035 {
0036     kill(getpid(), SIGUSR2);
0037     /*
0038      * SIGUSR2 is blocked until the handler exits, at which point it will
0039      * be raised again and think there is a restart to be done because the
0040      * pending restarted syscall has 512 (ERESTARTSYS) in r3. The second
0041      * restart will retreat NIP another 4 bytes to fail case branch.
0042      */
0043 }
0044 
0045 static void SIGUSR2_handler(int sig)
0046 {
0047 }
0048 
0049 static ssize_t raw_read(int fd, void *buf, size_t count)
0050 {
0051     register long nr asm("r0") = __NR_read;
0052     register long _fd asm("r3") = fd;
0053     register void *_buf asm("r4") = buf;
0054     register size_t _count asm("r5") = count;
0055 
0056     asm volatile(
0057 "       b   0f      \n"
0058 "       b   1f      \n"
0059 "   0:  sc  0       \n"
0060 "       bns 2f      \n"
0061 "       neg %0,%0       \n"
0062 "       b   2f      \n"
0063 "   1:              \n"
0064 "       li  %0,%4       \n"
0065 "   2:              \n"
0066         : "+r"(_fd), "+r"(nr), "+r"(_buf), "+r"(_count)
0067         : "i"(-ENOANO)
0068         : "memory", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "ctr", "cr0");
0069 
0070     if (_fd < 0) {
0071         errno = -_fd;
0072         _fd = -1;
0073     }
0074 
0075     return _fd;
0076 }
0077 
0078 #define DATA "test 123"
0079 #define DLEN (strlen(DATA)+1)
0080 
0081 int test_restart(void)
0082 {
0083     int pipefd[2];
0084     pid_t pid;
0085     char buf[512];
0086 
0087     if (pipe(pipefd) == -1) {
0088         perror("pipe");
0089         exit(EXIT_FAILURE);
0090     }
0091 
0092     pid = fork();
0093     if (pid == -1) {
0094         perror("fork");
0095         exit(EXIT_FAILURE);
0096     }
0097 
0098     if (pid == 0) { /* Child reads from pipe */
0099         struct sigaction act;
0100         int fd;
0101 
0102         memset(&act, 0, sizeof(act));
0103         sigaddset(&act.sa_mask, SIGUSR2);
0104         act.sa_handler = SIGUSR1_handler;
0105         act.sa_flags = SA_RESTART;
0106         if (sigaction(SIGUSR1, &act, NULL) == -1) {
0107             perror("sigaction");
0108             exit(EXIT_FAILURE);
0109         }
0110 
0111         memset(&act, 0, sizeof(act));
0112         act.sa_handler = SIGUSR2_handler;
0113         act.sa_flags = SA_RESTART;
0114         if (sigaction(SIGUSR2, &act, NULL) == -1) {
0115             perror("sigaction");
0116             exit(EXIT_FAILURE);
0117         }
0118 
0119         /* Let's get ERESTARTSYS into r3 */
0120         while ((fd = dup(pipefd[0])) != 512) {
0121             if (fd == -1) {
0122                 perror("dup");
0123                 exit(EXIT_FAILURE);
0124             }
0125         }
0126 
0127         if (raw_read(fd, buf, 512) == -1) {
0128             if (errno == ENOANO) {
0129                 fprintf(stderr, "Double restart moved restart before sc instruction.\n");
0130                 _exit(EXIT_FAILURE);
0131             }
0132             perror("read");
0133             exit(EXIT_FAILURE);
0134         }
0135 
0136         if (strncmp(buf, DATA, DLEN)) {
0137             fprintf(stderr, "bad test string %s\n", buf);
0138             exit(EXIT_FAILURE);
0139         }
0140 
0141         return 0;
0142 
0143     } else {
0144         int wstatus;
0145 
0146         usleep(100000);     /* Hack to get reader waiting */
0147         kill(pid, SIGUSR1);
0148         usleep(100000);
0149         if (write(pipefd[1], DATA, DLEN) != DLEN) {
0150             perror("write");
0151             exit(EXIT_FAILURE);
0152         }
0153         close(pipefd[0]);
0154         close(pipefd[1]);
0155         if (wait(&wstatus) == -1) {
0156             perror("wait");
0157             exit(EXIT_FAILURE);
0158         }
0159         if (!WIFEXITED(wstatus)) {
0160             fprintf(stderr, "child exited abnormally\n");
0161             exit(EXIT_FAILURE);
0162         }
0163 
0164         FAIL_IF(WEXITSTATUS(wstatus) != EXIT_SUCCESS);
0165 
0166         return 0;
0167     }
0168 }
0169 
0170 int main(void)
0171 {
0172     test_harness_set_timeout(10);
0173     return test_harness(test_restart, "sig sys restart");
0174 }