diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-02-09 18:40:48 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-02-09 18:40:48 -0500 |
commit | 5d96218b4a5ee0c5ff0ac87f3ba90cfa86ca0ca1 (patch) | |
tree | a67a6a4499a235a2aab53a61bf1badff484bc345 /arch/x86/ia32 | |
parent | 249d51b53aea1b7cdb1be65a1a9a0c59d9e06f3e (diff) | |
parent | 18114f61359ac05e3aa797d53d63f40db41f798d (diff) |
Merge branch 'x86/uaccess' into core/percpu
Diffstat (limited to 'arch/x86/ia32')
-rw-r--r-- | arch/x86/ia32/ia32_signal.c | 365 |
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 | ||
47 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) | 47 | int 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 | ||
105 | int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) | 108 | int 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 | ||