diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/ia32/ptrace32.c | 190 |
1 files changed, 107 insertions, 83 deletions
diff --git a/arch/x86/ia32/ptrace32.c b/arch/x86/ia32/ptrace32.c index 4a233ad6269c..9d754b640205 100644 --- a/arch/x86/ia32/ptrace32.c +++ b/arch/x86/ia32/ptrace32.c | |||
@@ -1,13 +1,13 @@ | |||
1 | /* | 1 | /* |
2 | * 32bit ptrace for x86-64. | 2 | * 32bit ptrace for x86-64. |
3 | * | 3 | * |
4 | * Copyright 2001,2002 Andi Kleen, SuSE Labs. | 4 | * Copyright 2001,2002 Andi Kleen, SuSE Labs. |
5 | * Some parts copied from arch/i386/kernel/ptrace.c. See that file for earlier | 5 | * Some parts copied from arch/i386/kernel/ptrace.c. See that file for earlier |
6 | * copyright. | 6 | * copyright. |
7 | * | 7 | * |
8 | * This allows to access 64bit processes too; but there is no way to see the extended | 8 | * This allows to access 64bit processes too; but there is no way to |
9 | * register contents. | 9 | * see the extended register contents. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/stddef.h> | 13 | #include <linux/stddef.h> |
@@ -35,8 +35,9 @@ | |||
35 | */ | 35 | */ |
36 | #define FLAG_MASK 0x54dd5UL | 36 | #define FLAG_MASK 0x54dd5UL |
37 | 37 | ||
38 | #define R32(l,q) \ | 38 | #define R32(l,q) \ |
39 | case offsetof(struct user32, regs.l): stack[offsetof(struct pt_regs, q)/8] = val; break | 39 | case offsetof(struct user32, regs.l): \ |
40 | stack[offsetof(struct pt_regs, q) / 8] = val; break | ||
40 | 41 | ||
41 | static int putreg32(struct task_struct *child, unsigned regno, u32 val) | 42 | static int putreg32(struct task_struct *child, unsigned regno, u32 val) |
42 | { | 43 | { |
@@ -45,30 +46,35 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) | |||
45 | 46 | ||
46 | switch (regno) { | 47 | switch (regno) { |
47 | case offsetof(struct user32, regs.fs): | 48 | case offsetof(struct user32, regs.fs): |
48 | if (val && (val & 3) != 3) return -EIO; | 49 | if (val && (val & 3) != 3) |
50 | return -EIO; | ||
49 | child->thread.fsindex = val & 0xffff; | 51 | child->thread.fsindex = val & 0xffff; |
50 | break; | 52 | break; |
51 | case offsetof(struct user32, regs.gs): | 53 | case offsetof(struct user32, regs.gs): |
52 | if (val && (val & 3) != 3) return -EIO; | 54 | if (val && (val & 3) != 3) |
55 | return -EIO; | ||
53 | child->thread.gsindex = val & 0xffff; | 56 | child->thread.gsindex = val & 0xffff; |
54 | break; | 57 | break; |
55 | case offsetof(struct user32, regs.ds): | 58 | case offsetof(struct user32, regs.ds): |
56 | if (val && (val & 3) != 3) return -EIO; | 59 | if (val && (val & 3) != 3) |
60 | return -EIO; | ||
57 | child->thread.ds = val & 0xffff; | 61 | child->thread.ds = val & 0xffff; |
58 | break; | 62 | break; |
59 | case offsetof(struct user32, regs.es): | 63 | case offsetof(struct user32, regs.es): |
60 | child->thread.es = val & 0xffff; | 64 | child->thread.es = val & 0xffff; |
61 | break; | 65 | break; |
62 | case offsetof(struct user32, regs.ss): | 66 | case offsetof(struct user32, regs.ss): |
63 | if ((val & 3) != 3) return -EIO; | 67 | if ((val & 3) != 3) |
64 | stack[offsetof(struct pt_regs, ss)/8] = val & 0xffff; | 68 | return -EIO; |
69 | stack[offsetof(struct pt_regs, ss)/8] = val & 0xffff; | ||
65 | break; | 70 | break; |
66 | case offsetof(struct user32, regs.cs): | 71 | case offsetof(struct user32, regs.cs): |
67 | if ((val & 3) != 3) return -EIO; | 72 | if ((val & 3) != 3) |
73 | return -EIO; | ||
68 | stack[offsetof(struct pt_regs, cs)/8] = val & 0xffff; | 74 | stack[offsetof(struct pt_regs, cs)/8] = val & 0xffff; |
69 | break; | 75 | break; |
70 | 76 | ||
71 | R32(ebx, rbx); | 77 | R32(ebx, rbx); |
72 | R32(ecx, rcx); | 78 | R32(ecx, rcx); |
73 | R32(edx, rdx); | 79 | R32(edx, rdx); |
74 | R32(edi, rdi); | 80 | R32(edi, rdi); |
@@ -81,12 +87,13 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) | |||
81 | 87 | ||
82 | case offsetof(struct user32, regs.eflags): { | 88 | case offsetof(struct user32, regs.eflags): { |
83 | __u64 *flags = &stack[offsetof(struct pt_regs, eflags)/8]; | 89 | __u64 *flags = &stack[offsetof(struct pt_regs, eflags)/8]; |
90 | |||
84 | val &= FLAG_MASK; | 91 | val &= FLAG_MASK; |
85 | *flags = val | (*flags & ~FLAG_MASK); | 92 | *flags = val | (*flags & ~FLAG_MASK); |
86 | break; | 93 | break; |
87 | } | 94 | } |
88 | 95 | ||
89 | case offsetof(struct user32, u_debugreg[4]): | 96 | case offsetof(struct user32, u_debugreg[4]): |
90 | case offsetof(struct user32, u_debugreg[5]): | 97 | case offsetof(struct user32, u_debugreg[5]): |
91 | return -EIO; | 98 | return -EIO; |
92 | 99 | ||
@@ -108,36 +115,40 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) | |||
108 | 115 | ||
109 | case offsetof(struct user32, u_debugreg[6]): | 116 | case offsetof(struct user32, u_debugreg[6]): |
110 | child->thread.debugreg6 = val; | 117 | child->thread.debugreg6 = val; |
111 | break; | 118 | break; |
112 | 119 | ||
113 | case offsetof(struct user32, u_debugreg[7]): | 120 | case offsetof(struct user32, u_debugreg[7]): |
114 | val &= ~DR_CONTROL_RESERVED; | 121 | val &= ~DR_CONTROL_RESERVED; |
115 | /* See arch/i386/kernel/ptrace.c for an explanation of | 122 | /* See arch/i386/kernel/ptrace.c for an explanation of |
116 | * this awkward check.*/ | 123 | * this awkward check.*/ |
117 | for(i=0; i<4; i++) | 124 | for (i = 0; i < 4; i++) |
118 | if ((0x5454 >> ((val >> (16 + 4*i)) & 0xf)) & 1) | 125 | if ((0x5454 >> ((val >> (16 + 4*i)) & 0xf)) & 1) |
119 | return -EIO; | 126 | return -EIO; |
120 | child->thread.debugreg7 = val; | 127 | child->thread.debugreg7 = val; |
121 | if (val) | 128 | if (val) |
122 | set_tsk_thread_flag(child, TIF_DEBUG); | 129 | set_tsk_thread_flag(child, TIF_DEBUG); |
123 | else | 130 | else |
124 | clear_tsk_thread_flag(child, TIF_DEBUG); | 131 | clear_tsk_thread_flag(child, TIF_DEBUG); |
125 | break; | 132 | break; |
126 | 133 | ||
127 | default: | 134 | default: |
128 | if (regno > sizeof(struct user32) || (regno & 3)) | 135 | if (regno > sizeof(struct user32) || (regno & 3)) |
129 | return -EIO; | 136 | return -EIO; |
130 | 137 | ||
131 | /* Other dummy fields in the virtual user structure are ignored */ | 138 | /* |
132 | break; | 139 | * Other dummy fields in the virtual user structure |
140 | * are ignored | ||
141 | */ | ||
142 | break; | ||
133 | } | 143 | } |
134 | return 0; | 144 | return 0; |
135 | } | 145 | } |
136 | 146 | ||
137 | #undef R32 | 147 | #undef R32 |
138 | 148 | ||
139 | #define R32(l,q) \ | 149 | #define R32(l,q) \ |
140 | case offsetof(struct user32, regs.l): *val = stack[offsetof(struct pt_regs, q)/8]; break | 150 | case offsetof(struct user32, regs.l): \ |
151 | *val = stack[offsetof(struct pt_regs, q)/8]; break | ||
141 | 152 | ||
142 | static int getreg32(struct task_struct *child, unsigned regno, u32 *val) | 153 | static int getreg32(struct task_struct *child, unsigned regno, u32 *val) |
143 | { | 154 | { |
@@ -145,7 +156,7 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val) | |||
145 | 156 | ||
146 | switch (regno) { | 157 | switch (regno) { |
147 | case offsetof(struct user32, regs.fs): | 158 | case offsetof(struct user32, regs.fs): |
148 | *val = child->thread.fsindex; | 159 | *val = child->thread.fsindex; |
149 | break; | 160 | break; |
150 | case offsetof(struct user32, regs.gs): | 161 | case offsetof(struct user32, regs.gs): |
151 | *val = child->thread.gsindex; | 162 | *val = child->thread.gsindex; |
@@ -159,7 +170,7 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val) | |||
159 | 170 | ||
160 | R32(cs, cs); | 171 | R32(cs, cs); |
161 | R32(ss, ss); | 172 | R32(ss, ss); |
162 | R32(ebx, rbx); | 173 | R32(ebx, rbx); |
163 | R32(ecx, rcx); | 174 | R32(ecx, rcx); |
164 | R32(edx, rdx); | 175 | R32(edx, rdx); |
165 | R32(edi, rdi); | 176 | R32(edi, rdi); |
@@ -171,32 +182,35 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val) | |||
171 | R32(eflags, eflags); | 182 | R32(eflags, eflags); |
172 | R32(esp, rsp); | 183 | R32(esp, rsp); |
173 | 184 | ||
174 | case offsetof(struct user32, u_debugreg[0]): | 185 | case offsetof(struct user32, u_debugreg[0]): |
175 | *val = child->thread.debugreg0; | 186 | *val = child->thread.debugreg0; |
176 | break; | 187 | break; |
177 | case offsetof(struct user32, u_debugreg[1]): | 188 | case offsetof(struct user32, u_debugreg[1]): |
178 | *val = child->thread.debugreg1; | 189 | *val = child->thread.debugreg1; |
179 | break; | 190 | break; |
180 | case offsetof(struct user32, u_debugreg[2]): | 191 | case offsetof(struct user32, u_debugreg[2]): |
181 | *val = child->thread.debugreg2; | 192 | *val = child->thread.debugreg2; |
182 | break; | 193 | break; |
183 | case offsetof(struct user32, u_debugreg[3]): | 194 | case offsetof(struct user32, u_debugreg[3]): |
184 | *val = child->thread.debugreg3; | 195 | *val = child->thread.debugreg3; |
185 | break; | 196 | break; |
186 | case offsetof(struct user32, u_debugreg[6]): | 197 | case offsetof(struct user32, u_debugreg[6]): |
187 | *val = child->thread.debugreg6; | 198 | *val = child->thread.debugreg6; |
188 | break; | 199 | break; |
189 | case offsetof(struct user32, u_debugreg[7]): | 200 | case offsetof(struct user32, u_debugreg[7]): |
190 | *val = child->thread.debugreg7; | 201 | *val = child->thread.debugreg7; |
191 | break; | 202 | break; |
192 | 203 | ||
193 | default: | 204 | default: |
194 | if (regno > sizeof(struct user32) || (regno & 3)) | 205 | if (regno > sizeof(struct user32) || (regno & 3)) |
195 | return -EIO; | 206 | return -EIO; |
196 | 207 | ||
197 | /* Other dummy fields in the virtual user structure are ignored */ | 208 | /* |
209 | * Other dummy fields in the virtual user structure | ||
210 | * are ignored | ||
211 | */ | ||
198 | *val = 0; | 212 | *val = 0; |
199 | break; | 213 | break; |
200 | } | 214 | } |
201 | return 0; | 215 | return 0; |
202 | } | 216 | } |
@@ -205,10 +219,11 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val) | |||
205 | 219 | ||
206 | static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data) | 220 | static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data) |
207 | { | 221 | { |
208 | int ret; | ||
209 | compat_siginfo_t __user *si32 = compat_ptr(data); | ||
210 | siginfo_t ssi; | ||
211 | siginfo_t __user *si = compat_alloc_user_space(sizeof(siginfo_t)); | 222 | siginfo_t __user *si = compat_alloc_user_space(sizeof(siginfo_t)); |
223 | compat_siginfo_t __user *si32 = compat_ptr(data); | ||
224 | siginfo_t ssi; | ||
225 | int ret; | ||
226 | |||
212 | if (request == PTRACE_SETSIGINFO) { | 227 | if (request == PTRACE_SETSIGINFO) { |
213 | memset(&ssi, 0, sizeof(siginfo_t)); | 228 | memset(&ssi, 0, sizeof(siginfo_t)); |
214 | ret = copy_siginfo_from_user32(&ssi, si32); | 229 | ret = copy_siginfo_from_user32(&ssi, si32); |
@@ -231,12 +246,12 @@ static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data) | |||
231 | asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) | 246 | asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) |
232 | { | 247 | { |
233 | struct task_struct *child; | 248 | struct task_struct *child; |
234 | struct pt_regs *childregs; | 249 | struct pt_regs *childregs; |
235 | void __user *datap = compat_ptr(data); | 250 | void __user *datap = compat_ptr(data); |
236 | int ret; | 251 | int ret; |
237 | __u32 val; | 252 | __u32 val; |
238 | 253 | ||
239 | switch (request) { | 254 | switch (request) { |
240 | case PTRACE_TRACEME: | 255 | case PTRACE_TRACEME: |
241 | case PTRACE_ATTACH: | 256 | case PTRACE_ATTACH: |
242 | case PTRACE_KILL: | 257 | case PTRACE_KILL: |
@@ -248,7 +263,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) | |||
248 | case PTRACE_SETOPTIONS: | 263 | case PTRACE_SETOPTIONS: |
249 | case PTRACE_SET_THREAD_AREA: | 264 | case PTRACE_SET_THREAD_AREA: |
250 | case PTRACE_GET_THREAD_AREA: | 265 | case PTRACE_GET_THREAD_AREA: |
251 | return sys_ptrace(request, pid, addr, data); | 266 | return sys_ptrace(request, pid, addr, data); |
252 | 267 | ||
253 | default: | 268 | default: |
254 | return -EINVAL; | 269 | return -EINVAL; |
@@ -257,7 +272,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) | |||
257 | case PTRACE_PEEKDATA: | 272 | case PTRACE_PEEKDATA: |
258 | case PTRACE_POKEDATA: | 273 | case PTRACE_POKEDATA: |
259 | case PTRACE_POKETEXT: | 274 | case PTRACE_POKETEXT: |
260 | case PTRACE_POKEUSR: | 275 | case PTRACE_POKEUSR: |
261 | case PTRACE_PEEKUSR: | 276 | case PTRACE_PEEKUSR: |
262 | case PTRACE_GETREGS: | 277 | case PTRACE_GETREGS: |
263 | case PTRACE_SETREGS: | 278 | case PTRACE_SETREGS: |
@@ -287,17 +302,19 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) | |||
287 | case PTRACE_PEEKDATA: | 302 | case PTRACE_PEEKDATA: |
288 | case PTRACE_PEEKTEXT: | 303 | case PTRACE_PEEKTEXT: |
289 | ret = 0; | 304 | ret = 0; |
290 | if (access_process_vm(child, addr, &val, sizeof(u32), 0)!=sizeof(u32)) | 305 | if (access_process_vm(child, addr, &val, sizeof(u32), 0) != |
306 | sizeof(u32)) | ||
291 | ret = -EIO; | 307 | ret = -EIO; |
292 | else | 308 | else |
293 | ret = put_user(val, (unsigned int __user *)datap); | 309 | ret = put_user(val, (unsigned int __user *)datap); |
294 | break; | 310 | break; |
295 | 311 | ||
296 | case PTRACE_POKEDATA: | 312 | case PTRACE_POKEDATA: |
297 | case PTRACE_POKETEXT: | 313 | case PTRACE_POKETEXT: |
298 | ret = 0; | 314 | ret = 0; |
299 | if (access_process_vm(child, addr, &data, sizeof(u32), 1)!=sizeof(u32)) | 315 | if (access_process_vm(child, addr, &data, sizeof(u32), 1) != |
300 | ret = -EIO; | 316 | sizeof(u32)) |
317 | ret = -EIO; | ||
301 | break; | 318 | break; |
302 | 319 | ||
303 | case PTRACE_PEEKUSR: | 320 | case PTRACE_PEEKUSR: |
@@ -312,14 +329,15 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) | |||
312 | 329 | ||
313 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ | 330 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ |
314 | int i; | 331 | int i; |
315 | if (!access_ok(VERIFY_WRITE, datap, 16*4)) { | 332 | |
333 | if (!access_ok(VERIFY_WRITE, datap, 16*4)) { | ||
316 | ret = -EIO; | 334 | ret = -EIO; |
317 | break; | 335 | break; |
318 | } | 336 | } |
319 | ret = 0; | 337 | ret = 0; |
320 | for ( i = 0; i <= 16*4 ; i += sizeof(__u32) ) { | 338 | for (i = 0; i <= 16*4; i += sizeof(__u32)) { |
321 | getreg32(child, i, &val); | 339 | getreg32(child, i, &val); |
322 | ret |= __put_user(val,(u32 __user *)datap); | 340 | ret |= __put_user(val, (u32 __user *)datap); |
323 | datap += sizeof(u32); | 341 | datap += sizeof(u32); |
324 | } | 342 | } |
325 | break; | 343 | break; |
@@ -328,12 +346,13 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) | |||
328 | case PTRACE_SETREGS: { /* Set all gp regs in the child. */ | 346 | case PTRACE_SETREGS: { /* Set all gp regs in the child. */ |
329 | unsigned long tmp; | 347 | unsigned long tmp; |
330 | int i; | 348 | int i; |
331 | if (!access_ok(VERIFY_READ, datap, 16*4)) { | 349 | |
350 | if (!access_ok(VERIFY_READ, datap, 16*4)) { | ||
332 | ret = -EIO; | 351 | ret = -EIO; |
333 | break; | 352 | break; |
334 | } | 353 | } |
335 | ret = 0; | 354 | ret = 0; |
336 | for ( i = 0; i <= 16*4; i += sizeof(u32) ) { | 355 | for (i = 0; i <= 16*4; i += sizeof(u32)) { |
337 | ret |= __get_user(tmp, (u32 __user *)datap); | 356 | ret |= __get_user(tmp, (u32 __user *)datap); |
338 | putreg32(child, i, tmp); | 357 | putreg32(child, i, tmp); |
339 | datap += sizeof(u32); | 358 | datap += sizeof(u32); |
@@ -342,17 +361,17 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) | |||
342 | } | 361 | } |
343 | 362 | ||
344 | case PTRACE_GETFPREGS: | 363 | case PTRACE_GETFPREGS: |
345 | ret = -EIO; | 364 | ret = -EIO; |
346 | if (!access_ok(VERIFY_READ, compat_ptr(data), | 365 | if (!access_ok(VERIFY_READ, compat_ptr(data), |
347 | sizeof(struct user_i387_struct))) | 366 | sizeof(struct user_i387_struct))) |
348 | break; | 367 | break; |
349 | save_i387_ia32(child, datap, childregs, 1); | 368 | save_i387_ia32(child, datap, childregs, 1); |
350 | ret = 0; | 369 | ret = 0; |
351 | break; | 370 | break; |
352 | 371 | ||
353 | case PTRACE_SETFPREGS: | 372 | case PTRACE_SETFPREGS: |
354 | ret = -EIO; | 373 | ret = -EIO; |
355 | if (!access_ok(VERIFY_WRITE, datap, | 374 | if (!access_ok(VERIFY_WRITE, datap, |
356 | sizeof(struct user_i387_struct))) | 375 | sizeof(struct user_i387_struct))) |
357 | break; | 376 | break; |
358 | ret = 0; | 377 | ret = 0; |
@@ -360,9 +379,10 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) | |||
360 | restore_i387_ia32(child, datap, 1); | 379 | restore_i387_ia32(child, datap, 1); |
361 | break; | 380 | break; |
362 | 381 | ||
363 | case PTRACE_GETFPXREGS: { | 382 | case PTRACE_GETFPXREGS: { |
364 | struct user32_fxsr_struct __user *u = datap; | 383 | struct user32_fxsr_struct __user *u = datap; |
365 | init_fpu(child); | 384 | |
385 | init_fpu(child); | ||
366 | ret = -EIO; | 386 | ret = -EIO; |
367 | if (!access_ok(VERIFY_WRITE, u, sizeof(*u))) | 387 | if (!access_ok(VERIFY_WRITE, u, sizeof(*u))) |
368 | break; | 388 | break; |
@@ -370,27 +390,31 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) | |||
370 | if (__copy_to_user(u, &child->thread.i387.fxsave, sizeof(*u))) | 390 | if (__copy_to_user(u, &child->thread.i387.fxsave, sizeof(*u))) |
371 | break; | 391 | break; |
372 | ret = __put_user(childregs->cs, &u->fcs); | 392 | ret = __put_user(childregs->cs, &u->fcs); |
373 | ret |= __put_user(child->thread.ds, &u->fos); | 393 | ret |= __put_user(child->thread.ds, &u->fos); |
374 | break; | 394 | break; |
375 | } | 395 | } |
376 | case PTRACE_SETFPXREGS: { | 396 | case PTRACE_SETFPXREGS: { |
377 | struct user32_fxsr_struct __user *u = datap; | 397 | struct user32_fxsr_struct __user *u = datap; |
398 | |||
378 | unlazy_fpu(child); | 399 | unlazy_fpu(child); |
379 | ret = -EIO; | 400 | ret = -EIO; |
380 | if (!access_ok(VERIFY_READ, u, sizeof(*u))) | 401 | if (!access_ok(VERIFY_READ, u, sizeof(*u))) |
381 | break; | 402 | break; |
382 | /* no checking to be bug-to-bug compatible with i386. */ | 403 | /* |
383 | /* but silence warning */ | 404 | * no checking to be bug-to-bug compatible with i386. |
405 | * but silence warning | ||
406 | */ | ||
384 | if (__copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u))) | 407 | if (__copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u))) |
385 | ; | 408 | ; |
386 | set_stopped_child_used_math(child); | 409 | set_stopped_child_used_math(child); |
387 | child->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask; | 410 | child->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask; |
388 | ret = 0; | 411 | ret = 0; |
389 | break; | 412 | break; |
390 | } | 413 | } |
391 | 414 | ||
392 | case PTRACE_GETEVENTMSG: | 415 | case PTRACE_GETEVENTMSG: |
393 | ret = put_user(child->ptrace_message,(unsigned int __user *)compat_ptr(data)); | 416 | ret = put_user(child->ptrace_message, |
417 | (unsigned int __user *)compat_ptr(data)); | ||
394 | break; | 418 | break; |
395 | 419 | ||
396 | default: | 420 | default: |