aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/ia32
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-02-09 18:40:48 -0500
committerIngo Molnar <mingo@elte.hu>2009-02-09 18:40:48 -0500
commit5d96218b4a5ee0c5ff0ac87f3ba90cfa86ca0ca1 (patch)
treea67a6a4499a235a2aab53a61bf1badff484bc345 /arch/x86/ia32
parent249d51b53aea1b7cdb1be65a1a9a0c59d9e06f3e (diff)
parent18114f61359ac05e3aa797d53d63f40db41f798d (diff)
Merge branch 'x86/uaccess' into core/percpu
Diffstat (limited to 'arch/x86/ia32')
-rw-r--r--arch/x86/ia32/ia32_signal.c365
1 files changed, 195 insertions, 170 deletions
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index 9dabd00e9805..dd77ac0cac46 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -46,78 +46,83 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
46 46
47int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) 47int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
48{ 48{
49 int err; 49 int err = 0;
50 50
51 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t))) 51 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
52 return -EFAULT; 52 return -EFAULT;
53 53
54 /* If you change siginfo_t structure, please make sure that 54 put_user_try {
55 this code is fixed accordingly. 55 /* If you change siginfo_t structure, please make sure that
56 It should never copy any pad contained in the structure 56 this code is fixed accordingly.
57 to avoid security leaks, but must copy the generic 57 It should never copy any pad contained in the structure
58 3 ints plus the relevant union member. */ 58 to avoid security leaks, but must copy the generic
59 err = __put_user(from->si_signo, &to->si_signo); 59 3 ints plus the relevant union member. */
60 err |= __put_user(from->si_errno, &to->si_errno); 60 put_user_ex(from->si_signo, &to->si_signo);
61 err |= __put_user((short)from->si_code, &to->si_code); 61 put_user_ex(from->si_errno, &to->si_errno);
62 62 put_user_ex((short)from->si_code, &to->si_code);
63 if (from->si_code < 0) { 63
64 err |= __put_user(from->si_pid, &to->si_pid); 64 if (from->si_code < 0) {
65 err |= __put_user(from->si_uid, &to->si_uid); 65 put_user_ex(from->si_pid, &to->si_pid);
66 err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr); 66 put_user_ex(from->si_uid, &to->si_uid);
67 } else { 67 put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr);
68 /* 68 } else {
69 * First 32bits of unions are always present: 69 /*
70 * si_pid === si_band === si_tid === si_addr(LS half) 70 * First 32bits of unions are always present:
71 */ 71 * si_pid === si_band === si_tid === si_addr(LS half)
72 err |= __put_user(from->_sifields._pad[0], 72 */
73 &to->_sifields._pad[0]); 73 put_user_ex(from->_sifields._pad[0],
74 switch (from->si_code >> 16) { 74 &to->_sifields._pad[0]);
75 case __SI_FAULT >> 16: 75 switch (from->si_code >> 16) {
76 break; 76 case __SI_FAULT >> 16:
77 case __SI_CHLD >> 16: 77 break;
78 err |= __put_user(from->si_utime, &to->si_utime); 78 case __SI_CHLD >> 16:
79 err |= __put_user(from->si_stime, &to->si_stime); 79 put_user_ex(from->si_utime, &to->si_utime);
80 err |= __put_user(from->si_status, &to->si_status); 80 put_user_ex(from->si_stime, &to->si_stime);
81 /* FALL THROUGH */ 81 put_user_ex(from->si_status, &to->si_status);
82 default: 82 /* FALL THROUGH */
83 case __SI_KILL >> 16: 83 default:
84 err |= __put_user(from->si_uid, &to->si_uid); 84 case __SI_KILL >> 16:
85 break; 85 put_user_ex(from->si_uid, &to->si_uid);
86 case __SI_POLL >> 16: 86 break;
87 err |= __put_user(from->si_fd, &to->si_fd); 87 case __SI_POLL >> 16:
88 break; 88 put_user_ex(from->si_fd, &to->si_fd);
89 case __SI_TIMER >> 16: 89 break;
90 err |= __put_user(from->si_overrun, &to->si_overrun); 90 case __SI_TIMER >> 16:
91 err |= __put_user(ptr_to_compat(from->si_ptr), 91 put_user_ex(from->si_overrun, &to->si_overrun);
92 &to->si_ptr); 92 put_user_ex(ptr_to_compat(from->si_ptr),
93 break; 93 &to->si_ptr);
94 /* This is not generated by the kernel as of now. */ 94 break;
95 case __SI_RT >> 16: 95 /* This is not generated by the kernel as of now. */
96 case __SI_MESGQ >> 16: 96 case __SI_RT >> 16:
97 err |= __put_user(from->si_uid, &to->si_uid); 97 case __SI_MESGQ >> 16:
98 err |= __put_user(from->si_int, &to->si_int); 98 put_user_ex(from->si_uid, &to->si_uid);
99 break; 99 put_user_ex(from->si_int, &to->si_int);
100 break;
101 }
100 } 102 }
101 } 103 } put_user_catch(err);
104
102 return err; 105 return err;
103} 106}
104 107
105int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) 108int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
106{ 109{
107 int err; 110 int err = 0;
108 u32 ptr32; 111 u32 ptr32;
109 112
110 if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t))) 113 if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
111 return -EFAULT; 114 return -EFAULT;
112 115
113 err = __get_user(to->si_signo, &from->si_signo); 116 get_user_try {
114 err |= __get_user(to->si_errno, &from->si_errno); 117 get_user_ex(to->si_signo, &from->si_signo);
115 err |= __get_user(to->si_code, &from->si_code); 118 get_user_ex(to->si_errno, &from->si_errno);
119 get_user_ex(to->si_code, &from->si_code);
116 120
117 err |= __get_user(to->si_pid, &from->si_pid); 121 get_user_ex(to->si_pid, &from->si_pid);
118 err |= __get_user(to->si_uid, &from->si_uid); 122 get_user_ex(to->si_uid, &from->si_uid);
119 err |= __get_user(ptr32, &from->si_ptr); 123 get_user_ex(ptr32, &from->si_ptr);
120 to->si_ptr = compat_ptr(ptr32); 124 to->si_ptr = compat_ptr(ptr32);
125 } get_user_catch(err);
121 126
122 return err; 127 return err;
123} 128}
@@ -142,17 +147,23 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
142 struct pt_regs *regs) 147 struct pt_regs *regs)
143{ 148{
144 stack_t uss, uoss; 149 stack_t uss, uoss;
145 int ret; 150 int ret, err = 0;
146 mm_segment_t seg; 151 mm_segment_t seg;
147 152
148 if (uss_ptr) { 153 if (uss_ptr) {
149 u32 ptr; 154 u32 ptr;
150 155
151 memset(&uss, 0, sizeof(stack_t)); 156 memset(&uss, 0, sizeof(stack_t));
152 if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)) || 157 if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)))
153 __get_user(ptr, &uss_ptr->ss_sp) || 158 return -EFAULT;
154 __get_user(uss.ss_flags, &uss_ptr->ss_flags) || 159
155 __get_user(uss.ss_size, &uss_ptr->ss_size)) 160 get_user_try {
161 get_user_ex(ptr, &uss_ptr->ss_sp);
162 get_user_ex(uss.ss_flags, &uss_ptr->ss_flags);
163 get_user_ex(uss.ss_size, &uss_ptr->ss_size);
164 } get_user_catch(err);
165
166 if (err)
156 return -EFAULT; 167 return -EFAULT;
157 uss.ss_sp = compat_ptr(ptr); 168 uss.ss_sp = compat_ptr(ptr);
158 } 169 }
@@ -161,10 +172,16 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
161 ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp); 172 ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp);
162 set_fs(seg); 173 set_fs(seg);
163 if (ret >= 0 && uoss_ptr) { 174 if (ret >= 0 && uoss_ptr) {
164 if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)) || 175 if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)))
165 __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) || 176 return -EFAULT;
166 __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) || 177
167 __put_user(uoss.ss_size, &uoss_ptr->ss_size)) 178 put_user_try {
179 put_user_ex(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp);
180 put_user_ex(uoss.ss_flags, &uoss_ptr->ss_flags);
181 put_user_ex(uoss.ss_size, &uoss_ptr->ss_size);
182 } put_user_catch(err);
183
184 if (err)
168 ret = -EFAULT; 185 ret = -EFAULT;
169 } 186 }
170 return ret; 187 return ret;
@@ -174,18 +191,18 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
174 * Do a signal return; undo the signal stack. 191 * Do a signal return; undo the signal stack.
175 */ 192 */
176#define COPY(x) { \ 193#define COPY(x) { \
177 err |= __get_user(regs->x, &sc->x); \ 194 get_user_ex(regs->x, &sc->x); \
178} 195}
179 196
180#define COPY_SEG_CPL3(seg) { \ 197#define COPY_SEG_CPL3(seg) { \
181 unsigned short tmp; \ 198 unsigned short tmp; \
182 err |= __get_user(tmp, &sc->seg); \ 199 get_user_ex(tmp, &sc->seg); \
183 regs->seg = tmp | 3; \ 200 regs->seg = tmp | 3; \
184} 201}
185 202
186#define RELOAD_SEG(seg) { \ 203#define RELOAD_SEG(seg) { \
187 unsigned int cur, pre; \ 204 unsigned int cur, pre; \
188 err |= __get_user(pre, &sc->seg); \ 205 get_user_ex(pre, &sc->seg); \
189 savesegment(seg, cur); \ 206 savesegment(seg, cur); \
190 pre |= 3; \ 207 pre |= 3; \
191 if (pre != cur) \ 208 if (pre != cur) \
@@ -209,39 +226,42 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
209 sc, sc->err, sc->ip, sc->cs, sc->flags); 226 sc, sc->err, sc->ip, sc->cs, sc->flags);
210#endif 227#endif
211 228
212 /* 229 get_user_try {
213 * Reload fs and gs if they have changed in the signal 230 /*
214 * handler. This does not handle long fs/gs base changes in 231 * Reload fs and gs if they have changed in the signal
215 * the handler, but does not clobber them at least in the 232 * handler. This does not handle long fs/gs base changes in
216 * normal case. 233 * the handler, but does not clobber them at least in the
217 */ 234 * normal case.
218 err |= __get_user(gs, &sc->gs); 235 */
219 gs |= 3; 236 get_user_ex(gs, &sc->gs);
220 savesegment(gs, oldgs); 237 gs |= 3;
221 if (gs != oldgs) 238 savesegment(gs, oldgs);
222 load_gs_index(gs); 239 if (gs != oldgs)
223 240 load_gs_index(gs);
224 RELOAD_SEG(fs); 241
225 RELOAD_SEG(ds); 242 RELOAD_SEG(fs);
226 RELOAD_SEG(es); 243 RELOAD_SEG(ds);
227 244 RELOAD_SEG(es);
228 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); 245
229 COPY(dx); COPY(cx); COPY(ip); 246 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
230 /* Don't touch extended registers */ 247 COPY(dx); COPY(cx); COPY(ip);
231 248 /* Don't touch extended registers */
232 COPY_SEG_CPL3(cs); 249
233 COPY_SEG_CPL3(ss); 250 COPY_SEG_CPL3(cs);
234 251 COPY_SEG_CPL3(ss);
235 err |= __get_user(tmpflags, &sc->flags); 252
236 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); 253 get_user_ex(tmpflags, &sc->flags);
237 /* disable syscall checks */ 254 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
238 regs->orig_ax = -1; 255 /* disable syscall checks */
239 256 regs->orig_ax = -1;
240 err |= __get_user(tmp, &sc->fpstate); 257
241 buf = compat_ptr(tmp); 258 get_user_ex(tmp, &sc->fpstate);
242 err |= restore_i387_xstate_ia32(buf); 259 buf = compat_ptr(tmp);
243 260 err |= restore_i387_xstate_ia32(buf);
244 err |= __get_user(*pax, &sc->ax); 261
262 get_user_ex(*pax, &sc->ax);
263 } get_user_catch(err);
264
245 return err; 265 return err;
246} 266}
247 267
@@ -319,36 +339,38 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
319{ 339{
320 int tmp, err = 0; 340 int tmp, err = 0;
321 341
322 savesegment(gs, tmp); 342 put_user_try {
323 err |= __put_user(tmp, (unsigned int __user *)&sc->gs); 343 savesegment(gs, tmp);
324 savesegment(fs, tmp); 344 put_user_ex(tmp, (unsigned int __user *)&sc->gs);
325 err |= __put_user(tmp, (unsigned int __user *)&sc->fs); 345 savesegment(fs, tmp);
326 savesegment(ds, tmp); 346 put_user_ex(tmp, (unsigned int __user *)&sc->fs);
327 err |= __put_user(tmp, (unsigned int __user *)&sc->ds); 347 savesegment(ds, tmp);
328 savesegment(es, tmp); 348 put_user_ex(tmp, (unsigned int __user *)&sc->ds);
329 err |= __put_user(tmp, (unsigned int __user *)&sc->es); 349 savesegment(es, tmp);
330 350 put_user_ex(tmp, (unsigned int __user *)&sc->es);
331 err |= __put_user(regs->di, &sc->di); 351
332 err |= __put_user(regs->si, &sc->si); 352 put_user_ex(regs->di, &sc->di);
333 err |= __put_user(regs->bp, &sc->bp); 353 put_user_ex(regs->si, &sc->si);
334 err |= __put_user(regs->sp, &sc->sp); 354 put_user_ex(regs->bp, &sc->bp);
335 err |= __put_user(regs->bx, &sc->bx); 355 put_user_ex(regs->sp, &sc->sp);
336 err |= __put_user(regs->dx, &sc->dx); 356 put_user_ex(regs->bx, &sc->bx);
337 err |= __put_user(regs->cx, &sc->cx); 357 put_user_ex(regs->dx, &sc->dx);
338 err |= __put_user(regs->ax, &sc->ax); 358 put_user_ex(regs->cx, &sc->cx);
339 err |= __put_user(current->thread.trap_no, &sc->trapno); 359 put_user_ex(regs->ax, &sc->ax);
340 err |= __put_user(current->thread.error_code, &sc->err); 360 put_user_ex(current->thread.trap_no, &sc->trapno);
341 err |= __put_user(regs->ip, &sc->ip); 361 put_user_ex(current->thread.error_code, &sc->err);
342 err |= __put_user(regs->cs, (unsigned int __user *)&sc->cs); 362 put_user_ex(regs->ip, &sc->ip);
343 err |= __put_user(regs->flags, &sc->flags); 363 put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
344 err |= __put_user(regs->sp, &sc->sp_at_signal); 364 put_user_ex(regs->flags, &sc->flags);
345 err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss); 365 put_user_ex(regs->sp, &sc->sp_at_signal);
346 366 put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
347 err |= __put_user(ptr_to_compat(fpstate), &sc->fpstate); 367
348 368 put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
349 /* non-iBCS2 extensions.. */ 369
350 err |= __put_user(mask, &sc->oldmask); 370 /* non-iBCS2 extensions.. */
351 err |= __put_user(current->thread.cr2, &sc->cr2); 371 put_user_ex(mask, &sc->oldmask);
372 put_user_ex(current->thread.cr2, &sc->cr2);
373 } put_user_catch(err);
352 374
353 return err; 375 return err;
354} 376}
@@ -437,13 +459,17 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
437 else 459 else
438 restorer = &frame->retcode; 460 restorer = &frame->retcode;
439 } 461 }
440 err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
441 462
442 /* 463 put_user_try {
443 * These are actually not used anymore, but left because some 464 put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
444 * gdb versions depend on them as a marker. 465
445 */ 466 /*
446 err |= __put_user(*((u64 *)&code), (u64 *)frame->retcode); 467 * These are actually not used anymore, but left because some
468 * gdb versions depend on them as a marker.
469 */
470 put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
471 } put_user_catch(err);
472
447 if (err) 473 if (err)
448 return -EFAULT; 474 return -EFAULT;
449 475
@@ -496,41 +522,40 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
496 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 522 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
497 return -EFAULT; 523 return -EFAULT;
498 524
499 err |= __put_user(sig, &frame->sig); 525 put_user_try {
500 err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo); 526 put_user_ex(sig, &frame->sig);
501 err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc); 527 put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo);
502 err |= copy_siginfo_to_user32(&frame->info, info); 528 put_user_ex(ptr_to_compat(&frame->uc), &frame->puc);
503 if (err) 529 err |= copy_siginfo_to_user32(&frame->info, info);
504 return -EFAULT;
505 530
506 /* Create the ucontext. */ 531 /* Create the ucontext. */
507 if (cpu_has_xsave) 532 if (cpu_has_xsave)
508 err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); 533 put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
509 else 534 else
510 err |= __put_user(0, &frame->uc.uc_flags); 535 put_user_ex(0, &frame->uc.uc_flags);
511 err |= __put_user(0, &frame->uc.uc_link); 536 put_user_ex(0, &frame->uc.uc_link);
512 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); 537 put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
513 err |= __put_user(sas_ss_flags(regs->sp), 538 put_user_ex(sas_ss_flags(regs->sp),
514 &frame->uc.uc_stack.ss_flags); 539 &frame->uc.uc_stack.ss_flags);
515 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); 540 put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
516 err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, 541 err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
517 regs, set->sig[0]); 542 regs, set->sig[0]);
518 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 543 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
519 if (err) 544
520 return -EFAULT; 545 if (ka->sa.sa_flags & SA_RESTORER)
546 restorer = ka->sa.sa_restorer;
547 else
548 restorer = VDSO32_SYMBOL(current->mm->context.vdso,
549 rt_sigreturn);
550 put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
551
552 /*
553 * Not actually used anymore, but left because some gdb
554 * versions need it.
555 */
556 put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
557 } put_user_catch(err);
521 558
522 if (ka->sa.sa_flags & SA_RESTORER)
523 restorer = ka->sa.sa_restorer;
524 else
525 restorer = VDSO32_SYMBOL(current->mm->context.vdso,
526 rt_sigreturn);
527 err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
528
529 /*
530 * Not actually used anymore, but left because some gdb
531 * versions need it.
532 */
533 err |= __put_user(*((u64 *)&code), (u64 *)frame->retcode);
534 if (err) 559 if (err)
535 return -EFAULT; 560 return -EFAULT;
536 561