d5663e295330aa5ac08fc19a29ac6984ba28cee0
[powerpc.git] / arch / x86 / ia32 / ptrace32.c
1 /*
2  * 32bit ptrace for x86-64.
3  *
4  * Copyright 2001,2002 Andi Kleen, SuSE Labs.
5  * Some parts copied from arch/i386/kernel/ptrace.c. See that file for earlier
6  * copyright.
7  *
8  * This allows to access 64bit processes too; but there is no way to
9  * see the extended register contents.
10  */
11
12 #include <linux/kernel.h>
13 #include <linux/stddef.h>
14 #include <linux/sched.h>
15 #include <linux/syscalls.h>
16 #include <linux/unistd.h>
17 #include <linux/mm.h>
18 #include <linux/err.h>
19 #include <linux/ptrace.h>
20 #include <asm/ptrace.h>
21 #include <asm/compat.h>
22 #include <asm/uaccess.h>
23 #include <asm/user32.h>
24 #include <asm/user.h>
25 #include <asm/errno.h>
26 #include <asm/debugreg.h>
27 #include <asm/i387.h>
28 #include <asm/fpu32.h>
29 #include <asm/ia32.h>
30
31 /*
32  * Determines which flags the user has access to [1 = access, 0 = no access].
33  * Prohibits changing ID(21), VIP(20), VIF(19), VM(17), IOPL(12-13), IF(9).
34  * Also masks reserved bits (31-22, 15, 5, 3, 1).
35  */
36 #define FLAG_MASK 0x54dd5UL
37
38 #define R32(l,q)                                                        \
39         case offsetof(struct user32, regs.l):                           \
40                 regs->q = val; break;
41
42 static int putreg32(struct task_struct *child, unsigned regno, u32 val)
43 {
44         struct pt_regs *regs = task_pt_regs(child);
45
46         switch (regno) {
47         case offsetof(struct user32, regs.fs):
48                 if (val && (val & 3) != 3)
49                         return -EIO;
50                 child->thread.fsindex = val & 0xffff;
51                 if (child == current)
52                         loadsegment(fs, child->thread.fsindex);
53                 break;
54         case offsetof(struct user32, regs.gs):
55                 if (val && (val & 3) != 3)
56                         return -EIO;
57                 child->thread.gsindex = val & 0xffff;
58                 if (child == current)
59                         load_gs_index(child->thread.gsindex);
60                 break;
61         case offsetof(struct user32, regs.ds):
62                 if (val && (val & 3) != 3)
63                         return -EIO;
64                 child->thread.ds = val & 0xffff;
65                 if (child == current)
66                         loadsegment(ds, child->thread.ds);
67                 break;
68         case offsetof(struct user32, regs.es):
69                 child->thread.es = val & 0xffff;
70                 if (child == current)
71                         loadsegment(es, child->thread.ds);
72                 break;
73         case offsetof(struct user32, regs.ss):
74                 if ((val & 3) != 3)
75                         return -EIO;
76                 regs->ss = val & 0xffff;
77                 break;
78         case offsetof(struct user32, regs.cs):
79                 if ((val & 3) != 3)
80                         return -EIO;
81                 regs->cs = val & 0xffff;
82                 break;
83
84         R32(ebx, bx);
85         R32(ecx, cx);
86         R32(edx, dx);
87         R32(edi, di);
88         R32(esi, si);
89         R32(ebp, bp);
90         R32(eax, ax);
91         R32(orig_eax, orig_ax);
92         R32(eip, ip);
93         R32(esp, sp);
94
95         case offsetof(struct user32, regs.eflags):
96                 val &= FLAG_MASK;
97                 /*
98                  * If the user value contains TF, mark that
99                  * it was not "us" (the debugger) that set it.
100                  * If not, make sure it stays set if we had.
101                  */
102                 if (val & X86_EFLAGS_TF)
103                         clear_tsk_thread_flag(child, TIF_FORCED_TF);
104                 else if (test_tsk_thread_flag(child, TIF_FORCED_TF))
105                         val |= X86_EFLAGS_TF;
106                 regs->flags = val | (regs->flags & ~FLAG_MASK);
107                 break;
108
109         case offsetof(struct user32, u_debugreg[0]) ...
110                 offsetof(struct user32, u_debugreg[7]):
111                 regno -= offsetof(struct user32, u_debugreg[0]);
112                 return ptrace_set_debugreg(child, regno / 4, val);
113
114         default:
115                 if (regno > sizeof(struct user32) || (regno & 3))
116                         return -EIO;
117
118                 /*
119                  * Other dummy fields in the virtual user structure
120                  * are ignored
121                  */
122                 break;
123         }
124         return 0;
125 }
126
127 #undef R32
128
129 #define R32(l,q)                                                        \
130         case offsetof(struct user32, regs.l):                           \
131                 *val = regs->q; break
132
133 static int getreg32(struct task_struct *child, unsigned regno, u32 *val)
134 {
135         struct pt_regs *regs = task_pt_regs(child);
136
137         switch (regno) {
138         case offsetof(struct user32, regs.fs):
139                 *val = child->thread.fsindex;
140                 if (child == current)
141                         asm("movl %%fs,%0" : "=r" (*val));
142                 break;
143         case offsetof(struct user32, regs.gs):
144                 *val = child->thread.gsindex;
145                 if (child == current)
146                         asm("movl %%gs,%0" : "=r" (*val));
147                 break;
148         case offsetof(struct user32, regs.ds):
149                 *val = child->thread.ds;
150                 if (child == current)
151                         asm("movl %%ds,%0" : "=r" (*val));
152                 break;
153         case offsetof(struct user32, regs.es):
154                 *val = child->thread.es;
155                 if (child == current)
156                         asm("movl %%es,%0" : "=r" (*val));
157                 break;
158
159         R32(cs, cs);
160         R32(ss, ss);
161         R32(ebx, bx);
162         R32(ecx, cx);
163         R32(edx, dx);
164         R32(edi, di);
165         R32(esi, si);
166         R32(ebp, bp);
167         R32(eax, ax);
168         R32(orig_eax, orig_ax);
169         R32(eip, ip);
170         R32(esp, sp);
171
172         case offsetof(struct user32, regs.eflags):
173                 /*
174                  * If the debugger set TF, hide it from the readout.
175                  */
176                 *val = regs->flags;
177                 if (test_tsk_thread_flag(child, TIF_FORCED_TF))
178                         *val &= ~X86_EFLAGS_TF;
179                 break;
180
181         case offsetof(struct user32, u_debugreg[0]) ...
182                 offsetof(struct user32, u_debugreg[7]):
183                 regno -= offsetof(struct user32, u_debugreg[0]);
184                 *val = ptrace_get_debugreg(child, regno / 4);
185                 break;
186
187         default:
188                 if (regno > sizeof(struct user32) || (regno & 3))
189                         return -EIO;
190
191                 /*
192                  * Other dummy fields in the virtual user structure
193                  * are ignored
194                  */
195                 *val = 0;
196                 break;
197         }
198         return 0;
199 }
200
201 #undef R32
202
203 static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data)
204 {
205         siginfo_t __user *si = compat_alloc_user_space(sizeof(siginfo_t));
206         compat_siginfo_t __user *si32 = compat_ptr(data);
207         siginfo_t ssi;
208         int ret;
209
210         if (request == PTRACE_SETSIGINFO) {
211                 memset(&ssi, 0, sizeof(siginfo_t));
212                 ret = copy_siginfo_from_user32(&ssi, si32);
213                 if (ret)
214                         return ret;
215                 if (copy_to_user(si, &ssi, sizeof(siginfo_t)))
216                         return -EFAULT;
217         }
218         ret = sys_ptrace(request, pid, addr, (unsigned long)si);
219         if (ret)
220                 return ret;
221         if (request == PTRACE_GETSIGINFO) {
222                 if (copy_from_user(&ssi, si, sizeof(siginfo_t)))
223                         return -EFAULT;
224                 ret = copy_siginfo_to_user32(si32, &ssi);
225         }
226         return ret;
227 }
228
229 asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
230 {
231         struct task_struct *child;
232         struct pt_regs *childregs;
233         void __user *datap = compat_ptr(data);
234         int ret;
235         __u32 val;
236
237         switch (request) {
238         case PTRACE_TRACEME:
239         case PTRACE_ATTACH:
240         case PTRACE_KILL:
241         case PTRACE_CONT:
242         case PTRACE_SINGLESTEP:
243         case PTRACE_SINGLEBLOCK:
244         case PTRACE_DETACH:
245         case PTRACE_SYSCALL:
246         case PTRACE_OLDSETOPTIONS:
247         case PTRACE_SETOPTIONS:
248         case PTRACE_SET_THREAD_AREA:
249         case PTRACE_GET_THREAD_AREA:
250                 return sys_ptrace(request, pid, addr, data);
251
252         default:
253                 return -EINVAL;
254
255         case PTRACE_PEEKTEXT:
256         case PTRACE_PEEKDATA:
257         case PTRACE_POKEDATA:
258         case PTRACE_POKETEXT:
259         case PTRACE_POKEUSR:
260         case PTRACE_PEEKUSR:
261         case PTRACE_GETREGS:
262         case PTRACE_SETREGS:
263         case PTRACE_SETFPREGS:
264         case PTRACE_GETFPREGS:
265         case PTRACE_SETFPXREGS:
266         case PTRACE_GETFPXREGS:
267         case PTRACE_GETEVENTMSG:
268                 break;
269
270         case PTRACE_SETSIGINFO:
271         case PTRACE_GETSIGINFO:
272                 return ptrace32_siginfo(request, pid, addr, data);
273         }
274
275         child = ptrace_get_task_struct(pid);
276         if (IS_ERR(child))
277                 return PTR_ERR(child);
278
279         ret = ptrace_check_attach(child, request == PTRACE_KILL);
280         if (ret < 0)
281                 goto out;
282
283         childregs = task_pt_regs(child);
284
285         switch (request) {
286         case PTRACE_PEEKDATA:
287         case PTRACE_PEEKTEXT:
288                 ret = 0;
289                 if (access_process_vm(child, addr, &val, sizeof(u32), 0) !=
290                     sizeof(u32))
291                         ret = -EIO;
292                 else
293                         ret = put_user(val, (unsigned int __user *)datap);
294                 break;
295
296         case PTRACE_POKEDATA:
297         case PTRACE_POKETEXT:
298                 ret = 0;
299                 if (access_process_vm(child, addr, &data, sizeof(u32), 1) !=
300                     sizeof(u32))
301                         ret = -EIO;
302                 break;
303
304         case PTRACE_PEEKUSR:
305                 ret = getreg32(child, addr, &val);
306                 if (ret == 0)
307                         ret = put_user(val, (__u32 __user *)datap);
308                 break;
309
310         case PTRACE_POKEUSR:
311                 ret = putreg32(child, addr, data);
312                 break;
313
314         case PTRACE_GETREGS: { /* Get all gp regs from the child. */
315                 int i;
316
317                 if (!access_ok(VERIFY_WRITE, datap, 16*4)) {
318                         ret = -EIO;
319                         break;
320                 }
321                 ret = 0;
322                 for (i = 0; i <= 16*4; i += sizeof(__u32)) {
323                         getreg32(child, i, &val);
324                         ret |= __put_user(val, (u32 __user *)datap);
325                         datap += sizeof(u32);
326                 }
327                 break;
328         }
329
330         case PTRACE_SETREGS: { /* Set all gp regs in the child. */
331                 unsigned long tmp;
332                 int i;
333
334                 if (!access_ok(VERIFY_READ, datap, 16*4)) {
335                         ret = -EIO;
336                         break;
337                 }
338                 ret = 0;
339                 for (i = 0; i <= 16*4; i += sizeof(u32)) {
340                         ret |= __get_user(tmp, (u32 __user *)datap);
341                         putreg32(child, i, tmp);
342                         datap += sizeof(u32);
343                 }
344                 break;
345         }
346
347         case PTRACE_GETFPREGS:
348                 ret = -EIO;
349                 if (!access_ok(VERIFY_READ, compat_ptr(data),
350                                sizeof(struct user_i387_struct)))
351                         break;
352                 save_i387_ia32(child, datap, childregs, 1);
353                 ret = 0;
354                         break;
355
356         case PTRACE_SETFPREGS:
357                 ret = -EIO;
358                 if (!access_ok(VERIFY_WRITE, datap,
359                                sizeof(struct user_i387_struct)))
360                         break;
361                 ret = 0;
362                 /* don't check EFAULT to be bug-to-bug compatible to i386 */
363                 restore_i387_ia32(child, datap, 1);
364                 break;
365
366         case PTRACE_GETFPXREGS: {
367                 struct user32_fxsr_struct __user *u = datap;
368
369                 init_fpu(child);
370                 ret = -EIO;
371                 if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
372                         break;
373                         ret = -EFAULT;
374                 if (__copy_to_user(u, &child->thread.i387.fxsave, sizeof(*u)))
375                         break;
376                 ret = __put_user(childregs->cs, &u->fcs);
377                 ret |= __put_user(child->thread.ds, &u->fos);
378                 break;
379         }
380         case PTRACE_SETFPXREGS: {
381                 struct user32_fxsr_struct __user *u = datap;
382
383                 unlazy_fpu(child);
384                 ret = -EIO;
385                 if (!access_ok(VERIFY_READ, u, sizeof(*u)))
386                         break;
387                 /*
388                  * no checking to be bug-to-bug compatible with i386.
389                  * but silence warning
390                  */
391                 if (__copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u)))
392                         ;
393                 set_stopped_child_used_math(child);
394                 child->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
395                 ret = 0;
396                 break;
397         }
398
399         case PTRACE_GETEVENTMSG:
400                 ret = put_user(child->ptrace_message,
401                                (unsigned int __user *)compat_ptr(data));
402                 break;
403
404         default:
405                 BUG();
406         }
407
408  out:
409         put_task_struct(child);
410         return ret;
411 }