summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Guenthe <guenther@cvs.openbsd.org>2011-08-03 16:11:32 +0000
committerPhilip Guenthe <guenther@cvs.openbsd.org>2011-08-03 16:11:32 +0000
commitc521aa1be51fe6cf5c467fd0dd8c63377aa82f83 (patch)
treedbdc126a15d9488fa08d66bc893d717579946750
parentbd7ebeca9ddd78842746f38aa29b57d1c8305add (diff)
Fix linux compat breakage: can't copyin() from kernel-space, so
move that out of i386_set_threadbase(), and have clone() pass NULL to fork1() for the child func argument so that it gets the child proc pointer. Report and verification by pirofti@, heavy lifting by matthew@
-rw-r--r--sys/arch/i386/i386/linux_machdep.c4
-rw-r--r--sys/arch/i386/i386/sys_machdep.c27
-rw-r--r--sys/arch/i386/include/sysarch.h4
-rw-r--r--sys/compat/linux/linux_sched.c7
4 files changed, 23 insertions, 19 deletions
diff --git a/sys/arch/i386/i386/linux_machdep.c b/sys/arch/i386/i386/linux_machdep.c
index 96b0ecb52e3..c9c8a5c5b00 100644
--- a/sys/arch/i386/i386/linux_machdep.c
+++ b/sys/arch/i386/i386/linux_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: linux_machdep.c,v 1.40 2011/07/05 04:48:01 guenther Exp $ */
+/* $OpenBSD: linux_machdep.c,v 1.41 2011/08/03 16:11:31 guenther Exp $ */
/* $NetBSD: linux_machdep.c,v 1.29 1996/05/03 19:42:11 christos Exp $ */
/*
@@ -653,7 +653,7 @@ linux_sys_set_thread_area(struct proc *p, void *v, register_t *retval)
} else if (ldesc.entry_number != GUGS_SEL)
return EINVAL;
- return i386_set_threadbase(p, &SCARG(uap, desc)->base_addr, TSEG_GS);
+ return i386_set_threadbase(p, SCARG(uap, desc)->base_addr, TSEG_GS);
}
int
diff --git a/sys/arch/i386/i386/sys_machdep.c b/sys/arch/i386/i386/sys_machdep.c
index cfc7827c347..0289edbaf0b 100644
--- a/sys/arch/i386/i386/sys_machdep.c
+++ b/sys/arch/i386/i386/sys_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sys_machdep.c,v 1.29 2011/04/15 15:08:19 chl Exp $ */
+/* $OpenBSD: sys_machdep.c,v 1.30 2011/08/03 16:11:31 guenther Exp $ */
/* $NetBSD: sys_machdep.c,v 1.28 1996/05/03 19:42:29 christos Exp $ */
/*-
@@ -72,8 +72,6 @@ extern struct vm_map *kernel_map;
int i386_iopl(struct proc *, void *, register_t *);
int i386_get_ioperm(struct proc *, void *, register_t *);
int i386_set_ioperm(struct proc *, void *, register_t *);
-int i386_get_threadbase(struct proc *, void *, int);
-int i386_set_threadbase(struct proc *, void *, int);
#ifdef USER_LDT
@@ -405,15 +403,10 @@ i386_get_threadbase(struct proc *p, void *args, int which)
}
int
-i386_set_threadbase(struct proc *p, void *args, int which)
+i386_set_threadbase(struct proc *p, uint32_t base, int which)
{
- int error;
- uint32_t base;
struct segment_descriptor *sdp;
- if ((error = copyin(args, &base, sizeof(base))) != 0)
- return error;
-
/*
* We can't place a limit on the segment used by the library
* thread register (%gs) because the ELF ABI for i386 places
@@ -472,16 +465,28 @@ sys_sysarch(struct proc *p, void *v, register_t *retval)
break;
case I386_SET_FSBASE:
- error = i386_set_threadbase(p, SCARG(uap, parms), TSEG_FS);
+ {
+ uint32_t base;
+
+ if ((error = copyin(SCARG(uap, parms), &base, sizeof(base))))
+ break;
+ error = i386_set_threadbase(p, base, TSEG_FS);
break;
+ }
case I386_GET_GSBASE:
error = i386_get_threadbase(p, SCARG(uap, parms), TSEG_GS);
break;
case I386_SET_GSBASE:
- error = i386_set_threadbase(p, SCARG(uap, parms), TSEG_GS);
+ {
+ uint32_t base;
+
+ if ((error = copyin(SCARG(uap, parms), &base, sizeof(base))))
+ break;
+ error = i386_set_threadbase(p, base, TSEG_GS);
break;
+ }
default:
error = EINVAL;
diff --git a/sys/arch/i386/include/sysarch.h b/sys/arch/i386/include/sysarch.h
index 04e50fab3bd..116325310cd 100644
--- a/sys/arch/i386/include/sysarch.h
+++ b/sys/arch/i386/include/sysarch.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysarch.h,v 1.8 2011/04/04 21:50:41 pirofti Exp $ */
+/* $OpenBSD: sysarch.h,v 1.9 2011/08/03 16:11:31 guenther Exp $ */
/* $NetBSD: sysarch.h,v 1.8 1996/01/08 13:51:44 mycroft Exp $ */
#ifndef _MACHINE_SYSARCH_H_
@@ -55,7 +55,7 @@ int i386_set_gsbase(void *);
int sysarch(int, void *);
#else
int i386_get_threadbase(struct proc *, void *, int);
-int i386_set_threadbase(struct proc *, void *, int);
+int i386_set_threadbase(struct proc *, uint32_t, int);
#endif
#endif /* !_MACHINE_SYSARCH_H_ */
diff --git a/sys/compat/linux/linux_sched.c b/sys/compat/linux/linux_sched.c
index 61a4b5b98ad..14b00c23bf8 100644
--- a/sys/compat/linux/linux_sched.c
+++ b/sys/compat/linux/linux_sched.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: linux_sched.c,v 1.10 2011/04/05 15:44:40 pirofti Exp $ */
+/* $OpenBSD: linux_sched.c,v 1.11 2011/08/03 16:11:31 guenther Exp $ */
/* $NetBSD: linux_sched.c,v 1.6 2000/05/28 05:49:05 thorpej Exp $ */
/*-
@@ -177,7 +177,7 @@ linux_sys_clone(struct proc *p, void *v, register_t *retval)
* that makes this adjustment is a noop.
*/
error = fork1(p, sig, flags, SCARG(uap, stack), 0, linux_child_return,
- p, retval, NULL);
+ NULL, retval, NULL);
if (error)
return error;
@@ -407,8 +407,7 @@ linux_child_return(void *arg)
struct proc *p = (struct proc *)arg;
struct linux_emuldata *emul = p->p_emuldata;
- if (i386_set_threadbase(p, &emul->my_tls_base, TSEG_GS))
- return;
+ i386_set_threadbase(p, emul->my_tls_base, TSEG_GS);
if (emul->my_set_tid) {
pid_t pid = p->p_pid + THREAD_PID_OFFSET;