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
|
diff -Naur linux-2.6.35.10-utrace/include/linux/ptrace.h linux-2.6.35.10-utrace-vm1/include/linux/ptrace.h
--- linux-2.6.35.10-utrace/include/linux/ptrace.h 2011-01-06 18:58:40.000000000 +0100
+++ linux-2.6.35.10-utrace-vm1/include/linux/ptrace.h 2011-01-06 19:01:14.000000000 +0100
@@ -66,6 +66,11 @@
#define PTRACE_EVENT_VFORK_DONE 5
#define PTRACE_EVENT_EXIT 6
+/* options for new PTRACE_SYSCALL syntax*/
+#define PTRACE_SYSCALL_SKIPEXIT 0x2
+#define PTRACE_SYSCALL_SKIPCALL 0x6
+#define PTRACE_SYSCALL_MASK 0x00000006
+
#include <asm/ptrace.h>
#ifdef __KERNEL__
@@ -88,6 +93,11 @@
#define PT_TRACE_VFORK_DONE 0x00000100
#define PT_TRACE_EXIT 0x00000200
+#define PT_SYSCALL_SKIPEXIT 0x60000000
+#define PT_SYSCALL_SKIPCALL 0x40000000
+#define PT_SYSCALL_MASK 0x60000000
+#define PTRACE2PT_SYSCALL(X) (((X) & PTRACE_SYSCALL_MASK) << 28)
+
#define PT_TRACE_MASK 0x000003f4
/* single stepping state bits (used on ARM and PA-RISC) */
diff -Naur linux-2.6.35.10-utrace/include/linux/tracehook.h linux-2.6.35.10-utrace-vm1/include/linux/tracehook.h
--- linux-2.6.35.10-utrace/include/linux/tracehook.h 2011-01-06 18:58:34.000000000 +0100
+++ linux-2.6.35.10-utrace-vm1/include/linux/tracehook.h 2011-01-06 19:01:14.000000000 +0100
@@ -118,7 +118,7 @@
utrace_report_syscall_entry(regs))
return 1;
ptrace_report_syscall(regs);
- return 0;
+ return (task_ptrace(current) & PT_SYSCALL_SKIPCALL) ? 1 : 0;
}
/**
@@ -150,7 +150,8 @@
return;
}
- ptrace_report_syscall(regs);
+ if (!(task_ptrace(current) & PT_SYSCALL_SKIPEXIT))
+ ptrace_report_syscall(regs);
}
/**
diff -Naur linux-2.6.35.10-utrace/kernel/ptrace-utrace.c linux-2.6.35.10-utrace-vm1/kernel/ptrace-utrace.c
--- linux-2.6.35.10-utrace/kernel/ptrace-utrace.c 2011-01-06 18:58:40.000000000 +0100
+++ linux-2.6.35.10-utrace-vm1/kernel/ptrace-utrace.c 2011-01-06 19:01:44.000000000 +0100
@@ -68,6 +68,7 @@
#define PTRACE_O_SYSEMU 0x100
#define PTRACE_O_DETACHED 0x200
+#define PTRACE_O_SKIPCALL 0x400
#define PTRACE_EVENT_SYSCALL (1 << 16)
#define PTRACE_EVENT_SIGTRAP (2 << 16)
@@ -237,6 +238,8 @@
enum utrace_resume_action action,
bool force_wakeup)
{
+ struct ptrace_context *ctx = ptrace_context(engine);
+
if (force_wakeup) {
unsigned long flags;
/*
@@ -250,7 +253,7 @@
}
}
- if (action != UTRACE_REPORT)
+ if (action != UTRACE_REPORT || ctx->options & PTRACE_O_SKIPCALL)
ptrace_context(engine)->stop_code = 0;
return utrace_control(tracee, engine, action);
@@ -429,7 +432,7 @@
* We already reported the first time.
* Nothing more to do now.
*/
- if (unlikely(ctx->options & PTRACE_O_SYSEMU))
+ if (unlikely(ctx->options & (PTRACE_O_SYSEMU | PTRACE_O_SKIPCALL)))
return UTRACE_SYSCALL_ABORT | UTRACE_REPORT;
return utrace_syscall_action(action) | UTRACE_RESUME;
}
@@ -440,6 +443,7 @@
if (unlikely(ctx->options & PTRACE_O_SYSEMU))
return UTRACE_SYSCALL_ABORT | UTRACE_REPORT;
+
/*
* Stop now to report. We will get another callback after
* we resume, with the UTRACE_SYSCALL_RESUMED flag set.
@@ -600,6 +604,10 @@
{
struct ptrace_context *ctx = ptrace_context(engine);
+ if (unlikely((ctx->options & PTRACE_O_SKIPCALL) &&
+ event == UTRACE_EVENT(SYSCALL_ENTRY)))
+ return event ? UTRACE_RESUME : ctx->resume;
+
if (ptrace_event_pending(ctx))
return UTRACE_STOP;
@@ -880,13 +888,13 @@
}
static int ptrace_resume_action(struct task_struct *tracee,
- struct utrace_engine *engine, long request)
+ struct utrace_engine *engine, long request, long addr)
{
struct ptrace_context *ctx = ptrace_context(engine);
unsigned long events;
int action;
- ctx->options &= ~PTRACE_O_SYSEMU;
+ ctx->options &= ~(PTRACE_O_SYSEMU | PTRACE_O_SKIPCALL);
events = engine->flags & ~UTRACE_EVENT_SYSCALL;
action = UTRACE_RESUME;
@@ -921,7 +929,14 @@
#endif
case PTRACE_SYSCALL:
- events |= UTRACE_EVENT_SYSCALL;
+ if (addr & (PTRACE_SYSCALL_SKIPCALL - PTRACE_SYSCALL_SKIPEXIT)) {
+ ctx->options |= PTRACE_O_SKIPCALL;
+ action = UTRACE_REPORT;
+ }
+ if (addr & PTRACE_SYSCALL_SKIPEXIT)
+ events |= UTRACE_EVENT(SYSCALL_ENTRY);
+ else
+ events |= UTRACE_EVENT_SYSCALL;
break;
case PTRACE_CONT:
@@ -939,7 +954,7 @@
static int ptrace_resume(struct task_struct *tracee,
struct utrace_engine *engine,
- long request, long data)
+ long request, long addr, long data)
{
struct ptrace_context *ctx = ptrace_context(engine);
int action;
@@ -947,7 +962,7 @@
if (!valid_signal(data))
return -EIO;
- action = ptrace_resume_action(tracee, engine, request);
+ action = ptrace_resume_action(tracee, engine, request, addr);
if (action < 0)
return action;
@@ -1052,7 +1067,7 @@
case PTRACE_KILL:
/* Ugly historical behaviour. */
if (task_is_traced(child))
- ptrace_resume(child, engine, PTRACE_CONT, SIGKILL);
+ ptrace_resume(child, engine, PTRACE_CONT, addr, SIGKILL);
ret = 0;
break;
@@ -1076,7 +1091,7 @@
}
default:
- ret = ptrace_resume(child, engine, request, data);
+ ret = ptrace_resume(child, engine, request, addr, data);
break;
}
diff -Naur linux-2.6.35.10-utrace/kernel/ptrace.c linux-2.6.35.10-utrace-vm1/kernel/ptrace.c
--- linux-2.6.35.10-utrace/kernel/ptrace.c 2011-01-06 18:58:40.000000000 +0100
+++ linux-2.6.35.10-utrace-vm1/kernel/ptrace.c 2011-01-06 19:01:14.000000000 +0100
@@ -637,7 +637,8 @@
#define is_sysemu_singlestep(request) 0
#endif
-static int ptrace_resume(struct task_struct *child, long request, long data)
+static int ptrace_resume(struct task_struct *child, long request,
+ long addr, long data)
{
if (!valid_signal(data))
return -EIO;
@@ -666,6 +667,9 @@
user_disable_single_step(child);
}
+ child->ptrace &= ~PT_SYSCALL_MASK;
+ child->ptrace |= PTRACE2PT_SYSCALL(addr);
+
child->exit_code = data;
wake_up_process(child);
@@ -753,12 +757,12 @@
#endif
case PTRACE_SYSCALL:
case PTRACE_CONT:
- return ptrace_resume(child, request, data);
+ return ptrace_resume(child, request, addr, data);
case PTRACE_KILL:
if (child->exit_state) /* already dead */
return 0;
- return ptrace_resume(child, request, SIGKILL);
+ return ptrace_resume(child, request, addr, SIGKILL);
#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
case PTRACE_GETREGSET:
|