ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/Linux/paranoia.cpp
Revision: 1.5
Committed: 2005-07-04T06:09:59Z (19 years, 4 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +0 -0 lines
State: FILE REMOVED
Log Message:
New paranoia checks that better match was SheepShaver is doing with threads
and sigaltstack(). At least, this time we force use of threads and also
alter r1 to see whether the current threading model relies on it or not.

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * paranoia.cpp - Check undocumented features of the Linux kernel that
3     * SheepShaver relies upon
4     *
5 gbeauche 1.3 * SheepShaver (C) 1997-2005 Christian Bauer and Marc Hellwig
6 cebix 1.1 *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20     */
21    
22     #include <unistd.h>
23     #include <stdio.h>
24     #include <signal.h>
25     #include <errno.h>
26    
27     #include "sysdeps.h"
28     #include "main.h"
29     #include "user_strings.h"
30    
31     typedef struct {
32     uint32 u[4];
33     } __attribute((aligned(16))) vector128;
34     #include <linux/elf.h>
35    
36     #define DEBUG 1
37     #include "debug.h"
38    
39    
40     // Constants
41     const uint32 SIG_STACK_SIZE = 0x10000; // Size of signal stack
42    
43     // Prototypes
44     extern "C" void *get_sp(void);
45 gbeauche 1.4 extern "C" void *get_r2(void);
46     extern "C" void set_r2(void *);
47     extern "C" void *get_r13(void);
48 cebix 1.1 extern void paranoia_check(void);
49     static void sigusr2_handler(int sig, sigcontext_struct *sc);
50    
51     // Global variables
52     static void *sig_stack = NULL;
53    
54     static int err = 0;
55     static void *sig_sp = NULL;
56     static void *sig_r4 = NULL;
57     static int sig_sc_signal = 0;
58     static void *sig_sc_regs = NULL;
59     static uint32 sig_r2 = 0;
60    
61    
62 gbeauche 1.4 int raise(int sig)
63     {
64     // Reimplement to get rid of access to r2 (TLS pointer)
65     return kill(getpid(), sig);
66     }
67    
68 cebix 1.1 void paranoia_check(void)
69     {
70     char str[256];
71    
72     D(bug("Paranoia checks...\n"));
73    
74     // Create and install stack for signal handler
75     sig_stack = malloc(SIG_STACK_SIZE);
76     if (sig_stack == NULL) {
77     ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
78     exit(1);
79     }
80    
81     struct sigaltstack old_stack;
82     struct sigaltstack new_stack;
83     new_stack.ss_sp = sig_stack;
84     new_stack.ss_flags = 0;
85     new_stack.ss_size = SIG_STACK_SIZE;
86     if (sigaltstack(&new_stack, &old_stack) < 0) {
87     sprintf(str, GetString(STR_SIGALTSTACK_ERR), strerror(errno));
88     ErrorAlert(str);
89     exit(1);
90     }
91    
92     // Install SIGUSR2 signal handler
93     static struct sigaction old_action;
94     static struct sigaction sigusr2_action;
95     sigemptyset(&sigusr2_action.sa_mask);
96     sigusr2_action.sa_handler = (__sighandler_t)sigusr2_handler;
97     sigusr2_action.sa_flags = SA_ONSTACK | SA_RESTART;
98     sigusr2_action.sa_restorer = NULL;
99     if (sigaction(SIGUSR2, &sigusr2_action, &old_action) < 0) {
100     sprintf(str, GetString(STR_SIGUSR2_INSTALL_ERR), strerror(errno));
101     ErrorAlert(str);
102     exit(1);
103     }
104    
105     // Raise SIGUSR2
106 gbeauche 1.4 TOC = get_r2();
107     R13 = get_r13();
108     set_r2((void *)0xaffebad5);
109 cebix 1.1 raise(SIGUSR2);
110 gbeauche 1.4 if (TOC != get_r2())
111     err = 6;
112     if (R13 != get_r13())
113     err = 7;
114 cebix 1.1
115     // Check error code
116     switch (err) {
117     case 1:
118     printf("FATAL: sigaltstack() doesn't seem to work (sp in signal handler was %08lx, expected %08lx..%08lx)\n", (uint32)sig_sp, (uint32)sig_stack, (uint32)sig_stack + SIG_STACK_SIZE);
119     break;
120     case 2:
121     printf("FATAL: r4 in signal handler (%08lx) doesn't point to stack\n", (uint32)sig_r4);
122     break;
123     case 3:
124     printf("FATAL: r4 in signal handler doesn't seem to point to a sigcontext_struct (signal number was %d, expected %d)", sig_sc_signal, SIGUSR2);
125     break;
126     case 4:
127     printf("FATAL: sc->regs in signal handler (%08lx) doesn't point to stack\n", (uint32)sig_sc_regs);
128     break;
129     case 5:
130     printf("FATAL: sc->regs->gpr[2] in signal handler (%08lx) doesn't have expected value (%08x)\n", (uint32)sig_r2, 0xaffebad5);
131     break;
132 gbeauche 1.4 case 6:
133     printf("FATAL: signal handler failed to restore initial r2 value (%08x, was %08x)\n", (uint32)get_r2(), (uint32)TOC);
134     break;
135     case 7:
136     printf("FATAL: signal handler failed to restore initial r13 value (%08x, was %08x)\n", get_r13(), (uint32)R13);
137 cebix 1.1 }
138     if (err) {
139     printf("Maybe you need a different kernel?\n");
140     exit(1);
141     }
142    
143     // Clean up
144     D(bug("...passed\n"));
145     sigaction(SIGUSR2, &old_action, NULL);
146     sigaltstack(&old_stack, NULL);
147     free(sig_stack);
148     }
149    
150    
151     static void sigusr2_handler(int sig, sigcontext_struct *sc)
152     {
153     // Check whether sigaltstack works
154     sig_sp = get_sp();
155     if (sig_sp < sig_stack || sig_sp >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) {
156     err = 1;
157 gbeauche 1.4 goto ret;
158 cebix 1.1 }
159    
160     // Check whether r4 points to info on the stack
161     sig_r4 = sc;
162     if (sig_r4 < sig_stack || sig_r4 >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) {
163     err = 2;
164 gbeauche 1.4 goto ret;
165 cebix 1.1 }
166    
167     // Check whether r4 looks like a sigcontext
168     sig_sc_signal = sc->signal;
169     if (sig_sc_signal != SIGUSR2) {
170     err = 3;
171 gbeauche 1.4 goto ret;
172 cebix 1.1 }
173    
174     // Check whether sc->regs points to info on the stack
175     sig_sc_regs = sc->regs;
176     if (sig_sc_regs < sig_stack || sig_sc_regs >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) {
177     err = 4;
178 gbeauche 1.4 goto ret;
179 cebix 1.1 }
180    
181     // Check whether r2 still holds the value we set it to
182     sig_r2 = sc->regs->gpr[2];
183     if (sig_r2 != 0xaffebad5) {
184     err = 5;
185 gbeauche 1.4 goto ret;
186 cebix 1.1 }
187 gbeauche 1.4
188     // Restore pointer to Thread Local Storage
189     ret:
190     #ifdef SYSTEM_CLOBBERS_R2
191     sc->regs->gpr[2] = (unsigned long)TOC;
192     #endif
193 cebix 1.1 }