summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authornetchild <netchild@FreeBSD.org>2007-02-23 22:39:26 +0000
committernetchild <netchild@FreeBSD.org>2007-02-23 22:39:26 +0000
commit902cc4aebabcbc802991bdb0b03f04e600fd8452 (patch)
treeee0d5379699a26a3d09a50992f83344be0588450 /sys
parentd0c562e57ca3e3905157ccbd79fa4efa843088c3 (diff)
downloadFreeBSD-src-902cc4aebabcbc802991bdb0b03f04e600fd8452.zip
FreeBSD-src-902cc4aebabcbc802991bdb0b03f04e600fd8452.tar.gz
MFp4 (114193 (i386 part), 114194, 114195, 114200):
- Dont "return" in linux_clone() after we forked the new process in a case of problems. - Move the copyout of p2->p_pid outside the emul_lock coverage in linux_clone(). - Cache the em->pdeath_signal in a local variable and move the copyout out of the emul_lock coverage. - Move the free() out of the emul_shared_lock coverage in a preparation to switch emul_lock to non-sleepable lock (mutex). Submitted by: rdivacky
Diffstat (limited to 'sys')
-rw-r--r--sys/compat/linux/linux_emul.c12
-rw-r--r--sys/compat/linux/linux_misc.c8
-rw-r--r--sys/i386/linux/linux_machdep.c81
3 files changed, 55 insertions, 46 deletions
diff --git a/sys/compat/linux/linux_emul.c b/sys/compat/linux/linux_emul.c
index 2a42f70..c2f6db1 100644
--- a/sys/compat/linux/linux_emul.c
+++ b/sys/compat/linux/linux_emul.c
@@ -186,9 +186,11 @@ linux_proc_exit(void *arg __unused, struct proc *p)
LIST_REMOVE(em, threads);
em->shared->refs--;
- if (em->shared->refs == 0)
+ if (em->shared->refs == 0) {
+ EMUL_SHARED_WUNLOCK(&emul_shared_lock);
free(em->shared, M_LINUX);
- EMUL_SHARED_WUNLOCK(&emul_shared_lock);
+ } else
+ EMUL_SHARED_WUNLOCK(&emul_shared_lock);
if (child_clear_tid != NULL) {
struct linux_sys_futex_args cup;
@@ -273,9 +275,11 @@ linux_proc_exec(void *arg __unused, struct proc *p, struct image_params *imgp)
PROC_UNLOCK(p);
em->shared->refs--;
- if (em->shared->refs == 0)
+ if (em->shared->refs == 0) {
+ EMUL_SHARED_WUNLOCK(&emul_shared_lock);
free(em->shared, M_LINUX);
- EMUL_SHARED_WUNLOCK(&emul_shared_lock);
+ } else
+ EMUL_SHARED_WUNLOCK(&emul_shared_lock);
free(em, M_LINUX);
}
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index 02d86f9..f5504dc 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -1642,6 +1642,7 @@ linux_prctl(struct thread *td, struct linux_prctl_args *args)
struct proc *p = td->td_proc;
char comm[LINUX_MAX_COMM_LEN];
struct linux_emuldata *em;
+ int pdeath_signal;
#ifdef DEBUG
if (ldebug(prctl))
@@ -1661,10 +1662,11 @@ linux_prctl(struct thread *td, struct linux_prctl_args *args)
case LINUX_PR_GET_PDEATHSIG:
em = em_find(p, EMUL_DOLOCK);
KASSERT(em != NULL, ("prctl: emuldata not found.\n"));
- error = copyout(&em->pdeath_signal,
- (void *)(register_t)args->arg2,
- sizeof(em->pdeath_signal));
+ pdeath_signal = em->pdeath_signal;
EMUL_UNLOCK(&emul_lock);
+ error = copyout(&pdeath_signal,
+ (void *)(register_t)args->arg2,
+ sizeof(pdeath_signal));
break;
case LINUX_PR_SET_NAME:
/*
diff --git a/sys/i386/linux/linux_machdep.c b/sys/i386/linux/linux_machdep.c
index e909d51..70f81f4 100644
--- a/sys/i386/linux/linux_machdep.c
+++ b/sys/i386/linux/linux_machdep.c
@@ -435,6 +435,10 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
if ((args->flags & 0xffffff00) == THREADING_FLAGS)
ff |= RFTHREAD;
+ if (args->flags & CLONE_PARENT_SETTID)
+ if (args->parent_tidptr == NULL)
+ return (EINVAL);
+
error = fork1(td, ff, 0, &p2);
if (error)
return (error);
@@ -453,17 +457,6 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
em = em_find(p2, EMUL_DOLOCK);
KASSERT(em != NULL, ("clone: emuldata not found.\n"));
/* and adjust it */
- if (args->flags & CLONE_PARENT_SETTID) {
- if (args->parent_tidptr == NULL) {
- EMUL_UNLOCK(&emul_lock);
- return (EINVAL);
- }
- error = copyout(&p2->p_pid, args->parent_tidptr, sizeof(p2->p_pid));
- if (error) {
- EMUL_UNLOCK(&emul_lock);
- return (error);
- }
- }
if (args->flags & CLONE_THREAD) {
/* XXX: linux mangles pgrp and pptr somehow
@@ -489,6 +482,12 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
EMUL_UNLOCK(&emul_lock);
+ if (args->flags & CLONE_PARENT_SETTID) {
+ error = copyout(&p2->p_pid, args->parent_tidptr, sizeof(p2->p_pid));
+ if (error)
+ printf(LMSG("copyout failed!"));
+ }
+
PROC_LOCK(p2);
p2->p_sigparent = exit_signal;
PROC_UNLOCK(p2);
@@ -507,34 +506,37 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
struct segment_descriptor sd;
error = copyin((void *)td->td_frame->tf_esi, &info, sizeof(struct l_user_desc));
- if (error)
- return (error);
+ if (error) {
+ printf(LMSG("copyin failed!"));
+ } else {
- idx = info.entry_number;
+ idx = info.entry_number;
- /*
- * looks like we're getting the idx we returned
- * in the set_thread_area() syscall
- */
- if (idx != 6 && idx != 3)
- return (EINVAL);
-
- /* this doesnt happen in practice */
- if (idx == 6) {
- /* we might copy out the entry_number as 3 */
- info.entry_number = 3;
- error = copyout(&info, (void *) td->td_frame->tf_esi, sizeof(struct l_user_desc));
- if (error)
- return (error);
- }
-
- a[0] = LDT_entry_a(&info);
- a[1] = LDT_entry_b(&info);
-
- memcpy(&sd, &a, sizeof(a));
+ /*
+ * looks like we're getting the idx we returned
+ * in the set_thread_area() syscall
+ */
+ if (idx != 6 && idx != 3) {
+ printf(LMSG("resetting idx!"));
+ idx = 3;
+ }
+
+ /* this doesnt happen in practice */
+ if (idx == 6) {
+ /* we might copy out the entry_number as 3 */
+ info.entry_number = 3;
+ error = copyout(&info, (void *) td->td_frame->tf_esi, sizeof(struct l_user_desc));
+ if (error)
+ printf(LMSG("copyout failed!"));
+ }
+
+ a[0] = LDT_entry_a(&info);
+ a[1] = LDT_entry_b(&info);
+
+ memcpy(&sd, &a, sizeof(a));
#ifdef DEBUG
- if (ldebug(clone))
- printf("Segment created in clone with CLONE_SETTLS: lobase: %x, hibase: %x, lolimit: %x, hilimit: %x, type: %i, dpl: %i, p: %i, xx: %i, def32: %i, gran: %i\n", sd.sd_lobase,
+ if (ldebug(clone))
+ printf("Segment created in clone with CLONE_SETTLS: lobase: %x, hibase: %x, lolimit: %x, hilimit: %x, type: %i, dpl: %i, p: %i, xx: %i, def32: %i, gran: %i\n", sd.sd_lobase,
sd.sd_hibase,
sd.sd_lolimit,
sd.sd_hilimit,
@@ -546,9 +548,10 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
sd.sd_gran);
#endif
- /* set %gs */
- td2->td_pcb->pcb_gsd = sd;
- td2->td_pcb->pcb_gs = GSEL(GUGS_SEL, SEL_UPL);
+ /* set %gs */
+ td2->td_pcb->pcb_gsd = sd;
+ td2->td_pcb->pcb_gs = GSEL(GUGS_SEL, SEL_UPL);
+ }
}
#ifdef DEBUG
OpenPOWER on IntegriCloud