Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src Calling _lwp_create() with a bogus ucontext could trigger a ...
details: https://anonhg.NetBSD.org/src/rev/cc06828721a3
branches: trunk
changeset: 779346:cc06828721a3
user: martin <martin%NetBSD.org@localhost>
date: Mon May 21 14:15:16 2012 +0000
description:
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.
diffstat:
distrib/sets/lists/tests/mi | 4 +-
lib/libc/sys/_lwp_create.2 | 11 +-
sys/arch/alpha/alpha/machdep.c | 22 +-
sys/arch/amd64/amd64/machdep.c | 9 +-
sys/arch/amd64/amd64/netbsd32_machdep.c | 11 +-
sys/arch/amd64/amd64/process_machdep.c | 6 +-
sys/arch/amd64/include/mcontext.h | 6 +-
sys/arch/arm/arm/sig_machdep.c | 22 +-
sys/arch/hppa/hppa/hppa_machdep.c | 76 ++++---
sys/arch/i386/i386/machdep.c | 43 +++-
sys/arch/m68k/m68k/sig_machdep.c | 24 ++-
sys/arch/mips/mips/cpu_subr.c | 18 +-
sys/arch/mips/mips/netbsd32_machdep.c | 18 +-
sys/arch/powerpc/powerpc/sig_machdep.c | 15 +-
sys/arch/sh3/sh3/sh3_machdep.c | 22 ++-
sys/arch/sparc/sparc/machdep.c | 37 ++-
sys/arch/sparc64/sparc64/machdep.c | 35 ++-
sys/arch/sparc64/sparc64/netbsd32_machdep.c | 36 ++-
sys/arch/vax/vax/machdep.c | 26 ++-
sys/compat/netbsd32/netbsd32_lwp.c | 42 +++-
sys/compat/sys/ucontext.h | 3 +-
sys/kern/sys_lwp.c | 84 +++++---
sys/sys/lwp.h | 3 +-
sys/sys/ucontext.h | 3 +-
tests/lib/libc/sys/Makefile | 3 +-
tests/lib/libc/sys/t_lwp_create.c | 247 ++++++++++++++++++++++++++++
26 files changed, 642 insertions(+), 184 deletions(-)
diffs (truncated from 1541 to 300 lines):
diff -r 122f01689cfa -r cc06828721a3 distrib/sets/lists/tests/mi
--- a/distrib/sets/lists/tests/mi Mon May 21 08:14:58 2012 +0000
+++ b/distrib/sets/lists/tests/mi Mon May 21 14:15:16 2012 +0000
@@ -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
diff -r 122f01689cfa -r cc06828721a3 lib/libc/sys/_lwp_create.2
--- a/lib/libc/sys/_lwp_create.2 Mon May 21 08:14:58 2012 +0000
+++ b/lib/libc/sys/_lwp_create.2 Mon May 21 14:15:16 2012 +0000
@@ -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 @@
.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 @@
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 @@
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 ,
diff -r 122f01689cfa -r cc06828721a3 sys/arch/alpha/alpha/machdep.c
--- a/sys/arch/alpha/alpha/machdep.c Mon May 21 08:14:58 2012 +0000
+++ b/sys/arch/alpha/alpha/machdep.c Mon May 21 14:15:16 2012 +0000
@@ -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 @@
}
}
+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 @@
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)
diff -r 122f01689cfa -r cc06828721a3 sys/arch/amd64/amd64/machdep.c
--- a/sys/arch/amd64/amd64/machdep.c Mon May 21 08:14:58 2012 +0000
+++ b/sys/arch/amd64/amd64/machdep.c Mon May 21 14:15:16 2012 +0000
@@ -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 @@
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 @@
}
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;
diff -r 122f01689cfa -r cc06828721a3 sys/arch/amd64/amd64/netbsd32_machdep.c
--- a/sys/arch/amd64/amd64/netbsd32_machdep.c Mon May 21 08:14:58 2012 +0000
+++ b/sys/arch/amd64/amd64/netbsd32_machdep.c Mon May 21 14:15:16 2012 +0000
@@ -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 @@
#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 @@
/*
* Check for security violations.
*/
- error = check_mcontext32(l, mcp);
+ error = cpu_mcontext32_validate(l, mcp);
if (error != 0)
return error;
@@ -984,8 +983,8 @@
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;
diff -r 122f01689cfa -r cc06828721a3 sys/arch/amd64/amd64/process_machdep.c
--- a/sys/arch/amd64/amd64/process_machdep.c Mon May 21 08:14:58 2012 +0000
+++ b/sys/arch/amd64/amd64/process_machdep.c Mon May 21 14:15:16 2012 +0000
@@ -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 @@
* 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;
diff -r 122f01689cfa -r cc06828721a3 sys/arch/amd64/include/mcontext.h
--- a/sys/arch/amd64/include/mcontext.h Mon May 21 08:14:58 2012 +0000
+++ b/sys/arch/amd64/include/mcontext.h Mon May 21 14:15:16 2012 +0000
@@ -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 @@
#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__ */
diff -r 122f01689cfa -r cc06828721a3 sys/arch/arm/arm/sig_machdep.c
--- a/sys/arch/arm/arm/sig_machdep.c Mon May 21 08:14:58 2012 +0000
+++ b/sys/arch/arm/arm/sig_machdep.c Mon May 21 14:15:16 2012 +0000
@@ -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 @@
}
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);
Home |
Main Index |
Thread Index |
Old Index