aboutsummaryrefslogtreecommitdiffstats
path: root/linux-uml/linux-uml-2.6.7/proc_sysemu.patch
blob: 4f17341421c6b4659bf53064f237c530036e6332 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
Adds /proc/sysemu to toggle SYSEMU usage.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade_spam@yahoo.it>
---

 uml-linux-2.6.7-paolo/arch/um/kernel/process.c                  |    4 
 uml-linux-2.6.7-paolo/arch/um/kernel/skas/include/ptrace-skas.h |    4 
 uml-linux-2.6.7-paolo/arch/um/kernel/skas/process.c             |   62 ++++------
 uml-linux-2.6.7-paolo/arch/um/kernel/skas/process_kern.c        |   59 +++++++++
 4 files changed, 93 insertions(+), 36 deletions(-)

diff -puN arch/um/kernel/process.c~proc_sysemu arch/um/kernel/process.c
--- uml-linux-2.6.7/arch/um/kernel/process.c~proc_sysemu	2004-06-29 21:03:04.416965888 +0200
+++ uml-linux-2.6.7-paolo/arch/um/kernel/process.c	2004-06-29 21:03:04.422964976 +0200
@@ -246,7 +246,7 @@ void __init check_ptrace(void)
 	printk("OK\n");
 
 	printk("Checking syscall emulation patch for ptrace...");
-	use_sysemu = 0;
+	set_using_sysemu(0);
 	pid = start_ptraced_child(&stack);
 	if(ptrace(PTRACE_SYSEMU, pid, 0, 0) >= 0) {
 		struct user_regs_struct regs;
@@ -269,7 +269,7 @@ void __init check_ptrace(void)
 
 		if (!force_sysemu_disabled) {
 			printk("found\n");
-			use_sysemu = 1;
+			set_using_sysemu(1);
 		} else {
 			printk("found but disabled\n");
 		}
diff -puN arch/um/kernel/skas/include/ptrace-skas.h~proc_sysemu arch/um/kernel/skas/include/ptrace-skas.h
--- uml-linux-2.6.7/arch/um/kernel/skas/include/ptrace-skas.h~proc_sysemu	2004-06-29 21:03:04.417965736 +0200
+++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/include/ptrace-skas.h	2004-06-29 21:03:04.422964976 +0200
@@ -15,7 +15,9 @@
 #ifndef PTRACE_SYSEMU
 #define PTRACE_SYSEMU 31
 #endif
-extern int use_sysemu;
+
+void set_using_sysemu(int value);
+int get_using_sysemu(void);
 
 #include "skas_ptregs.h"
 
diff -puN arch/um/kernel/skas/process.c~proc_sysemu arch/um/kernel/skas/process.c
--- uml-linux-2.6.7/arch/um/kernel/skas/process.c~proc_sysemu	2004-06-29 21:03:04.418965584 +0200
+++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/process.c	2004-06-29 21:03:04.423964824 +0200
@@ -28,10 +28,6 @@
 #include "chan_user.h"
 #include "signal_user.h"
 
-#ifdef PTRACE_SYSEMU
-int use_sysemu = 0;
-#endif
-
 int is_skas_winch(int pid, int fd, void *data)
 {
 	if(pid != getpid())
@@ -61,7 +57,8 @@ static void handle_segv(int pid)
 	segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL);
 }
 
-static void handle_trap(int pid, union uml_pt_regs *regs)
+/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
+static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu)
 {
 	int err, syscall_nr, status;
 
@@ -72,27 +69,23 @@ static void handle_trap(int pid, union u
 		return;
 	}
 
-#ifdef PTRACE_SYSEMU
-	if (!use_sysemu)
+	if (!local_using_sysemu)
 	{
-#endif
-	err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
-	if(err < 0)
-	        panic("handle_trap - nullifying syscall failed errno = %d\n", 
-		      errno);
+		err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
+		if(err < 0)
+			panic("handle_trap - nullifying syscall failed errno = %d\n",
+			      errno);
+
+		err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
+		if(err < 0)
+			panic("handle_trap - continuing to end of syscall failed, "
+			      "errno = %d\n", errno);
 
-	err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
-	if(err < 0)
-	        panic("handle_trap - continuing to end of syscall failed, "
-		      "errno = %d\n", errno);
-
-	err = waitpid(pid, &status, WUNTRACED);
-	if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
-		panic("handle_trap - failed to wait at end of syscall, "
-		      "errno = %d, status = %d\n", errno, status);
-#ifdef PTRACE_SYSEMU
+		err = waitpid(pid, &status, WUNTRACED);
+		if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
+			panic("handle_trap - failed to wait at end of syscall, "
+			      "errno = %d, status = %d\n", errno, status);
 	}
-#endif
 
 	handle_syscall(regs);
 }
@@ -147,15 +140,16 @@ void start_userspace(int cpu)
 void userspace(union uml_pt_regs *regs)
 {
 	int err, status, op, pid = userspace_pid[0];
+	int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/
 
 	restore_registers(regs);
 		
-#ifdef PTRACE_SYSEMU
-	if (use_sysemu)
+	local_using_sysemu = get_using_sysemu();
+
+	if (local_using_sysemu)
 		err = ptrace(PTRACE_SYSEMU, pid, 0, 0);
 	else
-#endif
-	err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
+		err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
 	if(err)
 		panic("userspace - PTRACE_SYSCALL failed, errno = %d\n", 
 		       errno);
@@ -174,7 +168,7 @@ void userspace(union uml_pt_regs *regs)
 				handle_segv(pid);
 				break;
 			case SIGTRAP:
-			        handle_trap(pid, regs);
+			        handle_trap(pid, regs, local_using_sysemu);
 				break;
 			case SIGIO:
 			case SIGVTALRM:
@@ -193,14 +187,16 @@ void userspace(union uml_pt_regs *regs)
 
 		restore_registers(regs);
 
-#ifdef PTRACE_SYSEMU
-		if (use_sysemu)
+		/*Now we ended the syscall, so re-read local_using_sysemu.*/
+		local_using_sysemu = get_using_sysemu();
+
+		if (local_using_sysemu)
 			op = singlestepping_skas() ? PTRACE_SINGLESTEP :
 				PTRACE_SYSEMU;
 		else
-#endif
-		op = singlestepping_skas() ? PTRACE_SINGLESTEP : 
-			PTRACE_SYSCALL;
+			op = singlestepping_skas() ? PTRACE_SINGLESTEP :
+				PTRACE_SYSCALL;
+
 		err = ptrace(op, pid, 0, 0);
 		if(err)
 			panic("userspace - PTRACE_SYSCALL failed, "
diff -puN arch/um/kernel/skas/process_kern.c~proc_sysemu arch/um/kernel/skas/process_kern.c
--- uml-linux-2.6.7/arch/um/kernel/skas/process_kern.c~proc_sysemu	2004-06-29 21:03:04.419965432 +0200
+++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/process_kern.c	2004-06-29 21:03:04.423964824 +0200
@@ -6,6 +6,12 @@
 #include "linux/sched.h"
 #include "linux/slab.h"
 #include "linux/ptrace.h"
+#include "linux/proc_fs.h"
+#include "linux/file.h"
+#include "linux/errno.h"
+#include "linux/init.h"
+#include "asm/uaccess.h"
+#include "asm/atomic.h"
 #include "kern_util.h"
 #include "time_user.h"
 #include "signal_user.h"
@@ -17,6 +23,59 @@
 #include "kern.h"
 #include "mode.h"
 
+#ifdef PTRACE_SYSEMU
+static atomic_t using_sysemu;
+#endif
+
+void set_using_sysemu(int value)
+{
+	atomic_set(&using_sysemu, value);
+}
+
+int get_using_sysemu(void)
+{
+	return atomic_read(&using_sysemu);
+}
+
+int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
+{
+	if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
+		*eof = 1;
+
+	return strlen(buf);
+}
+
+int proc_write_sysemu(struct file *file,const char *buf, unsigned long count,void *data)
+{
+	char tmp[2];
+
+	if (copy_from_user(tmp, buf, 1))
+		return -EFAULT;
+
+	if (tmp[0] == '0' || tmp[0] == '1')
+		set_using_sysemu(tmp[0] - '0');
+	return count; /*We use the first char, but pretend to write everything*/
+}
+
+int __init make_proc_sysemu(void)
+{
+	struct proc_dir_entry *ent;
+
+	ent = create_proc_entry("sysemu", 00600, &proc_root);
+	ent->read_proc  = proc_read_sysemu;
+	ent->write_proc = proc_write_sysemu;
+
+	if (ent == NULL)
+	{
+		printk("Failed to register /proc/sysemu\n");
+		return(0);
+	}
+
+	return 0;
+}
+
+late_initcall(make_proc_sysemu);
+
 int singlestepping_skas(void)
 {
 	int ret = current->ptrace & PT_DTRACE;
_