From 0f86c01644cc8c1781aac366d224a7646f89ba7b Mon Sep 17 00:00:00 2001 From: Michael Shalayeff Date: Thu, 29 Jan 2004 13:21:11 +0000 Subject: check struct reg for evil; from netbsd --- sys/arch/amd64/amd64/machdep.c | 40 +++++++++++++++++++++++++++++++++- sys/arch/amd64/amd64/process_machdep.c | 5 ++--- sys/arch/amd64/include/reg.h | 6 ++++- sys/arch/amd64/include/segments.h | 17 ++++++++++++++- 4 files changed, 62 insertions(+), 6 deletions(-) (limited to 'sys/arch') 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 #include #include +#include #include #include @@ -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_ */ -- cgit v1.2.3