cfg80211: handle failed skb allocation
[cascardo/linux.git] / arch / x86 / um / ptrace_32.c
1 /*
2  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3  * Licensed under the GPL
4  */
5
6 #include <linux/mm.h>
7 #include <linux/sched.h>
8 #include <asm/uaccess.h>
9 #include <asm/ptrace-abi.h>
10 #include <skas.h>
11
12 extern int arch_switch_tls(struct task_struct *to);
13
14 void arch_switch_to(struct task_struct *to)
15 {
16         int err = arch_switch_tls(to);
17         if (!err)
18                 return;
19
20         if (err != -EINVAL)
21                 printk(KERN_WARNING "arch_switch_tls failed, errno %d, "
22                        "not EINVAL\n", -err);
23         else
24                 printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n");
25 }
26
27 int is_syscall(unsigned long addr)
28 {
29         unsigned short instr;
30         int n;
31
32         n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
33         if (n) {
34                 /* access_process_vm() grants access to vsyscall and stub,
35                  * while copy_from_user doesn't. Maybe access_process_vm is
36                  * slow, but that doesn't matter, since it will be called only
37                  * in case of singlestepping, if copy_from_user failed.
38                  */
39                 n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
40                 if (n != sizeof(instr)) {
41                         printk(KERN_ERR "is_syscall : failed to read "
42                                "instruction from 0x%lx\n", addr);
43                         return 1;
44                 }
45         }
46         /* int 0x80 or sysenter */
47         return (instr == 0x80cd) || (instr == 0x340f);
48 }
49
50 /* determines which flags the user has access to. */
51 /* 1 = access 0 = no access */
52 #define FLAG_MASK 0x00044dd5
53
54 static const int reg_offsets[] = {
55         [EBX] = HOST_BX,
56         [ECX] = HOST_CX,
57         [EDX] = HOST_DX,
58         [ESI] = HOST_SI,
59         [EDI] = HOST_DI,
60         [EBP] = HOST_BP,
61         [EAX] = HOST_AX,
62         [DS] = HOST_DS,
63         [ES] = HOST_ES,
64         [FS] = HOST_FS,
65         [GS] = HOST_GS,
66         [EIP] = HOST_IP,
67         [CS] = HOST_CS,
68         [EFL] = HOST_EFLAGS,
69         [UESP] = HOST_SP,
70         [SS] = HOST_SS,
71         [ORIG_EAX] = HOST_ORIG_AX,
72 };
73
74 int putreg(struct task_struct *child, int regno, unsigned long value)
75 {
76         regno >>= 2;
77         switch (regno) {
78         case EBX:
79         case ECX:
80         case EDX:
81         case ESI:
82         case EDI:
83         case EBP:
84         case EAX:
85         case EIP:
86         case UESP:
87         case ORIG_EAX:
88                 break;
89         case FS:
90                 if (value && (value & 3) != 3)
91                         return -EIO;
92                 break;
93         case GS:
94                 if (value && (value & 3) != 3)
95                         return -EIO;
96                 break;
97         case DS:
98         case ES:
99                 if (value && (value & 3) != 3)
100                         return -EIO;
101                 value &= 0xffff;
102                 break;
103         case SS:
104         case CS:
105                 if ((value & 3) != 3)
106                         return -EIO;
107                 value &= 0xffff;
108                 break;
109         case EFL:
110                 value &= FLAG_MASK;
111                 child->thread.regs.regs.gp[HOST_EFLAGS] |= value;
112                 return 0;
113         default :
114                 panic("Bad register in putreg() : %d\n", regno);
115         }
116         child->thread.regs.regs.gp[reg_offsets[regno]] = value;
117         return 0;
118 }
119
120 int poke_user(struct task_struct *child, long addr, long data)
121 {
122         if ((addr & 3) || addr < 0)
123                 return -EIO;
124
125         if (addr < MAX_REG_OFFSET)
126                 return putreg(child, addr, data);
127         else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
128                  (addr <= offsetof(struct user, u_debugreg[7]))) {
129                 addr -= offsetof(struct user, u_debugreg[0]);
130                 addr = addr >> 2;
131                 if ((addr == 4) || (addr == 5))
132                         return -EIO;
133                 child->thread.arch.debugregs[addr] = data;
134                 return 0;
135         }
136         return -EIO;
137 }
138
139 unsigned long getreg(struct task_struct *child, int regno)
140 {
141         unsigned long mask = ~0UL;
142
143         regno >>= 2;
144         switch (regno) {
145         case FS:
146         case GS:
147         case DS:
148         case ES:
149         case SS:
150         case CS:
151                 mask = 0xffff;
152                 break;
153         case EIP:
154         case UESP:
155         case EAX:
156         case EBX:
157         case ECX:
158         case EDX:
159         case ESI:
160         case EDI:
161         case EBP:
162         case EFL:
163         case ORIG_EAX:
164                 break;
165         default:
166                 panic("Bad register in getreg() : %d\n", regno);
167         }
168         return mask & child->thread.regs.regs.gp[reg_offsets[regno]];
169 }
170
171 /* read the word at location addr in the USER area. */
172 int peek_user(struct task_struct *child, long addr, long data)
173 {
174         unsigned long tmp;
175
176         if ((addr & 3) || addr < 0)
177                 return -EIO;
178
179         tmp = 0;  /* Default return condition */
180         if (addr < MAX_REG_OFFSET) {
181                 tmp = getreg(child, addr);
182         }
183         else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
184                  (addr <= offsetof(struct user, u_debugreg[7]))) {
185                 addr -= offsetof(struct user, u_debugreg[0]);
186                 addr = addr >> 2;
187                 tmp = child->thread.arch.debugregs[addr];
188         }
189         return put_user(tmp, (unsigned long __user *) data);
190 }
191
192 static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
193 {
194         int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
195         struct user_i387_struct fpregs;
196
197         err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
198         if (err)
199                 return err;
200
201         n = copy_to_user(buf, &fpregs, sizeof(fpregs));
202         if(n > 0)
203                 return -EFAULT;
204
205         return n;
206 }
207
208 static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
209 {
210         int n, cpu = ((struct thread_info *) child->stack)->cpu;
211         struct user_i387_struct fpregs;
212
213         n = copy_from_user(&fpregs, buf, sizeof(fpregs));
214         if (n > 0)
215                 return -EFAULT;
216
217         return restore_fp_registers(userspace_pid[cpu],
218                                     (unsigned long *) &fpregs);
219 }
220
221 static int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
222 {
223         int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
224         struct user_fxsr_struct fpregs;
225
226         err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
227         if (err)
228                 return err;
229
230         n = copy_to_user(buf, &fpregs, sizeof(fpregs));
231         if(n > 0)
232                 return -EFAULT;
233
234         return n;
235 }
236
237 static int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
238 {
239         int n, cpu = ((struct thread_info *) child->stack)->cpu;
240         struct user_fxsr_struct fpregs;
241
242         n = copy_from_user(&fpregs, buf, sizeof(fpregs));
243         if (n > 0)
244                 return -EFAULT;
245
246         return restore_fpx_registers(userspace_pid[cpu],
247                                      (unsigned long *) &fpregs);
248 }
249
250 long subarch_ptrace(struct task_struct *child, long request,
251                     unsigned long addr, unsigned long data)
252 {
253         int ret = -EIO;
254         void __user *datap = (void __user *) data;
255         switch (request) {
256         case PTRACE_GETFPREGS: /* Get the child FPU state. */
257                 ret = get_fpregs(datap, child);
258                 break;
259         case PTRACE_SETFPREGS: /* Set the child FPU state. */
260                 ret = set_fpregs(datap, child);
261                 break;
262         case PTRACE_GETFPXREGS: /* Get the child FPU state. */
263                 ret = get_fpxregs(datap, child);
264                 break;
265         case PTRACE_SETFPXREGS: /* Set the child FPU state. */
266                 ret = set_fpxregs(datap, child);
267                 break;
268         default:
269                 ret = -EIO;
270         }
271         return ret;
272 }