aboutsummaryrefslogtreecommitdiffstats
path: root/arch
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
parent249d51b53aea1b7cdb1be65a1a9a0c59d9e06f3e (diff)
parent18114f61359ac05e3aa797d53d63f40db41f798d (diff)
Merge branch 'x86/uaccess' into core/percpu
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/ia32/ia32_signal.c365
-rw-r--r--arch/x86/include/asm/paravirt.h2
-rw-r--r--arch/x86/include/asm/spinlock.h66
-rw-r--r--arch/x86/include/asm/thread_info.h1
-rw-r--r--arch/x86/include/asm/uaccess.h138
-rw-r--r--arch/x86/kernel/io_apic.c34
-rw-r--r--arch/x86/kernel/paravirt-spinlocks.c10
-rw-r--r--arch/x86/kernel/signal.c291
-rw-r--r--arch/x86/mm/extable.c6
9 files changed, 488 insertions, 425 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
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index c85e7475e171..ff691736f5e9 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -1471,8 +1471,6 @@ u64 _paravirt_ident_64(u64);
1471 1471
1472#define paravirt_nop ((void *)_paravirt_nop) 1472#define paravirt_nop ((void *)_paravirt_nop)
1473 1473
1474void paravirt_use_bytelocks(void);
1475
1476#ifdef CONFIG_SMP 1474#ifdef CONFIG_SMP
1477 1475
1478static inline int __raw_spin_is_locked(struct raw_spinlock *lock) 1476static inline int __raw_spin_is_locked(struct raw_spinlock *lock)
diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h
index d17c91981da2..2bd6b111a414 100644
--- a/arch/x86/include/asm/spinlock.h
+++ b/arch/x86/include/asm/spinlock.h
@@ -172,70 +172,8 @@ static inline int __ticket_spin_is_contended(raw_spinlock_t *lock)
172 return (((tmp >> TICKET_SHIFT) - tmp) & ((1 << TICKET_SHIFT) - 1)) > 1; 172 return (((tmp >> TICKET_SHIFT) - tmp) & ((1 << TICKET_SHIFT) - 1)) > 1;
173} 173}
174 174
175#ifdef CONFIG_PARAVIRT 175#ifndef CONFIG_PARAVIRT
176/*
177 * Define virtualization-friendly old-style lock byte lock, for use in
178 * pv_lock_ops if desired.
179 *
180 * This differs from the pre-2.6.24 spinlock by always using xchgb
181 * rather than decb to take the lock; this allows it to use a
182 * zero-initialized lock structure. It also maintains a 1-byte
183 * contention counter, so that we can implement
184 * __byte_spin_is_contended.
185 */
186struct __byte_spinlock {
187 s8 lock;
188 s8 spinners;
189};
190
191static inline int __byte_spin_is_locked(raw_spinlock_t *lock)
192{
193 struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
194 return bl->lock != 0;
195}
196
197static inline int __byte_spin_is_contended(raw_spinlock_t *lock)
198{
199 struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
200 return bl->spinners != 0;
201}
202
203static inline void __byte_spin_lock(raw_spinlock_t *lock)
204{
205 struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
206 s8 val = 1;
207
208 asm("1: xchgb %1, %0\n"
209 " test %1,%1\n"
210 " jz 3f\n"
211 " " LOCK_PREFIX "incb %2\n"
212 "2: rep;nop\n"
213 " cmpb $1, %0\n"
214 " je 2b\n"
215 " " LOCK_PREFIX "decb %2\n"
216 " jmp 1b\n"
217 "3:"
218 : "+m" (bl->lock), "+q" (val), "+m" (bl->spinners): : "memory");
219}
220
221static inline int __byte_spin_trylock(raw_spinlock_t *lock)
222{
223 struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
224 u8 old = 1;
225
226 asm("xchgb %1,%0"
227 : "+m" (bl->lock), "+q" (old) : : "memory");
228 176
229 return old == 0;
230}
231
232static inline void __byte_spin_unlock(raw_spinlock_t *lock)
233{
234 struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
235 smp_wmb();
236 bl->lock = 0;
237}
238#else /* !CONFIG_PARAVIRT */
239static inline int __raw_spin_is_locked(raw_spinlock_t *lock) 177static inline int __raw_spin_is_locked(raw_spinlock_t *lock)
240{ 178{
241 return __ticket_spin_is_locked(lock); 179 return __ticket_spin_is_locked(lock);
@@ -267,7 +205,7 @@ static __always_inline void __raw_spin_lock_flags(raw_spinlock_t *lock,
267 __raw_spin_lock(lock); 205 __raw_spin_lock(lock);
268} 206}
269 207
270#endif /* CONFIG_PARAVIRT */ 208#endif
271 209
272static inline void __raw_spin_unlock_wait(raw_spinlock_t *lock) 210static inline void __raw_spin_unlock_wait(raw_spinlock_t *lock)
273{ 211{
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index b46f8ca007b5..df9d5f78385e 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -40,6 +40,7 @@ struct thread_info {
40 */ 40 */
41 __u8 supervisor_stack[0]; 41 __u8 supervisor_stack[0];
42#endif 42#endif
43 int uaccess_err;
43}; 44};
44 45
45#define INIT_THREAD_INFO(tsk) \ 46#define INIT_THREAD_INFO(tsk) \
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 4340055b7559..b685ece89d5c 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -121,7 +121,7 @@ extern int __get_user_bad(void);
121 121
122#define __get_user_x(size, ret, x, ptr) \ 122#define __get_user_x(size, ret, x, ptr) \
123 asm volatile("call __get_user_" #size \ 123 asm volatile("call __get_user_" #size \
124 : "=a" (ret),"=d" (x) \ 124 : "=a" (ret), "=d" (x) \
125 : "0" (ptr)) \ 125 : "0" (ptr)) \
126 126
127/* Careful: we have to cast the result to the type of the pointer 127/* Careful: we have to cast the result to the type of the pointer
@@ -181,12 +181,12 @@ extern int __get_user_bad(void);
181 181
182#define __put_user_x(size, x, ptr, __ret_pu) \ 182#define __put_user_x(size, x, ptr, __ret_pu) \
183 asm volatile("call __put_user_" #size : "=a" (__ret_pu) \ 183 asm volatile("call __put_user_" #size : "=a" (__ret_pu) \
184 :"0" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx") 184 : "0" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx")
185 185
186 186
187 187
188#ifdef CONFIG_X86_32 188#ifdef CONFIG_X86_32
189#define __put_user_u64(x, addr, err) \ 189#define __put_user_asm_u64(x, addr, err, errret) \
190 asm volatile("1: movl %%eax,0(%2)\n" \ 190 asm volatile("1: movl %%eax,0(%2)\n" \
191 "2: movl %%edx,4(%2)\n" \ 191 "2: movl %%edx,4(%2)\n" \
192 "3:\n" \ 192 "3:\n" \
@@ -197,14 +197,24 @@ extern int __get_user_bad(void);
197 _ASM_EXTABLE(1b, 4b) \ 197 _ASM_EXTABLE(1b, 4b) \
198 _ASM_EXTABLE(2b, 4b) \ 198 _ASM_EXTABLE(2b, 4b) \
199 : "=r" (err) \ 199 : "=r" (err) \
200 : "A" (x), "r" (addr), "i" (-EFAULT), "0" (err)) 200 : "A" (x), "r" (addr), "i" (errret), "0" (err))
201
202#define __put_user_asm_ex_u64(x, addr) \
203 asm volatile("1: movl %%eax,0(%1)\n" \
204 "2: movl %%edx,4(%1)\n" \
205 "3:\n" \
206 _ASM_EXTABLE(1b, 2b - 1b) \
207 _ASM_EXTABLE(2b, 3b - 2b) \
208 : : "A" (x), "r" (addr))
201 209
202#define __put_user_x8(x, ptr, __ret_pu) \ 210#define __put_user_x8(x, ptr, __ret_pu) \
203 asm volatile("call __put_user_8" : "=a" (__ret_pu) \ 211 asm volatile("call __put_user_8" : "=a" (__ret_pu) \
204 : "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx") 212 : "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx")
205#else 213#else
206#define __put_user_u64(x, ptr, retval) \ 214#define __put_user_asm_u64(x, ptr, retval, errret) \
207 __put_user_asm(x, ptr, retval, "q", "", "Zr", -EFAULT) 215 __put_user_asm(x, ptr, retval, "q", "", "Zr", errret)
216#define __put_user_asm_ex_u64(x, addr) \
217 __put_user_asm_ex(x, addr, "q", "", "Zr")
208#define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu) 218#define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu)
209#endif 219#endif
210 220
@@ -276,10 +286,32 @@ do { \
276 __put_user_asm(x, ptr, retval, "w", "w", "ir", errret); \ 286 __put_user_asm(x, ptr, retval, "w", "w", "ir", errret); \
277 break; \ 287 break; \
278 case 4: \ 288 case 4: \
279 __put_user_asm(x, ptr, retval, "l", "k", "ir", errret);\ 289 __put_user_asm(x, ptr, retval, "l", "k", "ir", errret); \
280 break; \ 290 break; \
281 case 8: \ 291 case 8: \
282 __put_user_u64((__typeof__(*ptr))(x), ptr, retval); \ 292 __put_user_asm_u64((__typeof__(*ptr))(x), ptr, retval, \
293 errret); \
294 break; \
295 default: \
296 __put_user_bad(); \
297 } \
298} while (0)
299
300#define __put_user_size_ex(x, ptr, size) \
301do { \
302 __chk_user_ptr(ptr); \
303 switch (size) { \
304 case 1: \
305 __put_user_asm_ex(x, ptr, "b", "b", "iq"); \
306 break; \
307 case 2: \
308 __put_user_asm_ex(x, ptr, "w", "w", "ir"); \
309 break; \
310 case 4: \
311 __put_user_asm_ex(x, ptr, "l", "k", "ir"); \
312 break; \
313 case 8: \
314 __put_user_asm_ex_u64((__typeof__(*ptr))(x), ptr); \
283 break; \ 315 break; \
284 default: \ 316 default: \
285 __put_user_bad(); \ 317 __put_user_bad(); \
@@ -311,9 +343,12 @@ do { \
311 343
312#ifdef CONFIG_X86_32 344#ifdef CONFIG_X86_32
313#define __get_user_asm_u64(x, ptr, retval, errret) (x) = __get_user_bad() 345#define __get_user_asm_u64(x, ptr, retval, errret) (x) = __get_user_bad()
346#define __get_user_asm_ex_u64(x, ptr) (x) = __get_user_bad()
314#else 347#else
315#define __get_user_asm_u64(x, ptr, retval, errret) \ 348#define __get_user_asm_u64(x, ptr, retval, errret) \
316 __get_user_asm(x, ptr, retval, "q", "", "=r", errret) 349 __get_user_asm(x, ptr, retval, "q", "", "=r", errret)
350#define __get_user_asm_ex_u64(x, ptr) \
351 __get_user_asm_ex(x, ptr, "q", "", "=r")
317#endif 352#endif
318 353
319#define __get_user_size(x, ptr, size, retval, errret) \ 354#define __get_user_size(x, ptr, size, retval, errret) \
@@ -350,6 +385,33 @@ do { \
350 : "=r" (err), ltype(x) \ 385 : "=r" (err), ltype(x) \
351 : "m" (__m(addr)), "i" (errret), "0" (err)) 386 : "m" (__m(addr)), "i" (errret), "0" (err))
352 387
388#define __get_user_size_ex(x, ptr, size) \
389do { \
390 __chk_user_ptr(ptr); \
391 switch (size) { \
392 case 1: \
393 __get_user_asm_ex(x, ptr, "b", "b", "=q"); \
394 break; \
395 case 2: \
396 __get_user_asm_ex(x, ptr, "w", "w", "=r"); \
397 break; \
398 case 4: \
399 __get_user_asm_ex(x, ptr, "l", "k", "=r"); \
400 break; \
401 case 8: \
402 __get_user_asm_ex_u64(x, ptr); \
403 break; \
404 default: \
405 (x) = __get_user_bad(); \
406 } \
407} while (0)
408
409#define __get_user_asm_ex(x, addr, itype, rtype, ltype) \
410 asm volatile("1: mov"itype" %1,%"rtype"0\n" \
411 "2:\n" \
412 _ASM_EXTABLE(1b, 2b - 1b) \
413 : ltype(x) : "m" (__m(addr)))
414
353#define __put_user_nocheck(x, ptr, size) \ 415#define __put_user_nocheck(x, ptr, size) \
354({ \ 416({ \
355 int __pu_err; \ 417 int __pu_err; \
@@ -385,6 +447,26 @@ struct __large_struct { unsigned long buf[100]; };
385 _ASM_EXTABLE(1b, 3b) \ 447 _ASM_EXTABLE(1b, 3b) \
386 : "=r"(err) \ 448 : "=r"(err) \
387 : ltype(x), "m" (__m(addr)), "i" (errret), "0" (err)) 449 : ltype(x), "m" (__m(addr)), "i" (errret), "0" (err))
450
451#define __put_user_asm_ex(x, addr, itype, rtype, ltype) \
452 asm volatile("1: mov"itype" %"rtype"0,%1\n" \
453 "2:\n" \
454 _ASM_EXTABLE(1b, 2b - 1b) \
455 : : ltype(x), "m" (__m(addr)))
456
457/*
458 * uaccess_try and catch
459 */
460#define uaccess_try do { \
461 int prev_err = current_thread_info()->uaccess_err; \
462 current_thread_info()->uaccess_err = 0; \
463 barrier();
464
465#define uaccess_catch(err) \
466 (err) |= current_thread_info()->uaccess_err; \
467 current_thread_info()->uaccess_err = prev_err; \
468} while (0)
469
388/** 470/**
389 * __get_user: - Get a simple variable from user space, with less checking. 471 * __get_user: - Get a simple variable from user space, with less checking.
390 * @x: Variable to store result. 472 * @x: Variable to store result.
@@ -408,6 +490,7 @@ struct __large_struct { unsigned long buf[100]; };
408 490
409#define __get_user(x, ptr) \ 491#define __get_user(x, ptr) \
410 __get_user_nocheck((x), (ptr), sizeof(*(ptr))) 492 __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
493
411/** 494/**
412 * __put_user: - Write a simple value into user space, with less checking. 495 * __put_user: - Write a simple value into user space, with less checking.
413 * @x: Value to copy to user space. 496 * @x: Value to copy to user space.
@@ -435,6 +518,45 @@ struct __large_struct { unsigned long buf[100]; };
435#define __put_user_unaligned __put_user 518#define __put_user_unaligned __put_user
436 519
437/* 520/*
521 * {get|put}_user_try and catch
522 *
523 * get_user_try {
524 * get_user_ex(...);
525 * } get_user_catch(err)
526 */
527#define get_user_try uaccess_try
528#define get_user_catch(err) uaccess_catch(err)
529
530#define get_user_ex(x, ptr) do { \
531 unsigned long __gue_val; \
532 __get_user_size_ex((__gue_val), (ptr), (sizeof(*(ptr)))); \
533 (x) = (__force __typeof__(*(ptr)))__gue_val; \
534} while (0)
535
536#ifdef CONFIG_X86_WP_WORKS_OK
537
538#define put_user_try uaccess_try
539#define put_user_catch(err) uaccess_catch(err)
540
541#define put_user_ex(x, ptr) \
542 __put_user_size_ex((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
543
544#else /* !CONFIG_X86_WP_WORKS_OK */
545
546#define put_user_try do { \
547 int __uaccess_err = 0;
548
549#define put_user_catch(err) \
550 (err) |= __uaccess_err; \
551} while (0)
552
553#define put_user_ex(x, ptr) do { \
554 __uaccess_err |= __put_user(x, ptr); \
555} while (0)
556
557#endif /* CONFIG_X86_WP_WORKS_OK */
558
559/*
438 * movsl can be slow when source and dest are not both 8-byte aligned 560 * movsl can be slow when source and dest are not both 8-byte aligned
439 */ 561 */
440#ifdef CONFIG_X86_INTEL_USERCOPY 562#ifdef CONFIG_X86_INTEL_USERCOPY
diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c
index 0a7f6d6b1206..c0498daf01c3 100644
--- a/arch/x86/kernel/io_apic.c
+++ b/arch/x86/kernel/io_apic.c
@@ -3466,40 +3466,6 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
3466 return 0; 3466 return 0;
3467} 3467}
3468 3468
3469int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc)
3470{
3471 unsigned int irq;
3472 int ret;
3473 unsigned int irq_want;
3474
3475 irq_want = nr_irqs_gsi;
3476 irq = create_irq_nr(irq_want);
3477 if (irq == 0)
3478 return -1;
3479
3480#ifdef CONFIG_INTR_REMAP
3481 if (!intr_remapping_enabled)
3482 goto no_ir;
3483
3484 ret = msi_alloc_irte(dev, irq, 1);
3485 if (ret < 0)
3486 goto error;
3487no_ir:
3488#endif
3489 ret = setup_msi_irq(dev, msidesc, irq);
3490 if (ret < 0) {
3491 destroy_irq(irq);
3492 return ret;
3493 }
3494 return 0;
3495
3496#ifdef CONFIG_INTR_REMAP
3497error:
3498 destroy_irq(irq);
3499 return ret;
3500#endif
3501}
3502
3503int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 3469int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
3504{ 3470{
3505 unsigned int irq; 3471 unsigned int irq;
diff --git a/arch/x86/kernel/paravirt-spinlocks.c b/arch/x86/kernel/paravirt-spinlocks.c
index 95777b0faa73..3a7c5a44082e 100644
--- a/arch/x86/kernel/paravirt-spinlocks.c
+++ b/arch/x86/kernel/paravirt-spinlocks.c
@@ -26,13 +26,3 @@ struct pv_lock_ops pv_lock_ops = {
26}; 26};
27EXPORT_SYMBOL(pv_lock_ops); 27EXPORT_SYMBOL(pv_lock_ops);
28 28
29void __init paravirt_use_bytelocks(void)
30{
31#ifdef CONFIG_SMP
32 pv_lock_ops.spin_is_locked = __byte_spin_is_locked;
33 pv_lock_ops.spin_is_contended = __byte_spin_is_contended;
34 pv_lock_ops.spin_lock = __byte_spin_lock;
35 pv_lock_ops.spin_trylock = __byte_spin_trylock;
36 pv_lock_ops.spin_unlock = __byte_spin_unlock;
37#endif
38}
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index df0587f24c54..7fc78b019815 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -51,24 +51,24 @@
51#endif 51#endif
52 52
53#define COPY(x) { \ 53#define COPY(x) { \
54 err |= __get_user(regs->x, &sc->x); \ 54 get_user_ex(regs->x, &sc->x); \
55} 55}
56 56
57#define COPY_SEG(seg) { \ 57#define COPY_SEG(seg) { \
58 unsigned short tmp; \ 58 unsigned short tmp; \
59 err |= __get_user(tmp, &sc->seg); \ 59 get_user_ex(tmp, &sc->seg); \
60 regs->seg = tmp; \ 60 regs->seg = tmp; \
61} 61}
62 62
63#define COPY_SEG_CPL3(seg) { \ 63#define COPY_SEG_CPL3(seg) { \
64 unsigned short tmp; \ 64 unsigned short tmp; \
65 err |= __get_user(tmp, &sc->seg); \ 65 get_user_ex(tmp, &sc->seg); \
66 regs->seg = tmp | 3; \ 66 regs->seg = tmp | 3; \
67} 67}
68 68
69#define GET_SEG(seg) { \ 69#define GET_SEG(seg) { \
70 unsigned short tmp; \ 70 unsigned short tmp; \
71 err |= __get_user(tmp, &sc->seg); \ 71 get_user_ex(tmp, &sc->seg); \
72 loadsegment(seg, tmp); \ 72 loadsegment(seg, tmp); \
73} 73}
74 74
@@ -83,45 +83,49 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
83 /* Always make any pending restarted system calls return -EINTR */ 83 /* Always make any pending restarted system calls return -EINTR */
84 current_thread_info()->restart_block.fn = do_no_restart_syscall; 84 current_thread_info()->restart_block.fn = do_no_restart_syscall;
85 85
86 get_user_try {
87
86#ifdef CONFIG_X86_32 88#ifdef CONFIG_X86_32
87 GET_SEG(gs); 89 GET_SEG(gs);
88 COPY_SEG(fs); 90 COPY_SEG(fs);
89 COPY_SEG(es); 91 COPY_SEG(es);
90 COPY_SEG(ds); 92 COPY_SEG(ds);
91#endif /* CONFIG_X86_32 */ 93#endif /* CONFIG_X86_32 */
92 94
93 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); 95 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
94 COPY(dx); COPY(cx); COPY(ip); 96 COPY(dx); COPY(cx); COPY(ip);
95 97
96#ifdef CONFIG_X86_64 98#ifdef CONFIG_X86_64
97 COPY(r8); 99 COPY(r8);
98 COPY(r9); 100 COPY(r9);
99 COPY(r10); 101 COPY(r10);
100 COPY(r11); 102 COPY(r11);
101 COPY(r12); 103 COPY(r12);
102 COPY(r13); 104 COPY(r13);
103 COPY(r14); 105 COPY(r14);
104 COPY(r15); 106 COPY(r15);
105#endif /* CONFIG_X86_64 */ 107#endif /* CONFIG_X86_64 */
106 108
107#ifdef CONFIG_X86_32 109#ifdef CONFIG_X86_32
108 COPY_SEG_CPL3(cs); 110 COPY_SEG_CPL3(cs);
109 COPY_SEG_CPL3(ss); 111 COPY_SEG_CPL3(ss);
110#else /* !CONFIG_X86_32 */ 112#else /* !CONFIG_X86_32 */
111 /* Kernel saves and restores only the CS segment register on signals, 113 /* Kernel saves and restores only the CS segment register on signals,
112 * which is the bare minimum needed to allow mixed 32/64-bit code. 114 * which is the bare minimum needed to allow mixed 32/64-bit code.
113 * App's signal handler can save/restore other segments if needed. */ 115 * App's signal handler can save/restore other segments if needed. */
114 COPY_SEG_CPL3(cs); 116 COPY_SEG_CPL3(cs);
115#endif /* CONFIG_X86_32 */ 117#endif /* CONFIG_X86_32 */
116 118
117 err |= __get_user(tmpflags, &sc->flags); 119 get_user_ex(tmpflags, &sc->flags);
118 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); 120 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
119 regs->orig_ax = -1; /* disable syscall checks */ 121 regs->orig_ax = -1; /* disable syscall checks */
122
123 get_user_ex(buf, &sc->fpstate);
124 err |= restore_i387_xstate(buf);
120 125
121 err |= __get_user(buf, &sc->fpstate); 126 get_user_ex(*pax, &sc->ax);
122 err |= restore_i387_xstate(buf); 127 } get_user_catch(err);
123 128
124 err |= __get_user(*pax, &sc->ax);
125 return err; 129 return err;
126} 130}
127 131
@@ -131,57 +135,60 @@ setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
131{ 135{
132 int err = 0; 136 int err = 0;
133 137
138 put_user_try {
139
134#ifdef CONFIG_X86_32 140#ifdef CONFIG_X86_32
135 { 141 {
136 unsigned int tmp; 142 unsigned int tmp;
137 143
138 savesegment(gs, tmp); 144 savesegment(gs, tmp);
139 err |= __put_user(tmp, (unsigned int __user *)&sc->gs); 145 put_user_ex(tmp, (unsigned int __user *)&sc->gs);
140 } 146 }
141 err |= __put_user(regs->fs, (unsigned int __user *)&sc->fs); 147 put_user_ex(regs->fs, (unsigned int __user *)&sc->fs);
142 err |= __put_user(regs->es, (unsigned int __user *)&sc->es); 148 put_user_ex(regs->es, (unsigned int __user *)&sc->es);
143 err |= __put_user(regs->ds, (unsigned int __user *)&sc->ds); 149 put_user_ex(regs->ds, (unsigned int __user *)&sc->ds);
144#endif /* CONFIG_X86_32 */ 150#endif /* CONFIG_X86_32 */
145 151
146 err |= __put_user(regs->di, &sc->di); 152 put_user_ex(regs->di, &sc->di);
147 err |= __put_user(regs->si, &sc->si); 153 put_user_ex(regs->si, &sc->si);
148 err |= __put_user(regs->bp, &sc->bp); 154 put_user_ex(regs->bp, &sc->bp);
149 err |= __put_user(regs->sp, &sc->sp); 155 put_user_ex(regs->sp, &sc->sp);
150 err |= __put_user(regs->bx, &sc->bx); 156 put_user_ex(regs->bx, &sc->bx);
151 err |= __put_user(regs->dx, &sc->dx); 157 put_user_ex(regs->dx, &sc->dx);
152 err |= __put_user(regs->cx, &sc->cx); 158 put_user_ex(regs->cx, &sc->cx);
153 err |= __put_user(regs->ax, &sc->ax); 159 put_user_ex(regs->ax, &sc->ax);
154#ifdef CONFIG_X86_64 160#ifdef CONFIG_X86_64
155 err |= __put_user(regs->r8, &sc->r8); 161 put_user_ex(regs->r8, &sc->r8);
156 err |= __put_user(regs->r9, &sc->r9); 162 put_user_ex(regs->r9, &sc->r9);
157 err |= __put_user(regs->r10, &sc->r10); 163 put_user_ex(regs->r10, &sc->r10);
158 err |= __put_user(regs->r11, &sc->r11); 164 put_user_ex(regs->r11, &sc->r11);
159 err |= __put_user(regs->r12, &sc->r12); 165 put_user_ex(regs->r12, &sc->r12);
160 err |= __put_user(regs->r13, &sc->r13); 166 put_user_ex(regs->r13, &sc->r13);
161 err |= __put_user(regs->r14, &sc->r14); 167 put_user_ex(regs->r14, &sc->r14);
162 err |= __put_user(regs->r15, &sc->r15); 168 put_user_ex(regs->r15, &sc->r15);
163#endif /* CONFIG_X86_64 */ 169#endif /* CONFIG_X86_64 */
164 170
165 err |= __put_user(current->thread.trap_no, &sc->trapno); 171 put_user_ex(current->thread.trap_no, &sc->trapno);
166 err |= __put_user(current->thread.error_code, &sc->err); 172 put_user_ex(current->thread.error_code, &sc->err);
167 err |= __put_user(regs->ip, &sc->ip); 173 put_user_ex(regs->ip, &sc->ip);
168#ifdef CONFIG_X86_32 174#ifdef CONFIG_X86_32
169 err |= __put_user(regs->cs, (unsigned int __user *)&sc->cs); 175 put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
170 err |= __put_user(regs->flags, &sc->flags); 176 put_user_ex(regs->flags, &sc->flags);
171 err |= __put_user(regs->sp, &sc->sp_at_signal); 177 put_user_ex(regs->sp, &sc->sp_at_signal);
172 err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss); 178 put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
173#else /* !CONFIG_X86_32 */ 179#else /* !CONFIG_X86_32 */
174 err |= __put_user(regs->flags, &sc->flags); 180 put_user_ex(regs->flags, &sc->flags);
175 err |= __put_user(regs->cs, &sc->cs); 181 put_user_ex(regs->cs, &sc->cs);
176 err |= __put_user(0, &sc->gs); 182 put_user_ex(0, &sc->gs);
177 err |= __put_user(0, &sc->fs); 183 put_user_ex(0, &sc->fs);
178#endif /* CONFIG_X86_32 */ 184#endif /* CONFIG_X86_32 */
179 185
180 err |= __put_user(fpstate, &sc->fpstate); 186 put_user_ex(fpstate, &sc->fpstate);
181 187
182 /* non-iBCS2 extensions.. */ 188 /* non-iBCS2 extensions.. */
183 err |= __put_user(mask, &sc->oldmask); 189 put_user_ex(mask, &sc->oldmask);
184 err |= __put_user(current->thread.cr2, &sc->cr2); 190 put_user_ex(current->thread.cr2, &sc->cr2);
191 } put_user_catch(err);
185 192
186 return err; 193 return err;
187} 194}
@@ -336,43 +343,41 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
336 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 343 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
337 return -EFAULT; 344 return -EFAULT;
338 345
339 err |= __put_user(sig, &frame->sig); 346 put_user_try {
340 err |= __put_user(&frame->info, &frame->pinfo); 347 put_user_ex(sig, &frame->sig);
341 err |= __put_user(&frame->uc, &frame->puc); 348 put_user_ex(&frame->info, &frame->pinfo);
342 err |= copy_siginfo_to_user(&frame->info, info); 349 put_user_ex(&frame->uc, &frame->puc);
343 if (err) 350 err |= copy_siginfo_to_user(&frame->info, info);
344 return -EFAULT;
345
346 /* Create the ucontext. */
347 if (cpu_has_xsave)
348 err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags);
349 else
350 err |= __put_user(0, &frame->uc.uc_flags);
351 err |= __put_user(0, &frame->uc.uc_link);
352 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
353 err |= __put_user(sas_ss_flags(regs->sp),
354 &frame->uc.uc_stack.ss_flags);
355 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
356 err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
357 regs, set->sig[0]);
358 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
359 if (err)
360 return -EFAULT;
361 351
362 /* Set up to return from userspace. */ 352 /* Create the ucontext. */
363 restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); 353 if (cpu_has_xsave)
364 if (ka->sa.sa_flags & SA_RESTORER) 354 put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
365 restorer = ka->sa.sa_restorer; 355 else
366 err |= __put_user(restorer, &frame->pretcode); 356 put_user_ex(0, &frame->uc.uc_flags);
357 put_user_ex(0, &frame->uc.uc_link);
358 put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
359 put_user_ex(sas_ss_flags(regs->sp),
360 &frame->uc.uc_stack.ss_flags);
361 put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
362 err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
363 regs, set->sig[0]);
364 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
365
366 /* Set up to return from userspace. */
367 restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn);
368 if (ka->sa.sa_flags & SA_RESTORER)
369 restorer = ka->sa.sa_restorer;
370 put_user_ex(restorer, &frame->pretcode);
367 371
368 /* 372 /*
369 * This is movl $__NR_rt_sigreturn, %ax ; int $0x80 373 * This is movl $__NR_rt_sigreturn, %ax ; int $0x80
370 * 374 *
371 * WE DO NOT USE IT ANY MORE! It's only left here for historical 375 * WE DO NOT USE IT ANY MORE! It's only left here for historical
372 * reasons and because gdb uses it as a signature to notice 376 * reasons and because gdb uses it as a signature to notice
373 * signal handler stack frames. 377 * signal handler stack frames.
374 */ 378 */
375 err |= __put_user(*((u64 *)&rt_retcode), (u64 *)frame->retcode); 379 put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
380 } put_user_catch(err);
376 381
377 if (err) 382 if (err)
378 return -EFAULT; 383 return -EFAULT;
@@ -436,28 +441,30 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
436 return -EFAULT; 441 return -EFAULT;
437 } 442 }
438 443
439 /* Create the ucontext. */ 444 put_user_try {
440 if (cpu_has_xsave) 445 /* Create the ucontext. */
441 err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); 446 if (cpu_has_xsave)
442 else 447 put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
443 err |= __put_user(0, &frame->uc.uc_flags); 448 else
444 err |= __put_user(0, &frame->uc.uc_link); 449 put_user_ex(0, &frame->uc.uc_flags);
445 err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); 450 put_user_ex(0, &frame->uc.uc_link);
446 err |= __put_user(sas_ss_flags(regs->sp), 451 put_user_ex(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
447 &frame->uc.uc_stack.ss_flags); 452 put_user_ex(sas_ss_flags(regs->sp),
448 err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); 453 &frame->uc.uc_stack.ss_flags);
449 err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); 454 put_user_ex(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
450 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 455 err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]);
451 456 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
452 /* Set up to return from userspace. If provided, use a stub 457
453 already in userspace. */ 458 /* Set up to return from userspace. If provided, use a stub
454 /* x86-64 should always use SA_RESTORER. */ 459 already in userspace. */
455 if (ka->sa.sa_flags & SA_RESTORER) { 460 /* x86-64 should always use SA_RESTORER. */
456 err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); 461 if (ka->sa.sa_flags & SA_RESTORER) {
457 } else { 462 put_user_ex(ka->sa.sa_restorer, &frame->pretcode);
458 /* could use a vstub here */ 463 } else {
459 return -EFAULT; 464 /* could use a vstub here */
460 } 465 err |= -EFAULT;
466 }
467 } put_user_catch(err);
461 468
462 if (err) 469 if (err)
463 return -EFAULT; 470 return -EFAULT;
@@ -509,31 +516,41 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
509 struct old_sigaction __user *oact) 516 struct old_sigaction __user *oact)
510{ 517{
511 struct k_sigaction new_ka, old_ka; 518 struct k_sigaction new_ka, old_ka;
512 int ret; 519 int ret = 0;
513 520
514 if (act) { 521 if (act) {
515 old_sigset_t mask; 522 old_sigset_t mask;
516 523
517 if (!access_ok(VERIFY_READ, act, sizeof(*act)) || 524 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
518 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
519 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
520 return -EFAULT; 525 return -EFAULT;
521 526
522 __get_user(new_ka.sa.sa_flags, &act->sa_flags); 527 get_user_try {
523 __get_user(mask, &act->sa_mask); 528 get_user_ex(new_ka.sa.sa_handler, &act->sa_handler);
529 get_user_ex(new_ka.sa.sa_flags, &act->sa_flags);
530 get_user_ex(mask, &act->sa_mask);
531 get_user_ex(new_ka.sa.sa_restorer, &act->sa_restorer);
532 } get_user_catch(ret);
533
534 if (ret)
535 return -EFAULT;
524 siginitset(&new_ka.sa.sa_mask, mask); 536 siginitset(&new_ka.sa.sa_mask, mask);
525 } 537 }
526 538
527 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); 539 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
528 540
529 if (!ret && oact) { 541 if (!ret && oact) {
530 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || 542 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
531 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
532 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
533 return -EFAULT; 543 return -EFAULT;
534 544
535 __put_user(old_ka.sa.sa_flags, &oact->sa_flags); 545 put_user_try {
536 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); 546 put_user_ex(old_ka.sa.sa_handler, &oact->sa_handler);
547 put_user_ex(old_ka.sa.sa_flags, &oact->sa_flags);
548 put_user_ex(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
549 put_user_ex(old_ka.sa.sa_restorer, &oact->sa_restorer);
550 } put_user_catch(ret);
551
552 if (ret)
553 return -EFAULT;
537 } 554 }
538 555
539 return ret; 556 return ret;
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index 7e8db53528a7..61b41ca3b5a2 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -23,6 +23,12 @@ int fixup_exception(struct pt_regs *regs)
23 23
24 fixup = search_exception_tables(regs->ip); 24 fixup = search_exception_tables(regs->ip);
25 if (fixup) { 25 if (fixup) {
26 /* If fixup is less than 16, it means uaccess error */
27 if (fixup->fixup < 16) {
28 current_thread_info()->uaccess_err = -EFAULT;
29 regs->ip += fixup->fixup;
30 return 1;
31 }
26 regs->ip = fixup->fixup; 32 regs->ip = fixup->fixup;
27 return 1; 33 return 1;
28 } 34 }