mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-13 14:04:05 +08:00
x86: get rid of get_user_ex() in ia32_restore_sigcontext()
Just do copyin into a local struct and be done with that - we are on a shallow stack here. [reworked by tglx, removing the macro horrors while we are touching that] Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
c63aad695d
commit
978727ca33
@ -36,70 +36,56 @@
|
||||
#include <asm/sighandling.h>
|
||||
#include <asm/smap.h>
|
||||
|
||||
static inline void reload_segments(struct sigcontext_32 *sc)
|
||||
{
|
||||
unsigned int cur;
|
||||
|
||||
savesegment(gs, cur);
|
||||
if ((sc->gs | 0x03) != cur)
|
||||
load_gs_index(sc->gs | 0x03);
|
||||
savesegment(fs, cur);
|
||||
if ((sc->fs | 0x03) != cur)
|
||||
loadsegment(fs, sc->fs | 0x03);
|
||||
savesegment(ds, cur);
|
||||
if ((sc->ds | 0x03) != cur)
|
||||
loadsegment(ds, sc->ds | 0x03);
|
||||
savesegment(es, cur);
|
||||
if ((sc->es | 0x03) != cur)
|
||||
loadsegment(es, sc->es | 0x03);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a signal return; undo the signal stack.
|
||||
*/
|
||||
#define loadsegment_gs(v) load_gs_index(v)
|
||||
#define loadsegment_fs(v) loadsegment(fs, v)
|
||||
#define loadsegment_ds(v) loadsegment(ds, v)
|
||||
#define loadsegment_es(v) loadsegment(es, v)
|
||||
|
||||
#define get_user_seg(seg) ({ unsigned int v; savesegment(seg, v); v; })
|
||||
#define set_user_seg(seg, v) loadsegment_##seg(v)
|
||||
|
||||
#define COPY(x) { \
|
||||
get_user_ex(regs->x, &sc->x); \
|
||||
}
|
||||
|
||||
#define GET_SEG(seg) ({ \
|
||||
unsigned short tmp; \
|
||||
get_user_ex(tmp, &sc->seg); \
|
||||
tmp; \
|
||||
})
|
||||
|
||||
#define COPY_SEG_CPL3(seg) do { \
|
||||
regs->seg = GET_SEG(seg) | 3; \
|
||||
} while (0)
|
||||
|
||||
#define RELOAD_SEG(seg) { \
|
||||
unsigned int pre = (seg) | 3; \
|
||||
unsigned int cur = get_user_seg(seg); \
|
||||
if (pre != cur) \
|
||||
set_user_seg(seg, pre); \
|
||||
}
|
||||
|
||||
static int ia32_restore_sigcontext(struct pt_regs *regs,
|
||||
struct sigcontext_32 __user *sc)
|
||||
struct sigcontext_32 __user *usc)
|
||||
{
|
||||
unsigned int tmpflags, err = 0;
|
||||
u16 gs, fs, es, ds;
|
||||
void __user *buf;
|
||||
u32 tmp;
|
||||
struct sigcontext_32 sc;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
get_user_try {
|
||||
gs = GET_SEG(gs);
|
||||
fs = GET_SEG(fs);
|
||||
ds = GET_SEG(ds);
|
||||
es = GET_SEG(es);
|
||||
if (unlikely(copy_from_user(&sc, usc, sizeof(sc))))
|
||||
return -EFAULT;
|
||||
|
||||
COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
|
||||
COPY(dx); COPY(cx); COPY(ip); COPY(ax);
|
||||
/* Don't touch extended registers */
|
||||
/* Get only the ia32 registers. */
|
||||
regs->bx = sc.bx;
|
||||
regs->cx = sc.cx;
|
||||
regs->dx = sc.dx;
|
||||
regs->si = sc.si;
|
||||
regs->di = sc.di;
|
||||
regs->bp = sc.bp;
|
||||
regs->ax = sc.ax;
|
||||
regs->sp = sc.sp;
|
||||
regs->ip = sc.ip;
|
||||
|
||||
COPY_SEG_CPL3(cs);
|
||||
COPY_SEG_CPL3(ss);
|
||||
/* Get CS/SS and force CPL3 */
|
||||
regs->cs = sc.cs | 0x03;
|
||||
regs->ss = sc.ss | 0x03;
|
||||
|
||||
get_user_ex(tmpflags, &sc->flags);
|
||||
regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
|
||||
/* disable syscall checks */
|
||||
regs->orig_ax = -1;
|
||||
|
||||
get_user_ex(tmp, &sc->fpstate);
|
||||
buf = compat_ptr(tmp);
|
||||
} get_user_catch(err);
|
||||
regs->flags = (regs->flags & ~FIX_EFLAGS) | (sc.flags & FIX_EFLAGS);
|
||||
/* disable syscall checks */
|
||||
regs->orig_ax = -1;
|
||||
|
||||
/*
|
||||
* Reload fs and gs if they have changed in the signal
|
||||
@ -107,14 +93,8 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
|
||||
* the handler, but does not clobber them at least in the
|
||||
* normal case.
|
||||
*/
|
||||
RELOAD_SEG(gs);
|
||||
RELOAD_SEG(fs);
|
||||
RELOAD_SEG(ds);
|
||||
RELOAD_SEG(es);
|
||||
|
||||
err |= fpu__restore_sig(buf, 1);
|
||||
|
||||
return err;
|
||||
reload_segments(&sc);
|
||||
return fpu__restore_sig(compat_ptr(sc.fpstate), 1);
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE0(sigreturn)
|
||||
@ -172,6 +152,8 @@ badframe:
|
||||
* Set up a signal frame.
|
||||
*/
|
||||
|
||||
#define get_user_seg(seg) ({ unsigned int v; savesegment(seg, v); v; })
|
||||
|
||||
static int ia32_setup_sigcontext(struct sigcontext_32 __user *sc,
|
||||
void __user *fpstate,
|
||||
struct pt_regs *regs, unsigned int mask)
|
||||
|
Loading…
Reference in New Issue
Block a user