diff options
Diffstat (limited to 'arch/frv/kernel/signal.c')
-rw-r--r-- | arch/frv/kernel/signal.c | 112 |
1 files changed, 42 insertions, 70 deletions
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index d822700d4f15..dc3d59de0870 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c | |||
@@ -158,19 +158,10 @@ static int setup_sigcontext(struct sigcontext __user *sc, unsigned long mask) | |||
158 | /* | 158 | /* |
159 | * Determine which stack to use.. | 159 | * Determine which stack to use.. |
160 | */ | 160 | */ |
161 | static inline void __user *get_sigframe(struct k_sigaction *ka, | 161 | static inline void __user *get_sigframe(struct ksignal *ksig, |
162 | size_t frame_size) | 162 | size_t frame_size) |
163 | { | 163 | { |
164 | unsigned long sp; | 164 | unsigned long sp = sigsp(__frame->sp, ksig); |
165 | |||
166 | /* Default to using normal stack */ | ||
167 | sp = __frame->sp; | ||
168 | |||
169 | /* This is the X/Open sanctioned signal stack switching. */ | ||
170 | if (ka->sa.sa_flags & SA_ONSTACK) { | ||
171 | if (! sas_ss_flags(sp)) | ||
172 | sp = current->sas_ss_sp + current->sas_ss_size; | ||
173 | } | ||
174 | 165 | ||
175 | return (void __user *) ((sp - frame_size) & ~7UL); | 166 | return (void __user *) ((sp - frame_size) & ~7UL); |
176 | 167 | ||
@@ -180,17 +171,17 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, | |||
180 | /* | 171 | /* |
181 | * | 172 | * |
182 | */ | 173 | */ |
183 | static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) | 174 | static int setup_frame(struct ksignal *ksig, sigset_t *set) |
184 | { | 175 | { |
185 | struct sigframe __user *frame; | 176 | struct sigframe __user *frame; |
186 | int rsig; | 177 | int rsig, sig = ksig->sig; |
187 | 178 | ||
188 | set_fs(USER_DS); | 179 | set_fs(USER_DS); |
189 | 180 | ||
190 | frame = get_sigframe(ka, sizeof(*frame)); | 181 | frame = get_sigframe(ksig, sizeof(*frame)); |
191 | 182 | ||
192 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 183 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
193 | goto give_sigsegv; | 184 | return -EFAULT; |
194 | 185 | ||
195 | rsig = sig; | 186 | rsig = sig; |
196 | if (sig < 32 && | 187 | if (sig < 32 && |
@@ -199,22 +190,22 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) | |||
199 | rsig = __current_thread_info->exec_domain->signal_invmap[sig]; | 190 | rsig = __current_thread_info->exec_domain->signal_invmap[sig]; |
200 | 191 | ||
201 | if (__put_user(rsig, &frame->sig) < 0) | 192 | if (__put_user(rsig, &frame->sig) < 0) |
202 | goto give_sigsegv; | 193 | return -EFAULT; |
203 | 194 | ||
204 | if (setup_sigcontext(&frame->sc, set->sig[0])) | 195 | if (setup_sigcontext(&frame->sc, set->sig[0])) |
205 | goto give_sigsegv; | 196 | return -EFAULT; |
206 | 197 | ||
207 | if (_NSIG_WORDS > 1) { | 198 | if (_NSIG_WORDS > 1) { |
208 | if (__copy_to_user(frame->extramask, &set->sig[1], | 199 | if (__copy_to_user(frame->extramask, &set->sig[1], |
209 | sizeof(frame->extramask))) | 200 | sizeof(frame->extramask))) |
210 | goto give_sigsegv; | 201 | return -EFAULT; |
211 | } | 202 | } |
212 | 203 | ||
213 | /* Set up to return from userspace. If provided, use a stub | 204 | /* Set up to return from userspace. If provided, use a stub |
214 | * already in userspace. */ | 205 | * already in userspace. */ |
215 | if (ka->sa.sa_flags & SA_RESTORER) { | 206 | if (ksig->ka.sa.sa_flags & SA_RESTORER) { |
216 | if (__put_user(ka->sa.sa_restorer, &frame->pretcode) < 0) | 207 | if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode) < 0) |
217 | goto give_sigsegv; | 208 | return -EFAULT; |
218 | } | 209 | } |
219 | else { | 210 | else { |
220 | /* Set up the following code on the stack: | 211 | /* Set up the following code on the stack: |
@@ -224,7 +215,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) | |||
224 | if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) || | 215 | if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) || |
225 | __put_user(0x8efc0000|__NR_sigreturn, &frame->retcode[0]) || | 216 | __put_user(0x8efc0000|__NR_sigreturn, &frame->retcode[0]) || |
226 | __put_user(0xc0700000, &frame->retcode[1])) | 217 | __put_user(0xc0700000, &frame->retcode[1])) |
227 | goto give_sigsegv; | 218 | return -EFAULT; |
228 | 219 | ||
229 | flush_icache_range((unsigned long) frame->retcode, | 220 | flush_icache_range((unsigned long) frame->retcode, |
230 | (unsigned long) (frame->retcode + 2)); | 221 | (unsigned long) (frame->retcode + 2)); |
@@ -233,14 +224,14 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) | |||
233 | /* Set up registers for the signal handler */ | 224 | /* Set up registers for the signal handler */ |
234 | if (current->personality & FDPIC_FUNCPTRS) { | 225 | if (current->personality & FDPIC_FUNCPTRS) { |
235 | struct fdpic_func_descriptor __user *funcptr = | 226 | struct fdpic_func_descriptor __user *funcptr = |
236 | (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; | 227 | (struct fdpic_func_descriptor __user *) ksig->ka.sa.sa_handler; |
237 | struct fdpic_func_descriptor desc; | 228 | struct fdpic_func_descriptor desc; |
238 | if (copy_from_user(&desc, funcptr, sizeof(desc))) | 229 | if (copy_from_user(&desc, funcptr, sizeof(desc))) |
239 | goto give_sigsegv; | 230 | return -EFAULT; |
240 | __frame->pc = desc.text; | 231 | __frame->pc = desc.text; |
241 | __frame->gr15 = desc.GOT; | 232 | __frame->gr15 = desc.GOT; |
242 | } else { | 233 | } else { |
243 | __frame->pc = (unsigned long) ka->sa.sa_handler; | 234 | __frame->pc = (unsigned long) ksig->ka.sa.sa_handler; |
244 | __frame->gr15 = 0; | 235 | __frame->gr15 = 0; |
245 | } | 236 | } |
246 | 237 | ||
@@ -255,29 +246,23 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) | |||
255 | #endif | 246 | #endif |
256 | 247 | ||
257 | return 0; | 248 | return 0; |
258 | |||
259 | give_sigsegv: | ||
260 | force_sigsegv(sig, current); | ||
261 | return -EFAULT; | ||
262 | |||
263 | } /* end setup_frame() */ | 249 | } /* end setup_frame() */ |
264 | 250 | ||
265 | /*****************************************************************************/ | 251 | /*****************************************************************************/ |
266 | /* | 252 | /* |
267 | * | 253 | * |
268 | */ | 254 | */ |
269 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 255 | static int setup_rt_frame(struct ksignal *ksig, sigset_t *set) |
270 | sigset_t *set) | ||
271 | { | 256 | { |
272 | struct rt_sigframe __user *frame; | 257 | struct rt_sigframe __user *frame; |
273 | int rsig; | 258 | int rsig, sig = ksig->sig; |
274 | 259 | ||
275 | set_fs(USER_DS); | 260 | set_fs(USER_DS); |
276 | 261 | ||
277 | frame = get_sigframe(ka, sizeof(*frame)); | 262 | frame = get_sigframe(ksig, sizeof(*frame)); |
278 | 263 | ||
279 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 264 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
280 | goto give_sigsegv; | 265 | return -EFAULT; |
281 | 266 | ||
282 | rsig = sig; | 267 | rsig = sig; |
283 | if (sig < 32 && | 268 | if (sig < 32 && |
@@ -288,28 +273,28 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
288 | if (__put_user(rsig, &frame->sig) || | 273 | if (__put_user(rsig, &frame->sig) || |
289 | __put_user(&frame->info, &frame->pinfo) || | 274 | __put_user(&frame->info, &frame->pinfo) || |
290 | __put_user(&frame->uc, &frame->puc)) | 275 | __put_user(&frame->uc, &frame->puc)) |
291 | goto give_sigsegv; | 276 | return -EFAULT; |
292 | 277 | ||
293 | if (copy_siginfo_to_user(&frame->info, info)) | 278 | if (copy_siginfo_to_user(&frame->info, &ksig->info)) |
294 | goto give_sigsegv; | 279 | return -EFAULT; |
295 | 280 | ||
296 | /* Create the ucontext. */ | 281 | /* Create the ucontext. */ |
297 | if (__put_user(0, &frame->uc.uc_flags) || | 282 | if (__put_user(0, &frame->uc.uc_flags) || |
298 | __put_user(NULL, &frame->uc.uc_link) || | 283 | __put_user(NULL, &frame->uc.uc_link) || |
299 | __save_altstack(&frame->uc.uc_stack, __frame->sp)) | 284 | __save_altstack(&frame->uc.uc_stack, __frame->sp)) |
300 | goto give_sigsegv; | 285 | return -EFAULT; |
301 | 286 | ||
302 | if (setup_sigcontext(&frame->uc.uc_mcontext, set->sig[0])) | 287 | if (setup_sigcontext(&frame->uc.uc_mcontext, set->sig[0])) |
303 | goto give_sigsegv; | 288 | return -EFAULT; |
304 | 289 | ||
305 | if (__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set))) | 290 | if (__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set))) |
306 | goto give_sigsegv; | 291 | return -EFAULT; |
307 | 292 | ||
308 | /* Set up to return from userspace. If provided, use a stub | 293 | /* Set up to return from userspace. If provided, use a stub |
309 | * already in userspace. */ | 294 | * already in userspace. */ |
310 | if (ka->sa.sa_flags & SA_RESTORER) { | 295 | if (ksig->ka.sa.sa_flags & SA_RESTORER) { |
311 | if (__put_user(ka->sa.sa_restorer, &frame->pretcode)) | 296 | if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode)) |
312 | goto give_sigsegv; | 297 | return -EFAULT; |
313 | } | 298 | } |
314 | else { | 299 | else { |
315 | /* Set up the following code on the stack: | 300 | /* Set up the following code on the stack: |
@@ -319,7 +304,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
319 | if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) || | 304 | if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) || |
320 | __put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) || | 305 | __put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) || |
321 | __put_user(0xc0700000, &frame->retcode[1])) | 306 | __put_user(0xc0700000, &frame->retcode[1])) |
322 | goto give_sigsegv; | 307 | return -EFAULT; |
323 | 308 | ||
324 | flush_icache_range((unsigned long) frame->retcode, | 309 | flush_icache_range((unsigned long) frame->retcode, |
325 | (unsigned long) (frame->retcode + 2)); | 310 | (unsigned long) (frame->retcode + 2)); |
@@ -328,14 +313,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
328 | /* Set up registers for signal handler */ | 313 | /* Set up registers for signal handler */ |
329 | if (current->personality & FDPIC_FUNCPTRS) { | 314 | if (current->personality & FDPIC_FUNCPTRS) { |
330 | struct fdpic_func_descriptor __user *funcptr = | 315 | struct fdpic_func_descriptor __user *funcptr = |
331 | (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; | 316 | (struct fdpic_func_descriptor __user *) ksig->ka.sa.sa_handler; |
332 | struct fdpic_func_descriptor desc; | 317 | struct fdpic_func_descriptor desc; |
333 | if (copy_from_user(&desc, funcptr, sizeof(desc))) | 318 | if (copy_from_user(&desc, funcptr, sizeof(desc))) |
334 | goto give_sigsegv; | 319 | return -EFAULT; |
335 | __frame->pc = desc.text; | 320 | __frame->pc = desc.text; |
336 | __frame->gr15 = desc.GOT; | 321 | __frame->gr15 = desc.GOT; |
337 | } else { | 322 | } else { |
338 | __frame->pc = (unsigned long) ka->sa.sa_handler; | 323 | __frame->pc = (unsigned long) ksig->ka.sa.sa_handler; |
339 | __frame->gr15 = 0; | 324 | __frame->gr15 = 0; |
340 | } | 325 | } |
341 | 326 | ||
@@ -349,21 +334,15 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
349 | sig, current->comm, current->pid, frame, __frame->pc, | 334 | sig, current->comm, current->pid, frame, __frame->pc, |
350 | frame->pretcode); | 335 | frame->pretcode); |
351 | #endif | 336 | #endif |
352 | |||
353 | return 0; | 337 | return 0; |
354 | 338 | ||
355 | give_sigsegv: | ||
356 | force_sigsegv(sig, current); | ||
357 | return -EFAULT; | ||
358 | |||
359 | } /* end setup_rt_frame() */ | 339 | } /* end setup_rt_frame() */ |
360 | 340 | ||
361 | /*****************************************************************************/ | 341 | /*****************************************************************************/ |
362 | /* | 342 | /* |
363 | * OK, we're invoking a handler | 343 | * OK, we're invoking a handler |
364 | */ | 344 | */ |
365 | static void handle_signal(unsigned long sig, siginfo_t *info, | 345 | static void handle_signal(struct ksignal *ksig) |
366 | struct k_sigaction *ka) | ||
367 | { | 346 | { |
368 | sigset_t *oldset = sigmask_to_save(); | 347 | sigset_t *oldset = sigmask_to_save(); |
369 | int ret; | 348 | int ret; |
@@ -378,7 +357,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info, | |||
378 | break; | 357 | break; |
379 | 358 | ||
380 | case -ERESTARTSYS: | 359 | case -ERESTARTSYS: |
381 | if (!(ka->sa.sa_flags & SA_RESTART)) { | 360 | if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { |
382 | __frame->gr8 = -EINTR; | 361 | __frame->gr8 = -EINTR; |
383 | break; | 362 | break; |
384 | } | 363 | } |
@@ -392,16 +371,12 @@ static void handle_signal(unsigned long sig, siginfo_t *info, | |||
392 | } | 371 | } |
393 | 372 | ||
394 | /* Set up the stack frame */ | 373 | /* Set up the stack frame */ |
395 | if (ka->sa.sa_flags & SA_SIGINFO) | 374 | if (ksig->ka.sa.sa_flags & SA_SIGINFO) |
396 | ret = setup_rt_frame(sig, ka, info, oldset); | 375 | ret = setup_rt_frame(ksig, oldset); |
397 | else | 376 | else |
398 | ret = setup_frame(sig, ka, oldset); | 377 | ret = setup_frame(ksig, oldset); |
399 | |||
400 | if (ret) | ||
401 | return; | ||
402 | 378 | ||
403 | signal_delivered(sig, info, ka, __frame, | 379 | signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP)); |
404 | test_thread_flag(TIF_SINGLESTEP)); | ||
405 | } /* end handle_signal() */ | 380 | } /* end handle_signal() */ |
406 | 381 | ||
407 | /*****************************************************************************/ | 382 | /*****************************************************************************/ |
@@ -412,13 +387,10 @@ static void handle_signal(unsigned long sig, siginfo_t *info, | |||
412 | */ | 387 | */ |
413 | static void do_signal(void) | 388 | static void do_signal(void) |
414 | { | 389 | { |
415 | struct k_sigaction ka; | 390 | struct ksignal ksig; |
416 | siginfo_t info; | ||
417 | int signr; | ||
418 | 391 | ||
419 | signr = get_signal_to_deliver(&info, &ka, __frame, NULL); | 392 | if (get_signal(&ksig)) { |
420 | if (signr > 0) { | 393 | handle_signal(&ksig); |
421 | handle_signal(signr, &info, &ka); | ||
422 | return; | 394 | return; |
423 | } | 395 | } |
424 | 396 | ||