diff options
author | netchild <netchild@FreeBSD.org> | 2007-02-23 22:39:26 +0000 |
---|---|---|
committer | netchild <netchild@FreeBSD.org> | 2007-02-23 22:39:26 +0000 |
commit | 902cc4aebabcbc802991bdb0b03f04e600fd8452 (patch) | |
tree | ee0d5379699a26a3d09a50992f83344be0588450 /sys | |
parent | d0c562e57ca3e3905157ccbd79fa4efa843088c3 (diff) | |
download | FreeBSD-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.c | 12 | ||||
-rw-r--r-- | sys/compat/linux/linux_misc.c | 8 | ||||
-rw-r--r-- | sys/i386/linux/linux_machdep.c | 81 |
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 |