1 From: Roland McGrath <roland@redhat.com>
2 Date: Sun Apr 20 14:35:12 2008 -0700
4 References: FATE#304321
7 Apply the changes from x86-utrace branch of
8 git://git.kernel.org/pub/scm/linux/kernel/git/frob/linux-2.6-utrace
11 Signed-off-by: Roland McGrath <roland@redhat.com>
12 Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
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(-)
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
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
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
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);
48 -static void syscall_trace(struct pt_regs *regs)
50 - if (!(current->ptrace & PT_PTRACED))
54 - printk("trace %s ip %lx sp %lx ax %d origrax %d caller %lx tiflags %x ptrace %x\n",
56 - regs->ip, regs->sp, regs->ax, regs->orig_ax, __builtin_return_address(0),
57 - current_thread_info()->flags, current->ptrace);
60 - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
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
67 - if (current->exit_code) {
68 - send_sig(current->exit_code, current, 1);
69 - current->exit_code = 0;
75 @@ -1443,8 +1420,9 @@ asmregparm long syscall_trace_enter(stru
76 if (unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
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))
85 if (unlikely(current->audit_context)) {
87 @@ -1473,7 +1451,7 @@ asmregparm void syscall_trace_leave(stru
88 audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax);
90 if (test_thread_flag(TIF_SYSCALL_TRACE))
91 - syscall_trace(regs);
92 + tracehook_report_syscall_exit(regs, 0);
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.
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);
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
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
117 regs->flags &= ~X86_EFLAGS_TF;
118 - if (test_thread_flag(TIF_SINGLESTEP))
119 - ptrace_notify(SIGTRAP);
121 spin_lock_irq(¤t->sighand->siglock);
122 sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
123 @@ -573,6 +572,9 @@ handle_signal(unsigned long sig, siginfo
124 current->instrumentation &= ~PTS_SELF;
127 + tracehook_signal_handler(sig, info, ka, regs,
128 + test_thread_flag(TIF_SINGLESTEP));
133 @@ -666,5 +668,10 @@ do_notify_resume(struct pt_regs *regs, v
134 if (thread_info_flags & _TIF_SIGPENDING)
137 + if (thread_info_flags & _TIF_NOTIFY_RESUME) {
138 + clear_thread_flag(TIF_NOTIFY_RESUME);
139 + tracehook_notify_resume(regs);
142 clear_thread_flag(TIF_IRET);
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
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>
155 #include <asm/proto.h>
156 #include <asm/ia32_unistd.h>
158 +#include <asm/syscall.h>
159 #include "sigframe.h"
161 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
162 @@ -355,35 +357,6 @@ give_sigsegv:
166 - * Return -1L or the syscall number that @regs is executing.
168 -static long current_syscall(struct pt_regs *regs)
171 - * We always sign-extend a -1 value being set here,
172 - * so this is always either -1L or a syscall number.
174 - return regs->orig_ax;
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.
181 -static long current_syscall_ret(struct pt_regs *regs)
183 -#ifdef CONFIG_IA32_EMULATION
184 - if (test_thread_flag(TIF_IA32))
186 - * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
187 - * and will match correctly in comparisons.
189 - return (int) regs->ax;
195 * OK, we're invoking a handler
198 @@ -394,9 +367,9 @@ handle_signal(unsigned long sig, siginfo
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:
210 @@ -453,8 +426,6 @@ handle_signal(unsigned long sig, siginfo
213 regs->flags &= ~X86_EFLAGS_TF;
214 - if (test_thread_flag(TIF_SINGLESTEP))
215 - ptrace_notify(SIGTRAP);
217 spin_lock_irq(¤t->sighand->siglock);
218 sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
219 @@ -462,6 +433,9 @@ handle_signal(unsigned long sig, siginfo
220 sigaddset(¤t->blocked,sig);
222 spin_unlock_irq(¤t->sighand->siglock);
224 + tracehook_signal_handler(sig, info, ka, regs,
225 + test_thread_flag(TIF_SINGLESTEP));
228 if (current->instrumentation & PTS_SELF) {
229 @@ -523,9 +497,9 @@ static void do_signal(struct pt_regs *re
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:
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)
246 + if (thread_info_flags & _TIF_NOTIFY_RESUME) {
247 + clear_thread_flag(TIF_NOTIFY_RESUME);
248 + tracehook_notify_resume(regs);
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
259 +static inline unsigned long user_stack_pointer(struct pt_regs *regs)
265 * These are defined as per linux/ptrace.h, which see.
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
271 + * Access to user system call parameters and results
273 + * Copyright (C) 2008 Red Hat, Inc. All rights reserved.
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.
279 + * See asm-generic/syscall.h for descriptions of what we must do here.
282 +#ifndef _ASM_SYSCALL_H
283 +#define _ASM_SYSCALL_H 1
285 +#include <linux/sched.h>
286 +#include <linux/err.h>
288 +static inline long syscall_get_nr(struct task_struct *task,
289 + struct pt_regs *regs)
292 + * We always sign-extend a -1 value being set here,
293 + * so this is always either -1L or a syscall number.
295 + return regs->orig_ax;
298 +static inline void syscall_rollback(struct task_struct *task,
299 + struct pt_regs *regs)
301 + regs->ax = regs->orig_ax;
304 +static inline long syscall_get_error(struct task_struct *task,
305 + struct pt_regs *regs)
307 + unsigned long error = regs->ax;
308 +#ifdef CONFIG_IA32_EMULATION
310 + * TS_COMPAT is set for 32-bit syscall entries and then
311 + * remains set until we return to user mode.
313 + if (task_thread_info(task)->status & TS_COMPAT)
315 + * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
316 + * and will match correctly in comparisons.
318 + error = (long) (int) error;
320 + return IS_ERR_VALUE(error) ? error : 0;
323 +static inline long syscall_get_return_value(struct task_struct *task,
324 + struct pt_regs *regs)
329 +static inline void syscall_set_return_value(struct task_struct *task,
330 + struct pt_regs *regs,
331 + int error, long val)
333 + regs->ax = (long) error ?: val;
336 +#ifdef CONFIG_X86_32
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)
344 + memcpy(args, ®s->bx + i, n * sizeof(args[0]));
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)
353 + memcpy(®s->bx + i, args, n * sizeof(args[0]));
356 +#else /* CONFIG_X86_64 */
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)
363 +# ifdef CONFIG_IA32_EMULATION
364 + if (task_thread_info(task)->status & TS_COMPAT)
368 + *args++ = regs->bx;
371 + *args++ = regs->cx;
374 + *args++ = regs->dx;
377 + *args++ = regs->si;
380 + *args++ = regs->di;
383 + *args++ = regs->bp;
395 + *args++ = regs->di;
398 + *args++ = regs->si;
401 + *args++ = regs->dx;
404 + *args++ = regs->r10;
407 + *args++ = regs->r8;
410 + *args++ = regs->r9;
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)
424 +# ifdef CONFIG_IA32_EMULATION
425 + if (task_thread_info(task)->status & TS_COMPAT)
429 + regs->bx = *args++;
432 + regs->cx = *args++;
435 + regs->dx = *args++;
438 + regs->si = *args++;
441 + regs->di = *args++;
444 + regs->bp = *args++;
456 + regs->di = *args++;
459 + regs->si = *args++;
462 + regs->dx = *args++;
465 + regs->r10 = *args++;
468 + regs->r8 = *args++;
471 + regs->r9 = *args++;
480 +#endif /* CONFIG_X86_32 */
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
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 */
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 {
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)
508 /* flags to check in __switch_to() */
509 #define _TIF_WORK_CTXSW \