Module Name: src
Committed By: martin
Date: Mon May 21 14:15:20 UTC 2012
Modified Files:
src/distrib/sets/lists/tests: mi
src/lib/libc/sys: _lwp_create.2
src/sys/arch/alpha/alpha: machdep.c
src/sys/arch/amd64/amd64: machdep.c netbsd32_machdep.c
process_machdep.c
src/sys/arch/amd64/include: mcontext.h
src/sys/arch/arm/arm: sig_machdep.c
src/sys/arch/hppa/hppa: hppa_machdep.c
src/sys/arch/i386/i386: machdep.c
src/sys/arch/m68k/m68k: sig_machdep.c
src/sys/arch/mips/mips: cpu_subr.c netbsd32_machdep.c
src/sys/arch/powerpc/powerpc: sig_machdep.c
src/sys/arch/sh3/sh3: sh3_machdep.c
src/sys/arch/sparc/sparc: machdep.c
src/sys/arch/sparc64/sparc64: machdep.c netbsd32_machdep.c
src/sys/arch/vax/vax: machdep.c
src/sys/compat/netbsd32: netbsd32_lwp.c
src/sys/compat/sys: ucontext.h
src/sys/kern: sys_lwp.c
src/sys/sys: lwp.h ucontext.h
src/tests/lib/libc/sys: Makefile
Added Files:
src/tests/lib/libc/sys: t_lwp_create.c
Log Message:
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.
To generate a diff of this commit:
cvs rdiff -u -r1.468 -r1.469 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.4 -r1.5 src/lib/libc/sys/_lwp_create.2
cvs rdiff -u -r1.338 -r1.339 src/sys/arch/alpha/alpha/machdep.c
cvs rdiff -u -r1.182 -r1.183 src/sys/arch/amd64/amd64/machdep.c
cvs rdiff -u -r1.75 -r1.76 src/sys/arch/amd64/amd64/netbsd32_machdep.c
cvs rdiff -u -r1.19 -r1.20 src/sys/arch/amd64/amd64/process_machdep.c
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/amd64/include/mcontext.h
cvs rdiff -u -r1.41 -r1.42 src/sys/arch/arm/arm/sig_machdep.c
cvs rdiff -u -r1.27 -r1.28 src/sys/arch/hppa/hppa/hppa_machdep.c
cvs rdiff -u -r1.726 -r1.727 src/sys/arch/i386/i386/machdep.c
cvs rdiff -u -r1.48 -r1.49 src/sys/arch/m68k/m68k/sig_machdep.c
cvs rdiff -u -r1.15 -r1.16 src/sys/arch/mips/mips/cpu_subr.c
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/mips/mips/netbsd32_machdep.c
cvs rdiff -u -r1.41 -r1.42 src/sys/arch/powerpc/powerpc/sig_machdep.c
cvs rdiff -u -r1.98 -r1.99 src/sys/arch/sh3/sh3/sh3_machdep.c
cvs rdiff -u -r1.318 -r1.319 src/sys/arch/sparc/sparc/machdep.c
cvs rdiff -u -r1.266 -r1.267 src/sys/arch/sparc64/sparc64/machdep.c
cvs rdiff -u -r1.97 -r1.98 src/sys/arch/sparc64/sparc64/netbsd32_machdep.c
cvs rdiff -u -r1.187 -r1.188 src/sys/arch/vax/vax/machdep.c
cvs rdiff -u -r1.12 -r1.13 src/sys/compat/netbsd32/netbsd32_lwp.c
cvs rdiff -u -r1.5 -r1.6 src/sys/compat/sys/ucontext.h
cvs rdiff -u -r1.53 -r1.54 src/sys/kern/sys_lwp.c
cvs rdiff -u -r1.160 -r1.161 src/sys/sys/lwp.h
cvs rdiff -u -r1.15 -r1.16 src/sys/sys/ucontext.h
cvs rdiff -u -r1.22 -r1.23 src/tests/lib/libc/sys/Makefile
cvs rdiff -u -r0 -r1.1 src/tests/lib/libc/sys/t_lwp_create.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/distrib/sets/lists/tests/mi
diff -u src/distrib/sets/lists/tests/mi:1.468 src/distrib/sets/lists/tests/mi:1.469
--- src/distrib/sets/lists/tests/mi:1.468 Fri May 18 15:25:25 2012
+++ src/distrib/sets/lists/tests/mi Mon May 21 14:15:16 2012
@@ -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
Index: src/lib/libc/sys/_lwp_create.2
diff -u src/lib/libc/sys/_lwp_create.2:1.4 src/lib/libc/sys/_lwp_create.2:1.5
--- src/lib/libc/sys/_lwp_create.2:1.4 Wed Apr 30 13:10:51 2008
+++ src/lib/libc/sys/_lwp_create.2 Mon May 21 14:15:16 2012
@@ -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 t
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 ,
Index: src/sys/arch/alpha/alpha/machdep.c
diff -u src/sys/arch/alpha/alpha/machdep.c:1.338 src/sys/arch/alpha/alpha/machdep.c:1.339
--- src/sys/arch/alpha/alpha/machdep.c:1.338 Tue Feb 21 17:39:17 2012
+++ src/sys/arch/alpha/alpha/machdep.c Mon May 21 14:15:16 2012
@@ -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_
}
}
+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 mco
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)
Index: src/sys/arch/amd64/amd64/machdep.c
diff -u src/sys/arch/amd64/amd64/machdep.c:1.182 src/sys/arch/amd64/amd64/machdep.c:1.183
--- src/sys/arch/amd64/amd64/machdep.c:1.182 Sun Apr 29 21:54:51 2012
+++ src/sys/arch/amd64/amd64/machdep.c Mon May 21 14:15:17 2012
@@ -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 mco
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 mco
}
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;
Index: src/sys/arch/amd64/amd64/netbsd32_machdep.c
diff -u src/sys/arch/amd64/amd64/netbsd32_machdep.c:1.75 src/sys/arch/amd64/amd64/netbsd32_machdep.c:1.76
--- src/sys/arch/amd64/amd64/netbsd32_machdep.c:1.75 Sun Feb 19 21:06:01 2012
+++ src/sys/arch/amd64/amd64/netbsd32_machdep.c Mon May 21 14:15:17 2012
@@ -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
#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 m
/*
* 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
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;
Index: src/sys/arch/amd64/amd64/process_machdep.c
diff -u src/sys/arch/amd64/amd64/process_machdep.c:1.19 src/sys/arch/amd64/amd64/process_machdep.c:1.20
--- src/sys/arch/amd64/amd64/process_machdep.c:1.19 Tue Dec 20 13:17:05 2011
+++ src/sys/arch/amd64/amd64/process_machdep.c Mon May 21 14:15:17 2012
@@ -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
* 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;
Index: src/sys/arch/amd64/include/mcontext.h
diff -u src/sys/arch/amd64/include/mcontext.h:1.14 src/sys/arch/amd64/include/mcontext.h:1.15
--- src/sys/arch/amd64/include/mcontext.h:1.14 Fri Feb 25 14:07:12 2011
+++ src/sys/arch/amd64/include/mcontext.h Mon May 21 14:15:17 2012
@@ -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__ */
Index: src/sys/arch/arm/arm/sig_machdep.c
diff -u src/sys/arch/arm/arm/sig_machdep.c:1.41 src/sys/arch/arm/arm/sig_machdep.c:1.42
--- src/sys/arch/arm/arm/sig_machdep.c:1.41 Wed Jan 25 17:38:09 2012
+++ src/sys/arch/arm/arm/sig_machdep.c Mon May 21 14:15:17 2012
@@ -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>
@@ -205,17 +205,29 @@ cpu_getmcontext(struct lwp *l, mcontext_
}
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];
Index: src/sys/arch/hppa/hppa/hppa_machdep.c
diff -u src/sys/arch/hppa/hppa/hppa_machdep.c:1.27 src/sys/arch/hppa/hppa/hppa_machdep.c:1.28
--- src/sys/arch/hppa/hppa/hppa_machdep.c:1.27 Sun Feb 19 21:06:07 2012
+++ src/sys/arch/hppa/hppa/hppa_machdep.c Mon May 21 14:15:17 2012
@@ -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>
@@ -130,45 +130,57 @@ cpu_getmcontext(struct lwp *l, mcontext_
}
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 *tf = l->l_md.md_regs;
- struct proc *p = l->l_proc;
- struct pmap *pmap = p->p_vmspace->vm_map.pmap;
const __greg_t *gr = mcp->__gregs;
- if ((flags & _UC_CPU) != 0) {
-
- if ((gr[_REG_PSW] & (PSW_MBS|PSW_MBZ)) != PSW_MBS) {
- return EINVAL;
- }
+ 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.
- */
+ /*
+ * 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_PCSQH] != pmap_sid(pmap, gr[_REG_PCOQH])) {
+ return EINVAL;
+ }
- if (gr[_REG_PCSQT] != pmap_sid(pmap, gr[_REG_PCOQT])) {
- 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_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;
- }
+ 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)
+{
+ struct trapframe *tf = l->l_md.md_regs;
+ 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) {
+ error = cpu_mcontext_validate(l, mcp);
+ if (error)
+ return error;
+
tf->tf_ipsw = gr[0] |
(hppa_cpu_ispa20_p() ? PSW_O : 0);
tf->tf_r1 = gr[1];
Index: src/sys/arch/i386/i386/machdep.c
diff -u src/sys/arch/i386/i386/machdep.c:1.726 src/sys/arch/i386/i386/machdep.c:1.727
--- src/sys/arch/i386/i386/machdep.c:1.726 Sun Mar 4 20:44:17 2012
+++ src/sys/arch/i386/i386/machdep.c Mon May 21 14:15:17 2012
@@ -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"
@@ -1764,12 +1764,33 @@ cpu_getmcontext(struct lwp *l, mcontext_
}
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)
{
struct trapframe *tf = l->l_md.md_regs;
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 mco
} 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];
Index: src/sys/arch/m68k/m68k/sig_machdep.c
diff -u src/sys/arch/m68k/m68k/sig_machdep.c:1.48 src/sys/arch/m68k/m68k/sig_machdep.c:1.49
--- src/sys/arch/m68k/m68k/sig_machdep.c:1.48 Sun Feb 19 21:06:14 2012
+++ src/sys/arch/m68k/m68k/sig_machdep.c Mon May 21 14:15:18 2012
@@ -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
@@ -270,17 +270,29 @@ cpu_getmcontext(struct lwp *l, mcontext_
}
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) {
Index: src/sys/arch/mips/mips/cpu_subr.c
diff -u src/sys/arch/mips/mips/cpu_subr.c:1.15 src/sys/arch/mips/mips/cpu_subr.c:1.16
--- src/sys/arch/mips/mips/cpu_subr.c:1.15 Sun Feb 19 21:06:16 2012
+++ src/sys/arch/mips/mips/cpu_subr.c Mon May 21 14:15:18 2012
@@ -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"
@@ -363,16 +363,28 @@ cpu_getmcontext(struct lwp *l, mcontext_
}
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)) {
Index: src/sys/arch/mips/mips/netbsd32_machdep.c
diff -u src/sys/arch/mips/mips/netbsd32_machdep.c:1.8 src/sys/arch/mips/mips/netbsd32_machdep.c:1.9
--- src/sys/arch/mips/mips/netbsd32_machdep.c:1.8 Sun Feb 19 21:06:19 2012
+++ src/sys/arch/mips/mips/netbsd32_machdep.c Mon May 21 14:15:18 2012
@@ -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"
@@ -266,11 +266,23 @@ cpu_getmcontext32(struct lwp *l, mcontex
}
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);
Index: src/sys/arch/powerpc/powerpc/sig_machdep.c
diff -u src/sys/arch/powerpc/powerpc/sig_machdep.c:1.41 src/sys/arch/powerpc/powerpc/sig_machdep.c:1.42
--- src/sys/arch/powerpc/powerpc/sig_machdep.c:1.41 Mon Jun 20 05:50:39 2011
+++ src/sys/arch/powerpc/powerpc/sig_machdep.c Mon May 21 14:15:18 2012
@@ -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"
@@ -187,13 +187,24 @@ cpu_getmcontext(struct lwp *l, mcontext_
}
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.
Index: src/sys/arch/sh3/sh3/sh3_machdep.c
diff -u src/sys/arch/sh3/sh3/sh3_machdep.c:1.98 src/sys/arch/sh3/sh3/sh3_machdep.c:1.99
--- src/sys/arch/sh3/sh3/sh3_machdep.c:1.98 Sun Feb 19 21:06:27 2012
+++ src/sys/arch/sh3/sh3/sh3_machdep.c Mon May 21 14:15:18 2012
@@ -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"
@@ -439,17 +439,31 @@ cpu_getmcontext(struct lwp *l, mcontext_
}
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];
Index: src/sys/arch/sparc/sparc/machdep.c
diff -u src/sys/arch/sparc/sparc/machdep.c:1.318 src/sys/arch/sparc/sparc/machdep.c:1.319
--- src/sys/arch/sparc/sparc/machdep.c:1.318 Wed Apr 25 08:19:33 2012
+++ src/sys/arch/sparc/sparc/machdep.c Mon May 21 14:15:18 2012
@@ -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_
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 mco
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 mco
#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);
Index: src/sys/arch/sparc64/sparc64/machdep.c
diff -u src/sys/arch/sparc64/sparc64/machdep.c:1.266 src/sys/arch/sparc64/sparc64/machdep.c:1.267
--- src/sys/arch/sparc64/sparc64/machdep.c:1.266 Sun Feb 19 21:06:31 2012
+++ src/sys/arch/sparc64/sparc64/machdep.c Mon May 21 14:15:18 2012
@@ -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"
@@ -2534,11 +2534,29 @@ cpu_getmcontext(struct lwp *l, mcontext_
}
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 mco
}
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 mco
l->l_sigstk.ss_flags &= ~SS_ONSTACK;
mutex_exit(p->p_lock);
- return (0);
+ return 0;
}
/*
Index: src/sys/arch/sparc64/sparc64/netbsd32_machdep.c
diff -u src/sys/arch/sparc64/sparc64/netbsd32_machdep.c:1.97 src/sys/arch/sparc64/sparc64/netbsd32_machdep.c:1.98
--- src/sys/arch/sparc64/sparc64/netbsd32_machdep.c:1.97 Sun Feb 19 21:06:31 2012
+++ src/sys/arch/sparc64/sparc64/netbsd32_machdep.c Mon May 21 14:15:18 2012
@@ -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 st
}
}
+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 m
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 m
/* 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);
}
Index: src/sys/arch/vax/vax/machdep.c
diff -u src/sys/arch/vax/vax/machdep.c:1.187 src/sys/arch/vax/vax/machdep.c:1.188
--- src/sys/arch/vax/vax/machdep.c:1.187 Mon Feb 27 15:41:10 2012
+++ src/sys/arch/vax/vax/machdep.c Mon May 21 14:15:19 2012
@@ -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_
}
int
+cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp)
+{
+ const __greg_t *gr = mcp->__gregs;
+
+ 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 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;
- 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);
+ 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 mco
if (flags & _UC_TLSBASE) {
void *tlsbase;
- int error;
error = copyin((void *)tf->tf_sp, &tlsbase, sizeof(tlsbase));
if (error) {
Index: src/sys/compat/netbsd32/netbsd32_lwp.c
diff -u src/sys/compat/netbsd32/netbsd32_lwp.c:1.12 src/sys/compat/netbsd32/netbsd32_lwp.c:1.13
--- src/sys/compat/netbsd32/netbsd32_lwp.c:1.12 Sat Feb 5 13:46:44 2011
+++ src/sys/compat/netbsd32/netbsd32_lwp.c Mon May 21 14:15:19 2012
@@ -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, cons
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
Index: src/sys/compat/sys/ucontext.h
diff -u src/sys/compat/sys/ucontext.h:1.5 src/sys/compat/sys/ucontext.h:1.6
--- src/sys/compat/sys/ucontext.h:1.5 Sun Mar 18 21:48:47 2012
+++ src/sys/compat/sys/ucontext.h Mon May 21 14:15:19 2012
@@ -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) == __UCO
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 */
Index: src/sys/kern/sys_lwp.c
diff -u src/sys/kern/sys_lwp.c:1.53 src/sys/kern/sys_lwp.c:1.54
--- src/sys/kern/sys_lwp.c:1.53 Sun Feb 19 21:06:56 2012
+++ src/sys/kern/sys_lwp.c Mon May 21 14:15:19 2012
@@ -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 str
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);
@@ -148,6 +125,49 @@ sys__lwp_create(struct lwp *l, const str
}
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)
{
Index: src/sys/sys/lwp.h
diff -u src/sys/sys/lwp.h:1.160 src/sys/sys/lwp.h:1.161
--- src/sys/sys/lwp.h:1.160 Sun Feb 19 21:06:58 2012
+++ src/sys/sys/lwp.h Mon May 21 14:15:19 2012
@@ -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);
Index: src/sys/sys/ucontext.h
diff -u src/sys/sys/ucontext.h:1.15 src/sys/sys/ucontext.h:1.16
--- src/sys/sys/ucontext.h:1.15 Sun Mar 18 17:59:57 2012
+++ src/sys/sys/ucontext.h Mon May 21 14:15:19 2012
@@ -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_
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_ */
Index: src/tests/lib/libc/sys/Makefile
diff -u src/tests/lib/libc/sys/Makefile:1.22 src/tests/lib/libc/sys/Makefile:1.23
--- src/tests/lib/libc/sys/Makefile:1.22 Fri Apr 20 12:11:29 2012
+++ src/tests/lib/libc/sys/Makefile Mon May 21 14:15:19 2012
@@ -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
Added files:
Index: src/tests/lib/libc/sys/t_lwp_create.c
diff -u /dev/null src/tests/lib/libc/sys/t_lwp_create.c:1.1
--- /dev/null Mon May 21 14:15:20 2012
+++ src/tests/lib/libc/sys/t_lwp_create.c Mon May 21 14:15:19 2012
@@ -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();
+}