Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright 2015, Michael Neuling, IBM Corp.
0004  *
0005  * Test the kernel's signal delievery code to ensure that we don't
0006  * trelaim twice in the kernel signal delivery code.  This can happen
0007  * if we trigger a signal when in a transaction and the stack pointer
0008  * is bogus.
0009  *
0010  * This test case registers a SEGV handler, sets the stack pointer
0011  * (r1) to NULL, starts a transaction and then generates a SEGV.  The
0012  * SEGV should be handled but we exit here as the stack pointer is
0013  * invalid and hance we can't sigreturn.  We only need to check that
0014  * this flow doesn't crash the kernel.
0015  */
0016 
0017 #include <unistd.h>
0018 #include <sys/types.h>
0019 #include <sys/wait.h>
0020 #include <stdlib.h>
0021 #include <stdio.h>
0022 #include <signal.h>
0023 
0024 #include "utils.h"
0025 #include "tm.h"
0026 
0027 void signal_segv(int signum)
0028 {
0029     /* This should never actually run since stack is foobar */
0030     exit(1);
0031 }
0032 
0033 int tm_signal_stack()
0034 {
0035     int pid;
0036 
0037     SKIP_IF(!have_htm());
0038     SKIP_IF(htm_is_synthetic());
0039 
0040     pid = fork();
0041     if (pid < 0)
0042         exit(1);
0043 
0044     if (pid) { /* Parent */
0045         /*
0046          * It's likely the whole machine will crash here so if
0047          * the child ever exits, we are good.
0048          */
0049         wait(NULL);
0050         return 0;
0051     }
0052 
0053     /*
0054      * The flow here is:
0055      * 1) register a signal handler (so signal delievery occurs)
0056      * 2) make stack pointer (r1) = NULL
0057      * 3) start transaction
0058      * 4) cause segv
0059      */
0060     if (signal(SIGSEGV, signal_segv) == SIG_ERR)
0061         exit(1);
0062     asm volatile("li 1, 0 ;"        /* stack ptr == NULL */
0063              "1:"
0064              "tbegin.;"
0065              "beq 1b ;"         /* retry forever */
0066              "tsuspend.;"
0067              "ld 2, 0(1) ;"     /* trigger segv" */
0068              : : : "memory");
0069 
0070     /* This should never get here due to above segv */
0071     return 1;
0072 }
0073 
0074 int main(void)
0075 {
0076     return test_harness(tm_signal_stack, "tm_signal_stack");
0077 }