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, 5 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

# Content
1 /*
2 * paranoia.cpp - Check undocumented features of the Linux kernel that
3 * SheepShaver relies upon
4 *
5 * SheepShaver (C) 1997-2005 Christian Bauer and Marc Hellwig
6 *
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 extern "C" void *get_r2(void);
46 extern "C" void set_r2(void *);
47 extern "C" void *get_r13(void);
48 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 int raise(int sig)
63 {
64 // Reimplement to get rid of access to r2 (TLS pointer)
65 return kill(getpid(), sig);
66 }
67
68 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 TOC = get_r2();
107 R13 = get_r13();
108 set_r2((void *)0xaffebad5);
109 raise(SIGUSR2);
110 if (TOC != get_r2())
111 err = 6;
112 if (R13 != get_r13())
113 err = 7;
114
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 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 }
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 goto ret;
158 }
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 goto ret;
165 }
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 goto ret;
172 }
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 goto ret;
179 }
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 goto ret;
186 }
187
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 }