Calling _lwp_create() with a bogus ucontext could trigger a kernel
assertion failure (and thus a crash in DIAGNOSTIC kernels). Independently discovered by YAMAMOTO Takashi and Joel Sing. To avoid this, introduce a cpu_mcontext_validate() function and move all sanity checks from cpu_setmcontext() there. Also untangle the netbsd32 compat mess slightly and add a cpu_mcontext32_validate() cousin there. Add an exhaustive atf test case, based partly on code from Joel Sing. Should finally fix the remaining open part of PR kern/43903.
This commit is contained in:
parent
f5ab9e9aed
commit
6c3cc552c2
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: mi,v 1.468 2012/05/18 15:25:25 jruoho Exp $
|
||||
# $NetBSD: mi,v 1.469 2012/05/21 14:15:16 martin Exp $
|
||||
#
|
||||
# Note: don't delete entries from here - mark them as "obsolete" instead.
|
||||
#
|
||||
|
@ -545,6 +545,7 @@
|
|||
./usr/libdata/debug/usr/tests/lib/libc/sys/t_link.debug tests-lib-debug debug,atf
|
||||
./usr/libdata/debug/usr/tests/lib/libc/sys/t_listen.debug tests-lib-debug debug,atf
|
||||
./usr/libdata/debug/usr/tests/lib/libc/sys/t_lwp_ctl.debug tests-lib-debug debug,atf
|
||||
./usr/libdata/debug/usr/tests/lib/libc/sys/t_lwp_create.debug tests-lib-debug debug,atf
|
||||
./usr/libdata/debug/usr/tests/lib/libc/sys/t_mincore.debug tests-lib-debug debug,atf
|
||||
./usr/libdata/debug/usr/tests/lib/libc/sys/t_mkdir.debug tests-lib-debug debug,atf
|
||||
./usr/libdata/debug/usr/tests/lib/libc/sys/t_mkfifo.debug tests-lib-debug debug,atf
|
||||
|
@ -2444,6 +2445,7 @@
|
|||
./usr/tests/lib/libc/sys/t_link tests-lib-tests atf
|
||||
./usr/tests/lib/libc/sys/t_listen tests-lib-tests atf
|
||||
./usr/tests/lib/libc/sys/t_lwp_ctl tests-lib-tests atf
|
||||
./usr/tests/lib/libc/sys/t_lwp_create tests-lib-tests atf
|
||||
./usr/tests/lib/libc/sys/t_mincore tests-lib-tests atf
|
||||
./usr/tests/lib/libc/sys/t_mkdir tests-lib-tests atf
|
||||
./usr/tests/lib/libc/sys/t_mkfifo tests-lib-tests atf
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: _lwp_create.2,v 1.4 2008/04/30 13:10:51 martin Exp $
|
||||
.\" $NetBSD: _lwp_create.2,v 1.5 2012/05/21 14:15:16 martin Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
|
@ -47,6 +47,10 @@ The
|
|||
.Fa context
|
||||
argument specifies the initial execution context for the new LWP including
|
||||
signal mask, stack, and machine registers.
|
||||
If this context specifies invalid register values (for example priviledge
|
||||
escalation by setting machine dependend bits forbidden for user processes),
|
||||
or does not specify cpu register values (uc_flags does not have the
|
||||
_UC_CPU bit set), the call will fail and errno will be set to EINVAL.
|
||||
.Pp
|
||||
The following flags affect the creation of the new LWP:
|
||||
.Bl -tag -width LWP_SUSPENDED
|
||||
|
@ -70,7 +74,8 @@ The LWP ID of the new LWP is stored in the location pointed to by
|
|||
Upon successful completion,
|
||||
.Fn _lwp_create
|
||||
returns a value of 0.
|
||||
Otherwise, an error code is returned to indicate the error.
|
||||
Otherwise, a value of -1 is returned and errno is set to one of the values
|
||||
documented below.
|
||||
.Sh ERRORS
|
||||
.Fn _lwp_create
|
||||
will fail and no LWP will be created if:
|
||||
|
@ -87,6 +92,8 @@ The address pointed to by
|
|||
or
|
||||
.Fa new_lwp
|
||||
is outside the process's allocated address space.
|
||||
.It Bq Er EINVAL
|
||||
The ucontext_t passed is invalid.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr _lwp_continue 2 ,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: machdep.c,v 1.338 2012/02/21 17:39:17 para Exp $ */
|
||||
/* $NetBSD: machdep.c,v 1.339 2012/05/21 14:15:16 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
|
||||
|
@ -68,7 +68,7 @@
|
|||
|
||||
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.338 2012/02/21 17:39:17 para Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.339 2012/05/21 14:15:16 martin Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -1803,6 +1803,17 @@ cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp)
|
||||
{
|
||||
const __greg_t *gr = mcp->__gregs;
|
||||
|
||||
if ((gr[_REG_PS] & ALPHA_PSL_USERSET) != ALPHA_PSL_USERSET ||
|
||||
(gr[_REG_PS] & ALPHA_PSL_USERCLR) != 0)
|
||||
return EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
||||
|
@ -1810,13 +1821,14 @@ cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
|||
struct trapframe *frame = l->l_md.md_tf;
|
||||
struct pcb *pcb = lwp_getpcb(l);
|
||||
const __greg_t *gr = mcp->__gregs;
|
||||
int error;
|
||||
|
||||
/* Restore register context, if any. */
|
||||
if (flags & _UC_CPU) {
|
||||
/* Check for security violations first. */
|
||||
if ((gr[_REG_PS] & ALPHA_PSL_USERSET) != ALPHA_PSL_USERSET ||
|
||||
(gr[_REG_PS] & ALPHA_PSL_USERCLR) != 0)
|
||||
return (EINVAL);
|
||||
error = cpu_mcontext_validate(l, mcp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
regtoframe((const struct reg *)gr, l->l_md.md_tf);
|
||||
if (l == curlwp)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: machdep.c,v 1.182 2012/04/29 21:54:51 christos Exp $ */
|
||||
/* $NetBSD: machdep.c,v 1.183 2012/05/21 14:15:17 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011
|
||||
|
@ -111,7 +111,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.182 2012/04/29 21:54:51 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.183 2012/05/21 14:15:17 martin Exp $");
|
||||
|
||||
/* #define XENDEBUG_LOW */
|
||||
|
||||
|
@ -2011,7 +2011,7 @@ cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
|||
int64_t rflags;
|
||||
|
||||
if ((flags & _UC_CPU) != 0) {
|
||||
error = check_mcontext(l, mcp, tf);
|
||||
error = cpu_mcontext_validate(l, mcp);
|
||||
if (error != 0)
|
||||
return error;
|
||||
/*
|
||||
|
@ -2068,13 +2068,14 @@ cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
|||
}
|
||||
|
||||
int
|
||||
check_mcontext(struct lwp *l, const mcontext_t *mcp, struct trapframe *tf)
|
||||
cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp)
|
||||
{
|
||||
const __greg_t *gr;
|
||||
uint16_t sel;
|
||||
int error;
|
||||
struct pmap *pmap = l->l_proc->p_vmspace->vm_map.pmap;
|
||||
struct proc *p = l->l_proc;
|
||||
struct trapframe *tf = l->l_md.md_regs;
|
||||
|
||||
gr = mcp->__gregs;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: netbsd32_machdep.c,v 1.75 2012/02/19 21:06:01 rmind Exp $ */
|
||||
/* $NetBSD: netbsd32_machdep.c,v 1.76 2012/05/21 14:15:17 martin Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wasabi Systems, Inc.
|
||||
|
@ -36,7 +36,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.75 2012/02/19 21:06:01 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.76 2012/05/21 14:15:17 martin Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_compat_netbsd.h"
|
||||
|
@ -94,7 +94,6 @@ static int x86_64_set_mtrr32(struct lwp *, void *, register_t *);
|
|||
#endif
|
||||
|
||||
static int check_sigcontext32(struct lwp *, const struct netbsd32_sigcontext *);
|
||||
static int check_mcontext32(struct lwp *, const mcontext32_t *);
|
||||
|
||||
#ifdef EXEC_AOUT
|
||||
/*
|
||||
|
@ -834,7 +833,7 @@ cpu_setmcontext32(struct lwp *l, const mcontext32_t *mcp, unsigned int flags)
|
|||
/*
|
||||
* Check for security violations.
|
||||
*/
|
||||
error = check_mcontext32(l, mcp);
|
||||
error = cpu_mcontext32_validate(l, mcp);
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
|
@ -984,8 +983,8 @@ check_sigcontext32(struct lwp *l, const struct netbsd32_sigcontext *scp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
check_mcontext32(struct lwp *l, const mcontext32_t *mcp)
|
||||
int
|
||||
cpu_mcontext32_validate(struct lwp *l, const mcontext32_t *mcp)
|
||||
{
|
||||
const __greg32_t *gr;
|
||||
struct trapframe *tf;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: process_machdep.c,v 1.19 2011/12/20 13:17:05 jmcneill Exp $ */
|
||||
/* $NetBSD: process_machdep.c,v 1.20 2012/05/21 14:15:17 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
|
||||
|
@ -53,7 +53,7 @@
|
|||
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.19 2011/12/20 13:17:05 jmcneill Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.20 2012/05/21 14:15:17 martin Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -146,7 +146,7 @@ process_write_regs(struct lwp *l, const struct reg *regp)
|
|||
* Note that struct regs is compatible with
|
||||
* the __gregs array in mcontext_t.
|
||||
*/
|
||||
error = check_mcontext(l, (const mcontext_t *)regs, tf);
|
||||
error = cpu_mcontext_validate(l, (const mcontext_t *)regs);
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: mcontext.h,v 1.14 2011/02/25 14:07:12 joerg Exp $ */
|
||||
/* $NetBSD: mcontext.h,v 1.15 2012/05/21 14:15:17 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999 The NetBSD Foundation, Inc.
|
||||
|
@ -156,10 +156,6 @@ typedef struct {
|
|||
#define _UC_MACHINE32_PAD 4
|
||||
#define __UCONTEXT32_SIZE 776
|
||||
|
||||
struct trapframe;
|
||||
struct lwp;
|
||||
int check_mcontext(struct lwp *, const mcontext_t *, struct trapframe *);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#else /* __x86_64__ */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sig_machdep.c,v 1.41 2012/01/25 17:38:09 tsutsui Exp $ */
|
||||
/* $NetBSD: sig_machdep.c,v 1.42 2012/05/21 14:15:17 martin Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994-1998 Mark Brinicombe.
|
||||
|
@ -44,7 +44,7 @@
|
|||
|
||||
#include <sys/param.h>
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.41 2012/01/25 17:38:09 tsutsui Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.42 2012/05/21 14:15:17 martin Exp $");
|
||||
|
||||
#include <sys/mount.h> /* XXX only needed by syscallargs.h */
|
||||
#include <sys/proc.h>
|
||||
|
@ -204,18 +204,30 @@ cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags)
|
|||
*flags |= _UC_TLSBASE;
|
||||
}
|
||||
|
||||
int
|
||||
cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp)
|
||||
{
|
||||
const __greg_t *gr = mcp->__gregs;
|
||||
|
||||
/* Make sure the processor mode has not been tampered with. */
|
||||
if (!VALID_R15_PSR(gr[_REG_PC], gr[_REG_CPSR]))
|
||||
return EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
||||
{
|
||||
struct trapframe *tf = process_frame(l);
|
||||
const __greg_t *gr = mcp->__gregs;
|
||||
struct proc *p = l->l_proc;
|
||||
int error;
|
||||
|
||||
if ((flags & _UC_CPU) != 0) {
|
||||
/* Restore General Register context. */
|
||||
/* Make sure the processor mode has not been tampered with. */
|
||||
if (!VALID_R15_PSR(gr[_REG_PC], gr[_REG_CPSR]))
|
||||
return EINVAL;
|
||||
error = cpu_mcontext_validate(l, mcp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
tf->tf_r0 = gr[_REG_R0];
|
||||
tf->tf_r1 = gr[_REG_R1];
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: hppa_machdep.c,v 1.27 2012/02/19 21:06:07 rmind Exp $ */
|
||||
/* $NetBSD: hppa_machdep.c,v 1.28 2012/05/21 14:15:17 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: hppa_machdep.c,v 1.27 2012/02/19 21:06:07 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: hppa_machdep.c,v 1.28 2012/05/21 14:15:17 martin Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -129,6 +129,44 @@ cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags)
|
|||
*flags |= _UC_FPU;
|
||||
}
|
||||
|
||||
int
|
||||
cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp)
|
||||
{
|
||||
const __greg_t *gr = mcp->__gregs;
|
||||
|
||||
if ((gr[_REG_PSW] & (PSW_MBS|PSW_MBZ)) != PSW_MBS) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* XXX
|
||||
* Force the space regs and priviledge bits to
|
||||
* the right values in the trapframe for now.
|
||||
*/
|
||||
|
||||
if (gr[_REG_PCSQH] != pmap_sid(pmap, gr[_REG_PCOQH])) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (gr[_REG_PCSQT] != pmap_sid(pmap, gr[_REG_PCOQT])) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (gr[_REG_PCOQH] < 0xc0000020 &&
|
||||
(gr[_REG_PCOQH] & HPPA_PC_PRIV_MASK) != HPPA_PC_PRIV_USER) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (gr[_REG_PCOQT] < 0xc0000020 &&
|
||||
(gr[_REG_PCOQT] & HPPA_PC_PRIV_MASK) != HPPA_PC_PRIV_USER) {
|
||||
return EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
||||
{
|
||||
|
@ -136,38 +174,12 @@ cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
|||
struct proc *p = l->l_proc;
|
||||
struct pmap *pmap = p->p_vmspace->vm_map.pmap;
|
||||
const __greg_t *gr = mcp->__gregs;
|
||||
int error;
|
||||
|
||||
if ((flags & _UC_CPU) != 0) {
|
||||
|
||||
if ((gr[_REG_PSW] & (PSW_MBS|PSW_MBZ)) != PSW_MBS) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* XXX
|
||||
* Force the space regs and priviledge bits to
|
||||
* the right values in the trapframe for now.
|
||||
*/
|
||||
|
||||
if (gr[_REG_PCSQH] != pmap_sid(pmap, gr[_REG_PCOQH])) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (gr[_REG_PCSQT] != pmap_sid(pmap, gr[_REG_PCOQT])) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (gr[_REG_PCOQH] < 0xc0000020 &&
|
||||
(gr[_REG_PCOQH] & HPPA_PC_PRIV_MASK) != HPPA_PC_PRIV_USER) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (gr[_REG_PCOQT] < 0xc0000020 &&
|
||||
(gr[_REG_PCOQT] & HPPA_PC_PRIV_MASK) != HPPA_PC_PRIV_USER) {
|
||||
return EINVAL;
|
||||
}
|
||||
#endif
|
||||
error = cpu_mcontext_validate(l, mcp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
tf->tf_ipsw = gr[0] |
|
||||
(hppa_cpu_ispa20_p() ? PSW_O : 0);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: machdep.c,v 1.726 2012/03/04 20:44:17 bouyer Exp $ */
|
||||
/* $NetBSD: machdep.c,v 1.727 2012/05/21 14:15:17 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008, 2009
|
||||
|
@ -67,7 +67,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.726 2012/03/04 20:44:17 bouyer Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.727 2012/05/21 14:15:17 martin Exp $");
|
||||
|
||||
#include "opt_beep.h"
|
||||
#include "opt_compat_ibcs2.h"
|
||||
|
@ -1763,6 +1763,26 @@ cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp)
|
||||
{
|
||||
const __greg_t *gr = mcp->__gregs;
|
||||
struct trapframe *tf = l->l_md.md_regs;
|
||||
|
||||
/*
|
||||
* Check for security violations. If we're returning
|
||||
* to protected mode, the CPU will validate the segment
|
||||
* registers automatically and generate a trap on
|
||||
* violations. We handle the trap, rather than doing
|
||||
* all of the checking here.
|
||||
*/
|
||||
if (((gr[_REG_EFL] ^ tf->tf_eflags) & PSL_USERSTATIC) ||
|
||||
!USERMODE(gr[_REG_CS], gr[_REG_EFL]))
|
||||
return EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
||||
{
|
||||
|
@ -1770,6 +1790,7 @@ cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
|||
const __greg_t *gr = mcp->__gregs;
|
||||
struct pcb *pcb = lwp_getpcb(l);
|
||||
struct proc *p = l->l_proc;
|
||||
int error;
|
||||
|
||||
/* Restore register context, if any. */
|
||||
if ((flags & _UC_CPU) != 0) {
|
||||
|
@ -1787,20 +1808,10 @@ cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* Check for security violations. If we're returning
|
||||
* to protected mode, the CPU will validate the segment
|
||||
* registers automatically and generate a trap on
|
||||
* violations. We handle the trap, rather than doing
|
||||
* all of the checking here.
|
||||
*/
|
||||
if (((gr[_REG_EFL] ^ tf->tf_eflags) & PSL_USERSTATIC) ||
|
||||
!USERMODE(gr[_REG_CS], gr[_REG_EFL])) {
|
||||
printf("cpu_setmcontext error: uc EFL: 0x%08x"
|
||||
" tf EFL: 0x%08x uc CS: 0x%x\n",
|
||||
gr[_REG_EFL], tf->tf_eflags, gr[_REG_CS]);
|
||||
return (EINVAL);
|
||||
}
|
||||
error = cpu_mcontext_validate(l, mcp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
tf->tf_gs = gr[_REG_GS];
|
||||
tf->tf_fs = gr[_REG_FS];
|
||||
tf->tf_es = gr[_REG_ES];
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sig_machdep.c,v 1.48 2012/02/19 21:06:14 rmind Exp $ */
|
||||
/* $NetBSD: sig_machdep.c,v 1.49 2012/05/21 14:15:18 martin Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988 University of Utah.
|
||||
|
@ -40,7 +40,7 @@
|
|||
#include "opt_m68k_arch.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.48 2012/02/19 21:06:14 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.49 2012/05/21 14:15:18 martin Exp $");
|
||||
|
||||
#define __M68K_SIGNAL_PRIVATE
|
||||
|
||||
|
@ -269,18 +269,30 @@ cpu_getmcontext(struct lwp *l, mcontext_t *mcp, u_int *flags)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp)
|
||||
{
|
||||
const __greg_t *gr = mcp->__gregs;
|
||||
|
||||
if ((gr[_REG_PS] & (PSL_MBZ|PSL_IPL|PSL_S)) != 0)
|
||||
return EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, u_int flags)
|
||||
{
|
||||
const __greg_t *gr = mcp->__gregs;
|
||||
struct frame *frame = (struct frame *)l->l_md.md_regs;
|
||||
unsigned int format = mcp->__mc_pad.__mc_frame.__mcf_format;
|
||||
int sz;
|
||||
int sz, error;
|
||||
|
||||
/* Validate the supplied context */
|
||||
if (((flags & _UC_CPU) != 0 &&
|
||||
(gr[_REG_PS] & (PSL_MBZ|PSL_IPL|PSL_S)) != 0))
|
||||
return (EINVAL);
|
||||
if ((flags & _UC_CPU) != 0) {
|
||||
error = cpu_mcontext_validate(l, mcp);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Restore exception frame information if necessary. */
|
||||
if ((flags & _UC_M68K_UC_USER) == 0 && format >= FMT4) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: cpu_subr.c,v 1.15 2012/02/19 21:06:16 rmind Exp $ */
|
||||
/* $NetBSD: cpu_subr.c,v 1.16 2012/05/21 14:15:18 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.15 2012/02/19 21:06:16 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.16 2012/05/21 14:15:18 martin Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_multiprocessor.h"
|
||||
|
@ -362,17 +362,29 @@ cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp)
|
||||
{
|
||||
/* XXX: Do we validate the addresses?? */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
||||
{
|
||||
struct trapframe *tf = l->l_md.md_utf;
|
||||
struct proc *p = l->l_proc;
|
||||
const __greg_t *gr = mcp->__gregs;
|
||||
int error;
|
||||
|
||||
/* Restore register context, if any. */
|
||||
if (flags & _UC_CPU) {
|
||||
error = cpu_mcontext_validate(l, mcp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* Save register context. */
|
||||
/* XXX: Do we validate the addresses?? */
|
||||
|
||||
#ifdef __mips_n32
|
||||
CTASSERT(_R_AST == _REG_AT);
|
||||
if (__predict_false(p->p_md.md_abi == _MIPS_BSD_API_O32)) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: netbsd32_machdep.c,v 1.8 2012/02/19 21:06:19 rmind Exp $ */
|
||||
/* $NetBSD: netbsd32_machdep.c,v 1.9 2012/05/21 14:15:18 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009 The NetBSD Foundation, Inc.
|
||||
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.8 2012/02/19 21:06:19 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.9 2012/05/21 14:15:18 martin Exp $");
|
||||
|
||||
#include "opt_compat_netbsd.h"
|
||||
#include "opt_coredump.h"
|
||||
|
@ -265,12 +265,24 @@ cpu_getmcontext32(struct lwp *l, mcontext32_t *mc32, unsigned int *flagsp)
|
|||
*flagsp |= _UC_TLSBASE;
|
||||
}
|
||||
|
||||
int
|
||||
cpu_mcontext32_validate(struct lwp *l, const mcontext32_t *mc32)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cpu_setmcontext32(struct lwp *l, const mcontext32_t *mc32, unsigned int flags)
|
||||
{
|
||||
const mcontext_o32_t * const mco32 = (const mcontext_o32_t *)mc32;
|
||||
mcontext_t mc;
|
||||
size_t i;
|
||||
size_t i, error;
|
||||
|
||||
if (flags & _UC_CPU) {
|
||||
error = cpu_mcontext32_validate(l, mc32);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
if (l->l_proc->p_md.md_abi == _MIPS_BSD_API_N32)
|
||||
return cpu_setmcontext(l, (const mcontext_t *)mc32, flags);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sig_machdep.c,v 1.41 2011/06/20 05:50:39 matt Exp $ */
|
||||
/* $NetBSD: sig_machdep.c,v 1.42 2012/05/21 14:15:18 martin Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
|
||||
|
@ -32,7 +32,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.41 2011/06/20 05:50:39 matt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.42 2012/05/21 14:15:18 martin Exp $");
|
||||
|
||||
#include "opt_ppcarch.h"
|
||||
#include "opt_altivec.h"
|
||||
|
@ -186,14 +186,25 @@ cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flagp)
|
|||
memset(&mcp->__vrf, 0, sizeof (mcp->__vrf));
|
||||
}
|
||||
|
||||
int
|
||||
cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
||||
{
|
||||
struct trapframe * const tf = l->l_md.md_utf;
|
||||
const __greg_t * const gr = mcp->__gregs;
|
||||
int error;
|
||||
|
||||
/* Restore GPR context, if any. */
|
||||
if (flags & _UC_CPU) {
|
||||
error = cpu_mcontext_validate(l, mcp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
#ifdef PPC_HAVE_FPU
|
||||
/*
|
||||
* Always save the FP exception mode in the PCB.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sh3_machdep.c,v 1.98 2012/02/19 21:06:27 rmind Exp $ */
|
||||
/* $NetBSD: sh3_machdep.c,v 1.99 2012/05/21 14:15:18 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997, 1998, 2002 The NetBSD Foundation, Inc.
|
||||
|
@ -65,7 +65,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sh3_machdep.c,v 1.98 2012/02/19 21:06:27 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sh3_machdep.c,v 1.99 2012/05/21 14:15:18 martin Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_kgdb.h"
|
||||
|
@ -438,18 +438,32 @@ cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags)
|
|||
memset(&mcp->__fpregs, 0, sizeof (mcp->__fpregs));
|
||||
}
|
||||
|
||||
int
|
||||
cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp)
|
||||
{
|
||||
struct trapframe *tf = l->l_md.md_regs;
|
||||
const __greg_t *gr = mcp->__gregs;
|
||||
|
||||
if (((tf->tf_ssr ^ gr[_REG_SR]) & PSL_USERSTATIC) != 0)
|
||||
return EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
||||
{
|
||||
struct trapframe *tf = l->l_md.md_regs;
|
||||
const __greg_t *gr = mcp->__gregs;
|
||||
struct proc *p = l->l_proc;
|
||||
int error;
|
||||
|
||||
/* Restore register context, if any. */
|
||||
if ((flags & _UC_CPU) != 0) {
|
||||
/* Check for security violations. */
|
||||
if (((tf->tf_ssr ^ gr[_REG_SR]) & PSL_USERSTATIC) != 0)
|
||||
return (EINVAL);
|
||||
error = cpu_mcontext_validate(l, mcp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
tf->tf_gbr = gr[_REG_GBR];
|
||||
tf->tf_spc = gr[_REG_PC];
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: machdep.c,v 1.318 2012/04/25 08:19:33 dholland Exp $ */
|
||||
/* $NetBSD: machdep.c,v 1.319 2012/05/21 14:15:18 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -71,7 +71,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.318 2012/04/25 08:19:33 dholland Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.319 2012/05/21 14:15:18 martin Exp $");
|
||||
|
||||
#include "opt_compat_netbsd.h"
|
||||
#include "opt_compat_sunos.h"
|
||||
|
@ -674,6 +674,23 @@ cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags)
|
|||
return;
|
||||
}
|
||||
|
||||
int
|
||||
cpu_mcontext_validate(struct lwp *l, const mcontext_t *mc)
|
||||
{
|
||||
const __greg_t *gr = mc->__gregs;
|
||||
|
||||
/*
|
||||
* Only the icc bits in the psr are used, so it need not be
|
||||
* verified. pc and npc must be multiples of 4. This is all
|
||||
* that is required; if it holds, just do it.
|
||||
*/
|
||||
if (((gr[_REG_PC] | gr[_REG_nPC]) & 3) != 0 ||
|
||||
gr[_REG_PC] == 0 || gr[_REG_nPC] == 0)
|
||||
return EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set to mcontext specified.
|
||||
* Return to previous pc and psl as specified by
|
||||
|
@ -689,6 +706,7 @@ cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
|||
struct trapframe *tf;
|
||||
const __greg_t *r = mcp->__gregs;
|
||||
struct proc *p = l->l_proc;
|
||||
int error;
|
||||
#ifdef FPU_CONTEXT
|
||||
__fpregset_t *f = &mcp->__fpregs;
|
||||
struct fpstate *fps = l->l_md.md_fpstate;
|
||||
|
@ -707,19 +725,14 @@ cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
|||
#endif
|
||||
|
||||
if (flags & _UC_CPU) {
|
||||
/* Validate */
|
||||
error = cpu_mcontext_validate(l, mcp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* Restore register context. */
|
||||
tf = (struct trapframe *)l->l_md.md_tf;
|
||||
|
||||
/*
|
||||
* Only the icc bits in the psr are used, so it need not be
|
||||
* verified. pc and npc must be multiples of 4. This is all
|
||||
* that is required; if it holds, just do it.
|
||||
*/
|
||||
if (((r[_REG_PC] | r[_REG_nPC]) & 3) != 0) {
|
||||
printf("pc or npc are not multiples of 4!\n");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/* take only psr ICC field */
|
||||
tf->tf_psr = (tf->tf_psr & ~PSR_ICC) |
|
||||
(r[_REG_PSR] & PSR_ICC);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: machdep.c,v 1.266 2012/02/19 21:06:31 rmind Exp $ */
|
||||
/* $NetBSD: machdep.c,v 1.267 2012/05/21 14:15:18 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -71,7 +71,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.266 2012/02/19 21:06:31 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.267 2012/05/21 14:15:18 martin Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_multiprocessor.h"
|
||||
|
@ -2533,12 +2533,30 @@ cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags)
|
|||
mcp->__xrs.__xrs_id = 0; /* Solaris extension? */
|
||||
}
|
||||
|
||||
int
|
||||
cpu_mcontext_validate(struct lwp *l, const mcontext_t *mc)
|
||||
{
|
||||
const __greg_t *gr = mc->__gregs;
|
||||
|
||||
/*
|
||||
* Only the icc bits in the psr are used, so it need not be
|
||||
* verified. pc and npc must be multiples of 4. This is all
|
||||
* that is required; if it holds, just do it.
|
||||
*/
|
||||
if (((gr[_REG_PC] | gr[_REG_nPC]) & 3) != 0 ||
|
||||
gr[_REG_PC] == 0 || gr[_REG_nPC] == 0)
|
||||
return EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
||||
{
|
||||
const __greg_t *gr = mcp->__gregs;
|
||||
struct trapframe64 *tf = l->l_md.md_tf;
|
||||
struct proc *p = l->l_proc;
|
||||
int error;
|
||||
|
||||
/* First ensure consistent stack state (see sendsig). */
|
||||
write_user_windows();
|
||||
|
@ -2548,14 +2566,9 @@ cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
|||
}
|
||||
|
||||
if ((flags & _UC_CPU) != 0) {
|
||||
/*
|
||||
* Only the icc bits in the psr are used, so it need not be
|
||||
* verified. pc and npc must be multiples of 4. This is all
|
||||
* that is required; if it holds, just do it.
|
||||
*/
|
||||
if (((gr[_REG_PC] | gr[_REG_nPC]) & 3) != 0 ||
|
||||
gr[_REG_PC] == 0 || gr[_REG_nPC] == 0)
|
||||
return (EINVAL);
|
||||
error = cpu_mcontext_validate(l, mcp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* Restore general register context. */
|
||||
/* take only tstate CCR (and ASI) fields */
|
||||
|
@ -2630,7 +2643,7 @@ cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
|||
l->l_sigstk.ss_flags &= ~SS_ONSTACK;
|
||||
mutex_exit(p->p_lock);
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: netbsd32_machdep.c,v 1.97 2012/02/19 21:06:31 rmind Exp $ */
|
||||
/* $NetBSD: netbsd32_machdep.c,v 1.98 2012/05/21 14:15:18 martin Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001 Matthew R. Green
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.97 2012/02/19 21:06:31 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.98 2012/05/21 14:15:18 martin Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_compat_netbsd.h"
|
||||
|
@ -811,7 +811,6 @@ netbsd32_cpu_getmcontext(
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
int netbsd32_cpu_setmcontext(struct lwp *, mcontext_t *, unsigned int);
|
||||
|
||||
int
|
||||
|
@ -1136,6 +1135,22 @@ netbsd32_sysarch(struct lwp *l, const struct netbsd32_sysarch_args *uap, registe
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
cpu_mcontext32_validate(struct lwp *l, const mcontext32_t *mc)
|
||||
{
|
||||
const __greg32_t *gr = mc->__gregs;
|
||||
|
||||
/*
|
||||
* Only the icc bits in the psr are used, so it need not be
|
||||
* verified. pc and npc must be multiples of 4. This is all
|
||||
* that is required; if it holds, just do it.
|
||||
*/
|
||||
if (((gr[_REG32_PC] | gr[_REG32_nPC]) & 3) != 0 ||
|
||||
gr[_REG32_PC] == 0 || gr[_REG32_nPC] == 0)
|
||||
return EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cpu_setmcontext32(struct lwp *l, const mcontext32_t *mcp, unsigned int flags)
|
||||
|
@ -1143,6 +1158,7 @@ cpu_setmcontext32(struct lwp *l, const mcontext32_t *mcp, unsigned int flags)
|
|||
struct trapframe *tf = l->l_md.md_tf;
|
||||
const __greg32_t *gr = mcp->__gregs;
|
||||
struct proc *p = l->l_proc;
|
||||
int error;
|
||||
|
||||
/* First ensure consistent stack state (see sendsig). */
|
||||
write_user_windows();
|
||||
|
@ -1153,14 +1169,9 @@ cpu_setmcontext32(struct lwp *l, const mcontext32_t *mcp, unsigned int flags)
|
|||
|
||||
/* Restore register context, if any. */
|
||||
if ((flags & _UC_CPU) != 0) {
|
||||
/*
|
||||
* Only the icc bits in the psr are used, so it need not be
|
||||
* verified. pc and npc must be multiples of 4. This is all
|
||||
* that is required; if it holds, just do it.
|
||||
*/
|
||||
if (((gr[_REG32_PC] | gr[_REG32_nPC]) & 3) != 0 ||
|
||||
gr[_REG32_PC] == 0 || gr[_REG32_nPC] == 0)
|
||||
return (EINVAL);
|
||||
error = cpu_mcontext32_validate(l, mcp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* Restore general register context. */
|
||||
/* take only tstate CCR (and ASI) fields */
|
||||
|
@ -1314,8 +1325,7 @@ startlwp32(void *arg)
|
|||
error = cpu_setmcontext32(l, &uc->uc_mcontext, uc->uc_flags);
|
||||
KASSERT(error == 0);
|
||||
|
||||
/* Note: we are freeing ucontext_t, not ucontext32_t. */
|
||||
kmem_free(uc, sizeof(ucontext_t));
|
||||
kmem_free(uc, sizeof(ucontext32_t));
|
||||
userret(l, 0, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: machdep.c,v 1.187 2012/02/27 15:41:10 matt Exp $ */
|
||||
/* $NetBSD: machdep.c,v 1.188 2012/05/21 14:15:19 martin Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
|
||||
|
@ -83,7 +83,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.187 2012/02/27 15:41:10 matt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.188 2012/05/21 14:15:19 martin Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_compat_netbsd.h"
|
||||
|
@ -641,18 +641,31 @@ cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags)
|
|||
}
|
||||
|
||||
int
|
||||
cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
||||
cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp)
|
||||
{
|
||||
struct trapframe * const tf = l->l_md.md_utf;
|
||||
const __greg_t *gr = mcp->__gregs;
|
||||
|
||||
if ((flags & _UC_CPU) == 0)
|
||||
return 0;
|
||||
|
||||
if ((gr[_REG_PSL] & (PSL_IPL | PSL_IS)) ||
|
||||
((gr[_REG_PSL] & (PSL_U | PSL_PREVU)) != (PSL_U | PSL_PREVU)) ||
|
||||
(gr[_REG_PSL] & PSL_CM))
|
||||
return (EINVAL);
|
||||
return EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
||||
{
|
||||
struct trapframe * const tf = l->l_md.md_utf;
|
||||
const __greg_t *gr = mcp->__gregs;
|
||||
int error;
|
||||
|
||||
if ((flags & _UC_CPU) == 0)
|
||||
return 0;
|
||||
|
||||
error = cpu_mcontext_validate(l, mcp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
tf->tf_r0 = gr[_REG_R0];
|
||||
tf->tf_r1 = gr[_REG_R1];
|
||||
|
@ -674,7 +687,6 @@ cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
|
|||
|
||||
if (flags & _UC_TLSBASE) {
|
||||
void *tlsbase;
|
||||
int error;
|
||||
|
||||
error = copyin((void *)tf->tf_sp, &tlsbase, sizeof(tlsbase));
|
||||
if (error) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: netbsd32_lwp.c,v 1.12 2011/02/05 13:46:44 yamt Exp $ */
|
||||
/* $NetBSD: netbsd32_lwp.c,v 1.13 2012/05/21 14:15:19 martin Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2006, 2007 The NetBSD Foundation.
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: netbsd32_lwp.c,v 1.12 2011/02/05 13:46:44 yamt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: netbsd32_lwp.c,v 1.13 2012/05/21 14:15:19 martin Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
@ -53,14 +53,40 @@ netbsd32__lwp_create(struct lwp *l, const struct netbsd32__lwp_create_args *uap,
|
|||
syscallarg(netbsd32_u_long) flags;
|
||||
syscallarg(netbsd32_lwpidp) new_lwp;
|
||||
} */
|
||||
struct sys__lwp_create_args ua;
|
||||
struct proc *p = l->l_proc;
|
||||
ucontext32_t *newuc = NULL;
|
||||
lwpid_t lid;
|
||||
int error;
|
||||
|
||||
CTASSERT(sizeof(ucontext32_t) <= sizeof(ucontext_t));
|
||||
NETBSD32TOP_UAP(ucp, const ucontext_t); /* see startlwp32() */
|
||||
NETBSD32TO64_UAP(flags);
|
||||
NETBSD32TOP_UAP(new_lwp, lwpid_t);
|
||||
KASSERT(p->p_emul->e_ucsize == sizeof(*newuc));
|
||||
|
||||
return sys__lwp_create(l, &ua, retval);
|
||||
newuc = kmem_alloc(sizeof(ucontext32_t), KM_SLEEP);
|
||||
error = copyin(SCARG_P32(uap, ucp), newuc, p->p_emul->e_ucsize);
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
/* validate the ucontext */
|
||||
if ((newuc->uc_flags & _UC_CPU) == 0) {
|
||||
error = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
error = cpu_mcontext32_validate(l, &newuc->uc_mcontext);
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
error = do_lwp_create(l, newuc, SCARG(uap, flags), &lid);
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* do not free ucontext in case of an error here,
|
||||
* the lwp will actually run and access it
|
||||
*/
|
||||
return copyout(&lid, SCARG_P32(uap, new_lwp), sizeof(lid));
|
||||
|
||||
fail:
|
||||
kmem_free(newuc, sizeof(*newuc));
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ucontext.h,v 1.5 2012/03/18 21:48:47 njoly Exp $ */
|
||||
/* $NetBSD: ucontext.h,v 1.6 2012/05/21 14:15:19 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2003 The NetBSD Foundation, Inc.
|
||||
|
@ -64,6 +64,7 @@ __CTASSERT(sizeof(ucontext32_t) == __UCONTEXT32_SIZE);
|
|||
struct lwp;
|
||||
void getucontext32(struct lwp *, ucontext32_t *);
|
||||
int setucontext32(struct lwp *, const ucontext32_t *);
|
||||
int cpu_mcontext32_validate(struct lwp *, const mcontext32_t *);
|
||||
void cpu_getmcontext32(struct lwp *, mcontext32_t *, unsigned int *);
|
||||
int cpu_setmcontext32(struct lwp *, const mcontext32_t *, unsigned int);
|
||||
#endif /* COMPAT_NETBSD32 */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sys_lwp.c,v 1.53 2012/02/19 21:06:56 rmind Exp $ */
|
||||
/* $NetBSD: sys_lwp.c,v 1.54 2012/05/21 14:15:19 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -35,7 +35,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sys_lwp.c,v 1.53 2012/02/19 21:06:56 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sys_lwp.c,v 1.54 2012/05/21 14:15:19 martin Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -70,51 +70,28 @@ lwp_sys_init(void)
|
|||
}
|
||||
|
||||
int
|
||||
sys__lwp_create(struct lwp *l, const struct sys__lwp_create_args *uap,
|
||||
register_t *retval)
|
||||
do_lwp_create(lwp_t *l, void *arg, u_long flags, lwpid_t *new_lwp)
|
||||
{
|
||||
/* {
|
||||
syscallarg(const ucontext_t *) ucp;
|
||||
syscallarg(u_long) flags;
|
||||
syscallarg(lwpid_t *) new_lwp;
|
||||
} */
|
||||
struct proc *p = l->l_proc;
|
||||
struct lwp *l2;
|
||||
struct schedstate_percpu *spc;
|
||||
vaddr_t uaddr;
|
||||
ucontext_t *newuc;
|
||||
int error, lid;
|
||||
|
||||
newuc = kmem_alloc(sizeof(ucontext_t), KM_SLEEP);
|
||||
error = copyin(SCARG(uap, ucp), newuc, p->p_emul->e_ucsize);
|
||||
if (error) {
|
||||
kmem_free(newuc, sizeof(ucontext_t));
|
||||
return error;
|
||||
}
|
||||
int error;
|
||||
|
||||
/* XXX check against resource limits */
|
||||
|
||||
uaddr = uvm_uarea_alloc();
|
||||
if (__predict_false(uaddr == 0)) {
|
||||
kmem_free(newuc, sizeof(ucontext_t));
|
||||
if (__predict_false(uaddr == 0))
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
error = lwp_create(l, p, uaddr, SCARG(uap, flags) & LWP_DETACHED,
|
||||
NULL, 0, p->p_emul->e_startlwp, newuc, &l2, l->l_class);
|
||||
error = lwp_create(l, p, uaddr, flags & LWP_DETACHED,
|
||||
NULL, 0, p->p_emul->e_startlwp, arg, &l2, l->l_class);
|
||||
if (__predict_false(error)) {
|
||||
uvm_uarea_free(uaddr);
|
||||
kmem_free(newuc, sizeof(ucontext_t));
|
||||
return error;
|
||||
}
|
||||
|
||||
lid = l2->l_lid;
|
||||
error = copyout(&lid, SCARG(uap, new_lwp), sizeof(lid));
|
||||
if (error) {
|
||||
lwp_exit(l2);
|
||||
kmem_free(newuc, sizeof(ucontext_t));
|
||||
return error;
|
||||
}
|
||||
*new_lwp = l2->l_lid;
|
||||
|
||||
/*
|
||||
* Set the new LWP running, unless the caller has requested that
|
||||
|
@ -124,7 +101,7 @@ sys__lwp_create(struct lwp *l, const struct sys__lwp_create_args *uap,
|
|||
mutex_enter(p->p_lock);
|
||||
lwp_lock(l2);
|
||||
spc = &l2->l_cpu->ci_schedstate;
|
||||
if ((SCARG(uap, flags) & LWP_SUSPENDED) == 0 &&
|
||||
if ((flags & LWP_SUSPENDED) == 0 &&
|
||||
(l->l_flag & (LW_WREBOOT | LW_WSUSPEND | LW_WEXIT)) == 0) {
|
||||
if (p->p_stat == SSTOP || (p->p_sflag & PS_STOPPING) != 0) {
|
||||
KASSERT(l2->l_wchan == NULL);
|
||||
|
@ -147,6 +124,49 @@ sys__lwp_create(struct lwp *l, const struct sys__lwp_create_args *uap,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sys__lwp_create(struct lwp *l, const struct sys__lwp_create_args *uap,
|
||||
register_t *retval)
|
||||
{
|
||||
/* {
|
||||
syscallarg(const ucontext_t *) ucp;
|
||||
syscallarg(u_long) flags;
|
||||
syscallarg(lwpid_t *) new_lwp;
|
||||
} */
|
||||
struct proc *p = l->l_proc;
|
||||
ucontext_t *newuc = NULL;
|
||||
lwpid_t lid;
|
||||
int error;
|
||||
|
||||
newuc = kmem_alloc(sizeof(ucontext_t), KM_SLEEP);
|
||||
error = copyin(SCARG(uap, ucp), newuc, p->p_emul->e_ucsize);
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
/* validate the ucontext */
|
||||
if ((newuc->uc_flags & _UC_CPU) == 0) {
|
||||
error = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
error = cpu_mcontext_validate(l, &newuc->uc_mcontext);
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
error = do_lwp_create(l, newuc, SCARG(uap, flags), &lid);
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* do not free ucontext in case of an error here,
|
||||
* the lwp will actually run and access it
|
||||
*/
|
||||
return copyout(&lid, SCARG(uap, new_lwp), sizeof(lid));
|
||||
|
||||
fail:
|
||||
kmem_free(newuc, sizeof(ucontext_t));
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
sys__lwp_exit(struct lwp *l, const void *v, register_t *retval)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: lwp.h,v 1.160 2012/02/19 21:06:58 rmind Exp $ */
|
||||
/* $NetBSD: lwp.h,v 1.161 2012/05/21 14:15:19 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001, 2006, 2007, 2008, 2009, 2010
|
||||
|
@ -325,6 +325,7 @@ void lwp_need_userret(lwp_t *);
|
|||
void lwp_free(lwp_t *, bool, bool);
|
||||
uint64_t lwp_pctr(void);
|
||||
int lwp_setprivate(lwp_t *, void *);
|
||||
int do_lwp_create(lwp_t *, void *, u_long, lwpid_t *);
|
||||
|
||||
void lwpinit_specificdata(void);
|
||||
int lwp_specific_key_create(specificdata_key_t *, specificdata_dtor_t);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ucontext.h,v 1.15 2012/03/18 17:59:57 tsutsui Exp $ */
|
||||
/* $NetBSD: ucontext.h,v 1.16 2012/05/21 14:15:19 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2003 The NetBSD Foundation, Inc.
|
||||
|
@ -85,6 +85,7 @@ void getucontext(struct lwp *, ucontext_t *);
|
|||
int setucontext(struct lwp *, const ucontext_t *);
|
||||
void cpu_getmcontext(struct lwp *, mcontext_t *, unsigned int *);
|
||||
int cpu_setmcontext(struct lwp *, const mcontext_t *, unsigned int);
|
||||
int cpu_mcontext_validate(struct lwp *, const mcontext_t *);
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_SYS_UCONTEXT_H_ */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.22 2012/04/20 12:11:29 jruoho Exp $
|
||||
# $NetBSD: Makefile,v 1.23 2012/05/21 14:15:19 martin Exp $
|
||||
|
||||
MKMAN= no
|
||||
|
||||
|
@ -29,6 +29,7 @@ TESTS_C+= t_kill
|
|||
TESTS_C+= t_link
|
||||
TESTS_C+= t_listen
|
||||
TESTS_C+= t_lwp_ctl
|
||||
TESTS_C+= t_lwp_create
|
||||
TESTS_C+= t_mincore
|
||||
TESTS_C+= t_mkdir
|
||||
TESTS_C+= t_mkfifo
|
||||
|
|
|
@ -0,0 +1,247 @@
|
|||
/* $NetBSD: t_lwp_create.c,v 1.1 2012/05/21 14:15:19 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2012 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is partly based on code by Joel Sing <joel at sing.id.au>
|
||||
*/
|
||||
|
||||
#include <atf-c.h>
|
||||
#include <lwp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ucontext.h>
|
||||
#include <inttypes.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef __alpha__
|
||||
#include <machine/alpha_cpu.h>
|
||||
#endif
|
||||
#ifdef __amd64__
|
||||
#include <machine/vmparam.h>
|
||||
#include <machine/psl.h>
|
||||
#endif
|
||||
#ifdef __hppa__
|
||||
#include <machine/psl.h>
|
||||
#endif
|
||||
#ifdef __i386__
|
||||
#include <machine/segments.h>
|
||||
#include <machine/psl.h>
|
||||
#endif
|
||||
#if defined(__m68k__) || defined(__sh3__) || defined __vax__
|
||||
#include <machine/psl.h>
|
||||
#endif
|
||||
|
||||
volatile lwpid_t the_lwp_id = 0;
|
||||
|
||||
static void lwp_main_func(void* arg)
|
||||
{
|
||||
the_lwp_id = _lwp_self();
|
||||
_lwp_exit();
|
||||
}
|
||||
|
||||
/*
|
||||
* Hard to docment - see usage examples below
|
||||
*/
|
||||
#define INVALID_UCONTEXT(ARCH,NAME,DESC) \
|
||||
static void ARCH##_##NAME(ucontext_t *); \
|
||||
ATF_TC(lwp_create_##ARCH##_fail_##NAME); \
|
||||
ATF_TC_HEAD(lwp_create_##ARCH##_fail_##NAME, tc) \
|
||||
{ \
|
||||
atf_tc_set_md_var(tc, "descr", "verify rejection of invalid ucontext " \
|
||||
"on " #ARCH " due to " DESC); \
|
||||
} \
|
||||
\
|
||||
ATF_TC_BODY(lwp_create_##ARCH##_fail_##NAME, tc) \
|
||||
{ \
|
||||
ucontext_t uc; \
|
||||
lwpid_t lid; \
|
||||
int error; \
|
||||
\
|
||||
getcontext(&uc); \
|
||||
uc.uc_flags = _UC_CPU; \
|
||||
ARCH##_##NAME(&uc); \
|
||||
\
|
||||
error = _lwp_create(&uc, 0, &lid); \
|
||||
ATF_REQUIRE(error != 0 && errno == EINVAL); \
|
||||
} \
|
||||
static void ARCH##_##NAME(ucontext_t *uc) \
|
||||
{
|
||||
|
||||
|
||||
ATF_TC(lwp_create_works);
|
||||
ATF_TC_HEAD(lwp_create_works, tc)
|
||||
{
|
||||
atf_tc_set_md_var(tc, "descr", "Verify creation of a lwp and waiting"
|
||||
" for it to finish");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(lwp_create_works, tc)
|
||||
{
|
||||
ucontext_t uc;
|
||||
lwpid_t lid;
|
||||
int error;
|
||||
void *stack;
|
||||
static const size_t ssize = 16*1024;
|
||||
|
||||
stack = malloc(ssize);
|
||||
_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
|
||||
|
||||
error = _lwp_create(&uc, 0, &lid);
|
||||
ATF_REQUIRE(error == 0);
|
||||
|
||||
error = _lwp_wait(lid, NULL);
|
||||
ATF_REQUIRE(error == 0);
|
||||
ATF_REQUIRE(lid == the_lwp_id);
|
||||
}
|
||||
|
||||
INVALID_UCONTEXT(generic, no_uc_cpu, "not setting cpu registers")
|
||||
uc->uc_flags &= ~_UC_CPU;
|
||||
}
|
||||
|
||||
#ifdef __alpha__
|
||||
INVALID_UCONTEXT(alpha, pslset, "trying to clear the USERMODE flag")
|
||||
uc->uc_mcontext.__gregs[_REG_PS] &= ~ALPHA_PSL_USERMODE;
|
||||
}
|
||||
INVALID_UCONTEXT(alpha, pslclr, "trying to set a 'must be zero' flag")
|
||||
uc->uc_mcontext.__gregs[_REG_PS] |= ALPHA_PSL_IPL_HIGH;
|
||||
}
|
||||
#endif
|
||||
#ifdef __amd64__
|
||||
INVALID_UCONTEXT(amd64, untouchable_rflags, "forbidden rflags changed")
|
||||
uc->uc_mcontext.__gregs[_REG_RFLAGS] |= PSL_MBZ;
|
||||
}
|
||||
/*
|
||||
* XXX: add invalid GS/DS selector tests
|
||||
*/
|
||||
INVALID_UCONTEXT(amd64, pc_too_high,
|
||||
"instruction pointer outside userland address space")
|
||||
uc->uc_mcontext.__gregs[_REG_RIP] = VM_MAXUSER_ADDRESS;
|
||||
}
|
||||
#endif
|
||||
#ifdef __arm__
|
||||
INVALID_UCONTEXT(arm, invalid_mode, "psr or r15 set to non-user-mode")
|
||||
uc->uc_mcontext.__gregs[_REG_PC] |= 0x1f /*PSR_SYS32_MODE*/;
|
||||
uc->uc_mcontext.__gregs[_REG_CPSR] |= 0x03 /*R15_MODE_SVC*/;
|
||||
}
|
||||
#endif
|
||||
#ifdef __hppa__
|
||||
INVALID_UCONTEXT(hppa, invalid_1, "set illegal bits in psw")
|
||||
uc->uc_mcontext.__gregs[_REG_PSW] |= PSW_MBZ;
|
||||
}
|
||||
INVALID_UCONTEXT(hppa, invalid_0, "clear illegal bits in psw")
|
||||
uc->uc_mcontext.__gregs[_REG_PSW] &= ~PSW_MBS;
|
||||
}
|
||||
#endif
|
||||
#ifdef __i386__
|
||||
INVALID_UCONTEXT(i386, untouchable_eflags, "changing forbidden eflags")
|
||||
uc->uc_mcontext.__gregs[_REG_EFL] |= PSL_IOPL;
|
||||
}
|
||||
INVALID_UCONTEXT(i386, priv_escalation, "modifying priviledge level")
|
||||
uc->uc_mcontext.__gregs[_REG_CS] &= ~SEL_RPL;
|
||||
}
|
||||
#endif
|
||||
#ifdef __m68k__
|
||||
INVALID_UCONTEXT(m68k, invalid_ps_bits,
|
||||
"setting forbidden bits in the ps register")
|
||||
uc->uc_mcontext.__gregs[_REG_PS] |= (PSL_MBZ|PSL_IPL|PSL_S);
|
||||
}
|
||||
#endif
|
||||
#ifdef __sh3__
|
||||
INVALID_UCONTEXT(sh3, modify_userstatic,
|
||||
"modifying illegal bits in the status register")
|
||||
uc->uc_mcontext.__gregs[_REG_SR] |= PSL_MD;
|
||||
}
|
||||
#endif
|
||||
#ifdef __sparc__
|
||||
INVALID_UCONTEXT(sparc, pc_odd, "mis-aligned instruction pointer")
|
||||
uc->uc_mcontext.__gregs[_REG_PC] = 0x100002;
|
||||
}
|
||||
INVALID_UCONTEXT(sparc, npc_odd, "mis-aligned next instruction pointer")
|
||||
uc->uc_mcontext.__gregs[_REG_nPC] = 0x100002;
|
||||
}
|
||||
INVALID_UCONTEXT(sparc, pc_null, "NULL instruction pointer")
|
||||
uc->uc_mcontext.__gregs[_REG_PC] = 0;
|
||||
}
|
||||
INVALID_UCONTEXT(sparc, npc_null, "NULL next instruction pointer")
|
||||
uc->uc_mcontext.__gregs[_REG_nPC] = 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef __vax__
|
||||
INVALID_UCONTEXT(vax, psl_0, "clearing forbidden bits in psl")
|
||||
uc->uc_mcontext.__gregs[_REG_PSL] &= ~(PSL_U | PSL_PREVU);
|
||||
}
|
||||
INVALID_UCONTEXT(vax, psl_1, "setting forbidden bits in psl")
|
||||
uc->uc_mcontext.__gregs[_REG_PSL] |= PSL_IPL | PSL_IS;
|
||||
}
|
||||
INVALID_UCONTEXT(vax, psl_cm, "setting CM bit in psl")
|
||||
uc->uc_mcontext.__gregs[_REG_PSL] |= PSL_CM;
|
||||
}
|
||||
#endif
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
ATF_TP_ADD_TC(tp, lwp_create_works);
|
||||
ATF_TP_ADD_TC(tp, lwp_create_generic_fail_no_uc_cpu);
|
||||
#ifdef __alpha__
|
||||
ATF_TP_ADD_TC(tp, lwp_create_alpha_fail_pslset);
|
||||
ATF_TP_ADD_TC(tp, lwp_create_alpha_fail_pslclr);
|
||||
#endif
|
||||
#ifdef __amd64__
|
||||
ATF_TP_ADD_TC(tp, lwp_create_amd64_fail_untouchable_rflags);
|
||||
ATF_TP_ADD_TC(tp, lwp_create_amd64_fail_pc_too_high);
|
||||
#endif
|
||||
#ifdef __arm__
|
||||
ATF_TP_ADD_TC(tp, lwp_create_arm_fail_invalid_mode);
|
||||
#endif
|
||||
#ifdef __hppa__
|
||||
ATF_TP_ADD_TC(tp, lwp_create_hppa_fail_invalid_1);
|
||||
ATF_TP_ADD_TC(tp, lwp_create_hppa_fail_invalid_0);
|
||||
#endif
|
||||
#ifdef __i386__
|
||||
ATF_TP_ADD_TC(tp, lwp_create_i386_fail_untouchable_eflags);
|
||||
ATF_TP_ADD_TC(tp, lwp_create_i386_fail_priv_escalation);
|
||||
#endif
|
||||
#ifdef __m68k__
|
||||
ATF_TP_ADD_TC(tp, lwp_create_m68k_fail_invalid_ps_bits);
|
||||
#endif
|
||||
#ifdef __sh3__
|
||||
ATF_TP_ADD_TC(tp, lwp_create_sh3_fail_modify_userstatic);
|
||||
#endif
|
||||
#ifdef __sparc__
|
||||
ATF_TP_ADD_TC(tp, lwp_create_sparc_fail_pc_odd);
|
||||
ATF_TP_ADD_TC(tp, lwp_create_sparc_fail_npc_odd);
|
||||
ATF_TP_ADD_TC(tp, lwp_create_sparc_fail_pc_null);
|
||||
ATF_TP_ADD_TC(tp, lwp_create_sparc_fail_npc_null);
|
||||
#endif
|
||||
#ifdef __vax__
|
||||
ATF_TP_ADD_TC(tp, lwp_create_vax_fail_psl_0);
|
||||
ATF_TP_ADD_TC(tp, lwp_create_vax_fail_psl_1);
|
||||
ATF_TP_ADD_TC(tp, lwp_create_vax_fail_psl_cm);
|
||||
#endif
|
||||
return atf_no_error();
|
||||
}
|
Loading…
Reference in New Issue