Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 227841
b: refs/heads/master
c: ea52b58
h: refs/heads/master
i:
  227839: 4ee1a4f
v: v3
  • Loading branch information
Al Viro authored and Geert Uytterhoeven committed Jan 7, 2011
1 parent 6398b28 commit 9b90084
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 113 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 90731d7537317ad5d9672187f7a1dff90b29bb12
refs/heads/master: ea52b58ccbda49aeb23eb424ce05bba3cb0bc976
173 changes: 61 additions & 112 deletions trunk/arch/m68k/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,53 +286,33 @@ static inline int rt_restore_fpu_state(struct ucontext __user *uc)
return err;
}

static inline int
restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp,
int *pd0)
static int mangle_kernel_stack(struct pt_regs *regs, int formatvec,
void __user *fp)
{
int fsize, formatvec;
struct sigcontext context;
int err;

/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;

/* get previous context */
if (copy_from_user(&context, usc, sizeof(context)))
goto badframe;

/* restore passed registers */
regs->d1 = context.sc_d1;
regs->a0 = context.sc_a0;
regs->a1 = context.sc_a1;
regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
regs->pc = context.sc_pc;
regs->orig_d0 = -1; /* disable syscall checks */
wrusp(context.sc_usp);
formatvec = context.sc_formatvec;
regs->format = formatvec >> 12;
regs->vector = formatvec & 0xfff;

err = restore_fpu_state(&context);

fsize = frame_extra_sizes[regs->format];
int fsize = frame_extra_sizes[formatvec >> 12];
if (fsize < 0) {
/*
* user process trying to return with weird frame format
*/
#ifdef DEBUG
printk("user process returning with weird frame format\n");
#endif
goto badframe;
return 1;
}
if (!fsize) {
regs->format = formatvec >> 12;
regs->vector = formatvec & 0xfff;
} else {
struct switch_stack *sw = (struct switch_stack *)regs - 1;
unsigned long buf[fsize / 2]; /* yes, twice as much */

/* OK. Make room on the supervisor stack for the extra junk,
* if necessary.
*/
/* that'll make sure that expansion won't crap over data */
if (copy_from_user(buf + fsize / 4, fp, fsize))
return 1;

if (fsize) {
struct switch_stack *sw = (struct switch_stack *)regs - 1;
regs->d0 = context.sc_d0;
/* point of no return */
regs->format = formatvec >> 12;
regs->vector = formatvec & 0xfff;
#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
__asm__ __volatile__
(" movel %0,%/a0\n\t"
Expand All @@ -344,40 +324,60 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u
" lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
" lsrl #2,%1\n\t"
" subql #1,%1\n\t"
"2: movesl %4@+,%2\n\t"
"3: movel %2,%/a0@+\n\t"
/* copy to the gap we'd made */
"2: movel %4@+,%/a0@+\n\t"
" dbra %1,2b\n\t"
" bral ret_from_signal\n"
"4:\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 2b,4b\n"
" .long 3b,4b\n"
".previous"
: /* no outputs, it doesn't ever return */
: "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
"n" (frame_offset), "a" (fp)
"n" (frame_offset), "a" (buf + fsize/4)
: "a0");
#undef frame_offset
/*
* If we ever get here an exception occurred while
* building the above stack-frame.
*/
goto badframe;
}
return 0;
}

*pd0 = context.sc_d0;
return err;
static inline int
restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp)
{
int formatvec;
struct sigcontext context;
int err;

/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;

/* get previous context */
if (copy_from_user(&context, usc, sizeof(context)))
goto badframe;

/* restore passed registers */
regs->d0 = context.sc_d0;
regs->d1 = context.sc_d1;
regs->a0 = context.sc_a0;
regs->a1 = context.sc_a1;
regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
regs->pc = context.sc_pc;
regs->orig_d0 = -1; /* disable syscall checks */
wrusp(context.sc_usp);
formatvec = context.sc_formatvec;

err = restore_fpu_state(&context);

if (err || mangle_kernel_stack(regs, formatvec, fp))
goto badframe;

return 0;

badframe:
return 1;
}

static inline int
rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
struct ucontext __user *uc, int *pd0)
struct ucontext __user *uc)
{
int fsize, temp;
int temp;
greg_t __user *gregs = uc->uc_mcontext.gregs;
unsigned long usp;
int err;
Expand Down Expand Up @@ -411,65 +411,16 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
regs->orig_d0 = -1; /* disable syscall checks */
err |= __get_user(temp, &uc->uc_formatvec);
regs->format = temp >> 12;
regs->vector = temp & 0xfff;

err |= rt_restore_fpu_state(uc);

if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
if (err || do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
goto badframe;

fsize = frame_extra_sizes[regs->format];
if (fsize < 0) {
/*
* user process trying to return with weird frame format
*/
#ifdef DEBUG
printk("user process returning with weird frame format\n");
#endif
if (mangle_kernel_stack(regs, temp, &uc->uc_extra))
goto badframe;
}

/* OK. Make room on the supervisor stack for the extra junk,
* if necessary.
*/

if (fsize) {
#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
__asm__ __volatile__
(" movel %0,%/a0\n\t"
" subl %1,%/a0\n\t" /* make room on stack */
" movel %/a0,%/sp\n\t" /* set stack pointer */
/* move switch_stack and pt_regs */
"1: movel %0@+,%/a0@+\n\t"
" dbra %2,1b\n\t"
" lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
" lsrl #2,%1\n\t"
" subql #1,%1\n\t"
"2: movesl %4@+,%2\n\t"
"3: movel %2,%/a0@+\n\t"
" dbra %1,2b\n\t"
" bral ret_from_signal\n"
"4:\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 2b,4b\n"
" .long 3b,4b\n"
".previous"
: /* no outputs, it doesn't ever return */
: "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
"n" (frame_offset), "a" (&uc->uc_extra)
: "a0");
#undef frame_offset
/*
* If we ever get here an exception occurred while
* building the above stack-frame.
*/
goto badframe;
}

*pd0 = regs->d0;
return err;
return 0;

badframe:
return 1;
Expand All @@ -482,7 +433,6 @@ asmlinkage int do_sigreturn(unsigned long __unused)
unsigned long usp = rdusp();
struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
sigset_t set;
int d0;

if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
Expand All @@ -496,9 +446,9 @@ asmlinkage int do_sigreturn(unsigned long __unused)
current->blocked = set;
recalc_sigpending();

if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0))
if (restore_sigcontext(regs, &frame->sc, frame + 1))
goto badframe;
return d0;
return regs->d0;

badframe:
force_sig(SIGSEGV, current);
Expand All @@ -512,7 +462,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
unsigned long usp = rdusp();
struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
sigset_t set;
int d0;

if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
Expand All @@ -523,9 +472,9 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
current->blocked = set;
recalc_sigpending();

if (rt_restore_ucontext(regs, sw, &frame->uc, &d0))
if (rt_restore_ucontext(regs, sw, &frame->uc))
goto badframe;
return d0;
return regs->d0;

badframe:
force_sig(SIGSEGV, current);
Expand Down

0 comments on commit 9b90084

Please sign in to comment.