summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/amd64/amd64/machdep.c40
-rw-r--r--sys/arch/amd64/amd64/process_machdep.c5
-rw-r--r--sys/arch/amd64/include/reg.h6
-rw-r--r--sys/arch/amd64/include/segments.h17
4 files changed, 62 insertions, 6 deletions
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index bd4cd513785..56ba54d60da 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $OpenBSD: machdep.c,v 1.2 2004/01/29 13:21:10 mickey Exp $ */
/* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
/*-
@@ -124,6 +124,7 @@
#include <machine/fpu.h>
#include <machine/mtrr.h>
#include <machine/mpbiosvar.h>
+#include <machine/reg.h>
#include <dev/isa/isareg.h>
#include <machine/isa_machdep.h>
@@ -1872,3 +1873,40 @@ splassert_check(int wantipl, const char *func)
}
#endif
+int
+check_context(const struct reg *regs, struct trapframe *tf)
+{
+ uint16_t sel;
+
+ if (((regs->r_rflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0)
+ return EINVAL;
+
+ sel = regs->r_es & 0xffff;
+ if (sel != 0 && !VALID_USER_DSEL(sel))
+ return EINVAL;
+
+ sel = regs->r_fs & 0xffff;
+ if (sel != 0 && !VALID_USER_DSEL(sel))
+ return EINVAL;
+
+ sel = regs->r_gs & 0xffff;
+ if (sel != 0 && !VALID_USER_DSEL(sel))
+ return EINVAL;
+
+ sel = regs->r_ds & 0xffff;
+ if (!VALID_USER_DSEL(sel))
+ return EINVAL;
+
+ sel = regs->r_ss & 0xffff;
+ if (!VALID_USER_DSEL(sel))
+ return EINVAL;
+
+ sel = regs->r_cs & 0xffff;
+ if (!VALID_USER_CSEL(sel))
+ return EINVAL;
+
+ if (regs->r_rip >= VM_MAXUSER_ADDRESS)
+ return EINVAL;
+
+ return 0;
+}
diff --git a/sys/arch/amd64/amd64/process_machdep.c b/sys/arch/amd64/amd64/process_machdep.c
index a7982608504..b7c607cd1f0 100644
--- a/sys/arch/amd64/amd64/process_machdep.c
+++ b/sys/arch/amd64/amd64/process_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: process_machdep.c,v 1.2 2004/01/29 12:43:35 mickey Exp $ */
+/* $OpenBSD: process_machdep.c,v 1.3 2004/01/29 13:21:10 mickey Exp $ */
/* $NetBSD: process_machdep.c,v 1.1 2003/04/26 18:39:31 fvdl Exp $ */
/*-
@@ -165,8 +165,7 @@ process_write_regs(struct proc *p, struct reg *regs)
/*
* Check for security violations.
*/
- if (((regs->r_rflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0 ||
- !USERMODE(regs->r_cs, regs->r_rflags))
+ if (check_context(regs, tf))
return (EINVAL);
tf->tf_rdi = regs->r_rdi;
diff --git a/sys/arch/amd64/include/reg.h b/sys/arch/amd64/include/reg.h
index d2ab5521203..293d1fbf403 100644
--- a/sys/arch/amd64/include/reg.h
+++ b/sys/arch/amd64/include/reg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: reg.h,v 1.2 2004/01/29 12:43:35 mickey Exp $ */
+/* $OpenBSD: reg.h,v 1.3 2004/01/29 13:21:10 mickey Exp $ */
/* $NetBSD: reg.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */
/*-
@@ -125,4 +125,8 @@ struct fpreg {
#define fp_st fxstate.fx_st
#define fp_xmm fxstate.fx_xmm
+#ifdef _KERNEL
+int check_context(const struct reg *, struct trapframe *);
+#endif
+
#endif /* !_AMD64_REG_H_ */
diff --git a/sys/arch/amd64/include/segments.h b/sys/arch/amd64/include/segments.h
index 636f3a38fee..58890114e6a 100644
--- a/sys/arch/amd64/include/segments.h
+++ b/sys/arch/amd64/include/segments.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: segments.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $OpenBSD: segments.h,v 1.2 2004/01/29 13:21:10 mickey Exp $ */
/* $NetBSD: segments.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */
/*-
@@ -302,4 +302,19 @@ void cpu_init_idt(void);
#define LSYSRETBASE_SEL LUCODE32_SEL
+/*
+ * Checks for valid user selectors. If USER_LDT ever gets implemented
+ * for amd64, these must check the ldt length and SEL_UPL if a user
+ * ldt is active.
+ */
+#define VALID_USER_DSEL32(s) \
+ ((s) == GSEL(GUDATA32_SEL, SEL_UPL) || (s) == LSEL(LUDATA32_SEL, SEL_UPL))
+#define VALID_USER_CSEL32(s) \
+ ((s) == GSEL(GUCODE32_SEL, SEL_UPL) || (s) == LSEL(LUCODE32_SEL, SEL_UPL))
+
+#define VALID_USER_CSEL(s) \
+ ((s) == GSEL(GUCODE_SEL, SEL_UPL) || (s) == LSEL(LUCODE_SEL, SEL_UPL))
+#define VALID_USER_DSEL(s) \
+ ((s) == GSEL(GUDATA_SEL, SEL_UPL) || (s) == LSEL(LUDATA_SEL, SEL_UPL))
+
#endif /* _AMD64_SEGMENTS_H_ */