]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.arch/x86-tracehook
Imported linux-2.6.27.39 suse/xen patches.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.arch / x86-tracehook
CommitLineData
2cb7cef9
BS
1From: Roland McGrath <roland@redhat.com>
2Date: Sun Apr 20 14:35:12 2008 -0700
3Subject: x86 tracehook
4References: FATE#304321
5Patch-mainline: no
6
7Apply the changes from x86-utrace branch of
8git://git.kernel.org/pub/scm/linux/kernel/git/frob/linux-2.6-utrace
9plus later cleanups.
10
11Signed-off-by: Roland McGrath <roland@redhat.com>
12Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
13
14---
15 arch/x86/Kconfig | 1
16 arch/x86/kernel/ptrace.c | 34 +-----
17 arch/x86/kernel/signal_32.c | 11 +-
18 arch/x86/kernel/signal_64.c | 49 ++-------
19 include/asm-x86/ptrace.h | 5
20 include/asm-x86/syscall.h | 213 ++++++++++++++++++++++++++++++++++++++++++
21 include/asm-x86/thread_info.h | 4
22 7 files changed, 251 insertions(+), 66 deletions(-)
23
24--- linux-2.6.27.orig/arch/x86/Kconfig 2008-10-20 11:46:16.000000000 +0200
25+++ linux-2.6.27/arch/x86/Kconfig 2008-10-20 17:24:26.000000000 +0200
26@@ -29,6 +29,7 @@ config X86
27 select HAVE_FTRACE
28 select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64)
29 select HAVE_ARCH_KGDB if !X86_VOYAGER
30+ select HAVE_ARCH_TRACEHOOK
31 select HAVE_GENERIC_DMA_COHERENT if X86_32
32 select HAVE_EFFICIENT_UNALIGNED_ACCESS
33
34--- linux-2.6.27.orig/arch/x86/kernel/ptrace.c 2008-10-20 11:46:16.000000000 +0200
35+++ linux-2.6.27/arch/x86/kernel/ptrace.c 2008-10-20 11:46:16.000000000 +0200
36@@ -14,6 +14,7 @@
37 #include <linux/errno.h>
38 #include <linux/ptrace.h>
39 #include <linux/regset.h>
40+#include <linux/tracehook.h>
41 #include <linux/user.h>
42 #include <linux/elf.h>
43 #include <linux/security.h>
44@@ -1375,30 +1376,6 @@ void send_sigtrap(struct task_struct *ts
45 force_sig_info(SIGTRAP, &info, tsk);
46 }
47
48-static void syscall_trace(struct pt_regs *regs)
49-{
50- if (!(current->ptrace & PT_PTRACED))
51- return;
52-
53-#if 0
54- printk("trace %s ip %lx sp %lx ax %d origrax %d caller %lx tiflags %x ptrace %x\n",
55- current->comm,
56- regs->ip, regs->sp, regs->ax, regs->orig_ax, __builtin_return_address(0),
57- current_thread_info()->flags, current->ptrace);
58-#endif
59-
60- ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
61- ? 0x80 : 0));
62- /*
63- * this isn't the same as continuing with a signal, but it will do
64- * for normal use. strace only continues with a signal if the
65- * stopping signal is not SIGTRAP. -brl
66- */
67- if (current->exit_code) {
68- send_sig(current->exit_code, current, 1);
69- current->exit_code = 0;
70- }
71-}
72
73 #ifdef CONFIG_X86_32
74 # define IS_IA32 1
75@@ -1443,8 +1420,9 @@ asmregparm long syscall_trace_enter(stru
76 if (unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
77 ret = -1L;
78
79- if (ret || test_thread_flag(TIF_SYSCALL_TRACE))
80- syscall_trace(regs);
81+ if ((ret || test_thread_flag(TIF_SYSCALL_TRACE)) &&
82+ tracehook_report_syscall_entry(regs))
83+ ret = -1L;
84
85 if (unlikely(current->audit_context)) {
86 if (IS_IA32)
87@@ -1473,7 +1451,7 @@ asmregparm void syscall_trace_leave(stru
88 audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax);
89
90 if (test_thread_flag(TIF_SYSCALL_TRACE))
91- syscall_trace(regs);
92+ tracehook_report_syscall_exit(regs, 0);
93
94 /*
95 * If TIF_SYSCALL_EMU is set, we only get here because of
96@@ -1489,6 +1467,6 @@ asmregparm void syscall_trace_leave(stru
97 * system call instruction.
98 */
99 if (test_thread_flag(TIF_SINGLESTEP) &&
100- (current->ptrace & PT_PTRACED))
101+ tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL))
102 send_sigtrap(current, regs, 0);
103 }
104--- linux-2.6.27.orig/arch/x86/kernel/signal_32.c 2008-10-20 11:46:16.000000000 +0200
105+++ linux-2.6.27/arch/x86/kernel/signal_32.c 2008-10-20 11:46:16.000000000 +0200
106@@ -17,6 +17,7 @@
107 #include <linux/errno.h>
108 #include <linux/sched.h>
109 #include <linux/wait.h>
110+#include <linux/tracehook.h>
111 #include <linux/elf.h>
112 #include <linux/smp.h>
113 #include <linux/mm.h>
114@@ -558,8 +559,6 @@ handle_signal(unsigned long sig, siginfo
115 * handler too.
116 */
117 regs->flags &= ~X86_EFLAGS_TF;
118- if (test_thread_flag(TIF_SINGLESTEP))
119- ptrace_notify(SIGTRAP);
120
121 spin_lock_irq(&current->sighand->siglock);
122 sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
123@@ -573,6 +572,9 @@ handle_signal(unsigned long sig, siginfo
124 current->instrumentation &= ~PTS_SELF;
125 }
126
127+ tracehook_signal_handler(sig, info, ka, regs,
128+ test_thread_flag(TIF_SINGLESTEP));
129+
130 return 0;
131 }
132
133@@ -666,5 +668,10 @@ do_notify_resume(struct pt_regs *regs, v
134 if (thread_info_flags & _TIF_SIGPENDING)
135 do_signal(regs);
136
137+ if (thread_info_flags & _TIF_NOTIFY_RESUME) {
138+ clear_thread_flag(TIF_NOTIFY_RESUME);
139+ tracehook_notify_resume(regs);
140+ }
141+
142 clear_thread_flag(TIF_IRET);
143 }
144--- linux-2.6.27.orig/arch/x86/kernel/signal_64.c 2008-10-20 11:46:16.000000000 +0200
145+++ linux-2.6.27/arch/x86/kernel/signal_64.c 2008-10-20 11:46:16.000000000 +0200
146@@ -15,6 +15,7 @@
147 #include <linux/errno.h>
148 #include <linux/wait.h>
149 #include <linux/ptrace.h>
150+#include <linux/tracehook.h>
151 #include <linux/unistd.h>
152 #include <linux/stddef.h>
153 #include <linux/personality.h>
154@@ -26,6 +27,7 @@
155 #include <asm/proto.h>
156 #include <asm/ia32_unistd.h>
157 #include <asm/mce.h>
158+#include <asm/syscall.h>
159 #include "sigframe.h"
160
161 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
162@@ -355,35 +357,6 @@ give_sigsegv:
163 }
164
165 /*
166- * Return -1L or the syscall number that @regs is executing.
167- */
168-static long current_syscall(struct pt_regs *regs)
169-{
170- /*
171- * We always sign-extend a -1 value being set here,
172- * so this is always either -1L or a syscall number.
173- */
174- return regs->orig_ax;
175-}
176-
177-/*
178- * Return a value that is -EFOO if the system call in @regs->orig_ax
179- * returned an error. This only works for @regs from @current.
180- */
181-static long current_syscall_ret(struct pt_regs *regs)
182-{
183-#ifdef CONFIG_IA32_EMULATION
184- if (test_thread_flag(TIF_IA32))
185- /*
186- * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
187- * and will match correctly in comparisons.
188- */
189- return (int) regs->ax;
190-#endif
191- return regs->ax;
192-}
193-
194-/*
195 * OK, we're invoking a handler
196 */
197
198@@ -394,9 +367,9 @@ handle_signal(unsigned long sig, siginfo
199 int ret;
200
201 /* Are we from a system call? */
202- if (current_syscall(regs) >= 0) {
203+ if (syscall_get_nr(current, regs) >= 0) {
204 /* If so, check system call restarting.. */
205- switch (current_syscall_ret(regs)) {
206+ switch (syscall_get_error(current, regs)) {
207 case -ERESTART_RESTARTBLOCK:
208 case -ERESTARTNOHAND:
209 regs->ax = -EINTR;
210@@ -453,8 +426,6 @@ handle_signal(unsigned long sig, siginfo
211 * handler too.
212 */
213 regs->flags &= ~X86_EFLAGS_TF;
214- if (test_thread_flag(TIF_SINGLESTEP))
215- ptrace_notify(SIGTRAP);
216
217 spin_lock_irq(&current->sighand->siglock);
218 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
219@@ -462,6 +433,9 @@ handle_signal(unsigned long sig, siginfo
220 sigaddset(&current->blocked,sig);
221 recalc_sigpending();
222 spin_unlock_irq(&current->sighand->siglock);
223+
224+ tracehook_signal_handler(sig, info, ka, regs,
225+ test_thread_flag(TIF_SINGLESTEP));
226 }
227
228 if (current->instrumentation & PTS_SELF) {
229@@ -523,9 +497,9 @@ static void do_signal(struct pt_regs *re
230 }
231
232 /* Did we come from a system call? */
233- if (current_syscall(regs) >= 0) {
234+ if (syscall_get_nr(current, regs) >= 0) {
235 /* Restart the system call - no handlers present */
236- switch (current_syscall_ret(regs)) {
237+ switch (syscall_get_error(current, regs)) {
238 case -ERESTARTNOHAND:
239 case -ERESTARTSYS:
240 case -ERESTARTNOINTR:
241@@ -563,6 +537,11 @@ void do_notify_resume(struct pt_regs *re
242 /* deal with pending signal delivery */
243 if (thread_info_flags & _TIF_SIGPENDING)
244 do_signal(regs);
245+
246+ if (thread_info_flags & _TIF_NOTIFY_RESUME) {
247+ clear_thread_flag(TIF_NOTIFY_RESUME);
248+ tracehook_notify_resume(regs);
249+ }
250 }
251
252 void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
253--- linux-2.6.27.orig/include/asm-x86/ptrace.h 2008-10-10 00:13:53.000000000 +0200
254+++ linux-2.6.27/include/asm-x86/ptrace.h 2008-10-20 17:23:29.000000000 +0200
255@@ -213,6 +213,11 @@ static inline unsigned long frame_pointe
256 return regs->bp;
257 }
258
259+static inline unsigned long user_stack_pointer(struct pt_regs *regs)
260+{
261+ return regs->sp;
262+}
263+
264 /*
265 * These are defined as per linux/ptrace.h, which see.
266 */
267--- /dev/null 1970-01-01 00:00:00.000000000 +0000
268+++ linux-2.6.27/include/asm-x86/syscall.h 2008-10-20 17:32:17.000000000 +0200
269@@ -0,0 +1,213 @@
270+/*
271+ * Access to user system call parameters and results
272+ *
273+ * Copyright (C) 2008 Red Hat, Inc. All rights reserved.
274+ *
275+ * This copyrighted material is made available to anyone wishing to use,
276+ * modify, copy, or redistribute it subject to the terms and conditions
277+ * of the GNU General Public License v.2.
278+ *
279+ * See asm-generic/syscall.h for descriptions of what we must do here.
280+ */
281+
282+#ifndef _ASM_SYSCALL_H
283+#define _ASM_SYSCALL_H 1
284+
285+#include <linux/sched.h>
286+#include <linux/err.h>
287+
288+static inline long syscall_get_nr(struct task_struct *task,
289+ struct pt_regs *regs)
290+{
291+ /*
292+ * We always sign-extend a -1 value being set here,
293+ * so this is always either -1L or a syscall number.
294+ */
295+ return regs->orig_ax;
296+}
297+
298+static inline void syscall_rollback(struct task_struct *task,
299+ struct pt_regs *regs)
300+{
301+ regs->ax = regs->orig_ax;
302+}
303+
304+static inline long syscall_get_error(struct task_struct *task,
305+ struct pt_regs *regs)
306+{
307+ unsigned long error = regs->ax;
308+#ifdef CONFIG_IA32_EMULATION
309+ /*
310+ * TS_COMPAT is set for 32-bit syscall entries and then
311+ * remains set until we return to user mode.
312+ */
313+ if (task_thread_info(task)->status & TS_COMPAT)
314+ /*
315+ * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
316+ * and will match correctly in comparisons.
317+ */
318+ error = (long) (int) error;
319+#endif
320+ return IS_ERR_VALUE(error) ? error : 0;
321+}
322+
323+static inline long syscall_get_return_value(struct task_struct *task,
324+ struct pt_regs *regs)
325+{
326+ return regs->ax;
327+}
328+
329+static inline void syscall_set_return_value(struct task_struct *task,
330+ struct pt_regs *regs,
331+ int error, long val)
332+{
333+ regs->ax = (long) error ?: val;
334+}
335+
336+#ifdef CONFIG_X86_32
337+
338+static inline void syscall_get_arguments(struct task_struct *task,
339+ struct pt_regs *regs,
340+ unsigned int i, unsigned int n,
341+ unsigned long *args)
342+{
343+ BUG_ON(i + n > 6);
344+ memcpy(args, &regs->bx + i, n * sizeof(args[0]));
345+}
346+
347+static inline void syscall_set_arguments(struct task_struct *task,
348+ struct pt_regs *regs,
349+ unsigned int i, unsigned int n,
350+ const unsigned long *args)
351+{
352+ BUG_ON(i + n > 6);
353+ memcpy(&regs->bx + i, args, n * sizeof(args[0]));
354+}
355+
356+#else /* CONFIG_X86_64 */
357+
358+static inline void syscall_get_arguments(struct task_struct *task,
359+ struct pt_regs *regs,
360+ unsigned int i, unsigned int n,
361+ unsigned long *args)
362+{
363+# ifdef CONFIG_IA32_EMULATION
364+ if (task_thread_info(task)->status & TS_COMPAT)
365+ switch (i) {
366+ case 0:
367+ if (!n--) break;
368+ *args++ = regs->bx;
369+ case 1:
370+ if (!n--) break;
371+ *args++ = regs->cx;
372+ case 2:
373+ if (!n--) break;
374+ *args++ = regs->dx;
375+ case 3:
376+ if (!n--) break;
377+ *args++ = regs->si;
378+ case 4:
379+ if (!n--) break;
380+ *args++ = regs->di;
381+ case 5:
382+ if (!n--) break;
383+ *args++ = regs->bp;
384+ case 6:
385+ if (!n--) break;
386+ default:
387+ BUG();
388+ break;
389+ }
390+ else
391+# endif
392+ switch (i) {
393+ case 0:
394+ if (!n--) break;
395+ *args++ = regs->di;
396+ case 1:
397+ if (!n--) break;
398+ *args++ = regs->si;
399+ case 2:
400+ if (!n--) break;
401+ *args++ = regs->dx;
402+ case 3:
403+ if (!n--) break;
404+ *args++ = regs->r10;
405+ case 4:
406+ if (!n--) break;
407+ *args++ = regs->r8;
408+ case 5:
409+ if (!n--) break;
410+ *args++ = regs->r9;
411+ case 6:
412+ if (!n--) break;
413+ default:
414+ BUG();
415+ break;
416+ }
417+}
418+
419+static inline void syscall_set_arguments(struct task_struct *task,
420+ struct pt_regs *regs,
421+ unsigned int i, unsigned int n,
422+ const unsigned long *args)
423+{
424+# ifdef CONFIG_IA32_EMULATION
425+ if (task_thread_info(task)->status & TS_COMPAT)
426+ switch (i) {
427+ case 0:
428+ if (!n--) break;
429+ regs->bx = *args++;
430+ case 1:
431+ if (!n--) break;
432+ regs->cx = *args++;
433+ case 2:
434+ if (!n--) break;
435+ regs->dx = *args++;
436+ case 3:
437+ if (!n--) break;
438+ regs->si = *args++;
439+ case 4:
440+ if (!n--) break;
441+ regs->di = *args++;
442+ case 5:
443+ if (!n--) break;
444+ regs->bp = *args++;
445+ case 6:
446+ if (!n--) break;
447+ default:
448+ BUG();
449+ break;
450+ }
451+ else
452+# endif
453+ switch (i) {
454+ case 0:
455+ if (!n--) break;
456+ regs->di = *args++;
457+ case 1:
458+ if (!n--) break;
459+ regs->si = *args++;
460+ case 2:
461+ if (!n--) break;
462+ regs->dx = *args++;
463+ case 3:
464+ if (!n--) break;
465+ regs->r10 = *args++;
466+ case 4:
467+ if (!n--) break;
468+ regs->r8 = *args++;
469+ case 5:
470+ if (!n--) break;
471+ regs->r9 = *args++;
472+ case 6:
473+ if (!n--) break;
474+ default:
475+ BUG();
476+ break;
477+ }
478+}
479+
480+#endif /* CONFIG_X86_32 */
481+
482+#endif /* _ASM_SYSCALL_H */
483--- linux-2.6.27.orig/include/asm-x86/thread_info.h 2008-10-10 00:13:53.000000000 +0200
484+++ linux-2.6.27/include/asm-x86/thread_info.h 2008-10-20 17:23:10.000000000 +0200
485@@ -71,6 +71,7 @@ struct thread_info {
486 * Warning: layout of LSW is hardcoded in entry.S
487 */
488 #define TIF_SYSCALL_TRACE 0 /* syscall trace active */
489+#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
490 #define TIF_SIGPENDING 2 /* signal pending */
491 #define TIF_NEED_RESCHED 3 /* rescheduling necessary */
492 #define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/
493@@ -93,6 +94,7 @@ struct thread_info {
494 #define TIF_BTS_TRACE_TS 27 /* record scheduling event timestamps */
495
496 #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
497+#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
498 #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
499 #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
500 #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
501@@ -133,7 +135,7 @@ struct thread_info {
502
503 /* Only used for 64 bit */
504 #define _TIF_DO_NOTIFY_MASK \
505- (_TIF_SIGPENDING|_TIF_MCE_NOTIFY)
506+ (_TIF_SIGPENDING|_TIF_MCE_NOTIFY|_TIF_NOTIFY_RESUME)
507
508 /* flags to check in __switch_to() */
509 #define _TIF_WORK_CTXSW \