summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/amd64/linux32/linux32_machdep.c92
-rw-r--r--sys/compat/linux/linux_misc.c14
2 files changed, 90 insertions, 16 deletions
diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c
index 01945e0..edeefc9 100644
--- a/sys/amd64/linux32/linux32_machdep.c
+++ b/sys/amd64/linux32/linux32_machdep.c
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
#include <compat/linux/linux_ipc.h>
#include <compat/linux/linux_signal.h>
#include <compat/linux/linux_util.h>
+#include <compat/linux/linux_emul.h>
struct l_old_select_argv {
l_int nfds;
@@ -211,6 +212,14 @@ linux_execve(struct thread *td, struct linux_execve_args *args)
free(path, M_TEMP);
if (error == 0)
error = kern_execve(td, &eargs, NULL);
+ if (error == 0)
+ /* linux process can exec fbsd one, dont attempt
+ * to create emuldata for such process using
+ * linux_proc_init, this leads to a panic on KASSERT
+ * because such process has p->p_emuldata == NULL
+ */
+ if (td->td_proc->p_sysent == &elf_linux_sysvec)
+ error = linux_proc_init(td, 0, 0);
return (error);
}
@@ -452,6 +461,10 @@ linux_fork(struct thread *td, struct linux_fork_args *args)
if (td->td_retval[1] == 1)
td->td_retval[0] = 0;
+ error = linux_proc_init(td, td->td_retval[0], 0);
+ if (error)
+ return (error);
+
return (0);
}
@@ -470,6 +483,9 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args)
/* Are we the child? */
if (td->td_retval[1] == 1)
td->td_retval[0] = 0;
+ error = linux_proc_init(td, td->td_retval[0], 0);
+ if (error)
+ return (error);
return (0);
}
@@ -480,12 +496,14 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
struct proc *p2;
struct thread *td2;
int exit_signal;
+ struct linux_emuldata *em;
#ifdef DEBUG
if (ldebug(clone)) {
- printf(ARGS(clone, "flags %x, stack %x"),
- (unsigned int)(uintptr_t)args->flags,
- (unsigned int)(uintptr_t)args->stack);
+ printf(ARGS(clone, "flags %x, stack %x, parent tid: %x, child tid: %x"),
+ (unsigned int)args->flags, (unsigned int)(uintptr_t)args->stack,
+ (unsigned int)(uintptr_t)args->parent_tidptr,
+ (unsigned int)(uintptr_t)args->child_tidptr);
}
#endif
@@ -503,10 +521,74 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
if (!(args->flags & CLONE_FILES))
ff |= RFFDG;
+ /*
+ * Attempt to detect when linux_clone(2) is used for creating
+ * kernel threads. Unfortunately despite the existence of the
+ * CLONE_THREAD flag, version of linuxthreads package used in
+ * most popular distros as of beginning of 2005 doesn't make
+ * any use of it. Therefore, this detection relay fully on
+ * empirical observation that linuxthreads sets certain
+ * combination of flags, so that we can make more or less
+ * precise detection and notify the FreeBSD kernel that several
+ * processes are in fact part of the same threading group, so
+ * that special treatment is necessary for signal delivery
+ * between those processes and fd locking.
+ */
+ if ((args->flags & 0xffffff00) == THREADING_FLAGS)
+ ff |= RFTHREAD;
+
error = fork1(td, ff, 0, &p2);
if (error)
return (error);
+ /* create the emuldata */
+ error = linux_proc_init(td, p2->p_pid, args->flags);
+ /* reference it - no need to check this */
+ em = em_find(p2, EMUL_UNLOCKED);
+ 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_PARENT) {
+#ifdef DEBUG
+ printf("linux_clone: CLONE_PARENT\n");
+#endif
+ }
+
+ if (args->flags & CLONE_THREAD) {
+ /* XXX: linux mangles pgrp and pptr somehow
+ * I think it might be this but I am not sure.
+ */
+#ifdef notyet
+ p2->p_pgrp = td->td_proc->p_pgrp;
+ p2->p_pptr = td->td_proc->p_pptr;
+#endif
+ exit_signal = 0;
+#ifdef DEBUG
+ printf("linux_clone: CLONE_THREADS\n");
+#endif
+ }
+
+ if (args->flags & CLONE_CHILD_SETTID)
+ em->child_set_tid = args->child_tidptr;
+ else
+ em->child_set_tid = NULL;
+
+ if (args->flags & CLONE_CHILD_CLEARTID)
+ em->child_clear_tid = args->child_tidptr;
+ else
+ em->child_clear_tid = NULL;
+ EMUL_UNLOCK(&emul_lock);
PROC_LOCK(p2);
p2->p_sigparent = exit_signal;
@@ -519,6 +601,10 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
if (args->stack)
td2->td_frame->tf_rsp = PTROUT(args->stack);
+ if (args->flags & CLONE_SETTLS) {
+ /* XXX: todo */
+ }
+
#ifdef DEBUG
if (ldebug(clone))
printf(LMSG("clone: successful rfork to %ld, stack %p sig = %d"),
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index d8be75a..f394e55 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -1331,7 +1331,6 @@ linux_reboot(struct thread *td, struct linux_reboot_args *args)
int
linux_getpid(struct thread *td, struct linux_getpid_args *args)
{
-#ifdef __i386__
struct linux_emuldata *em;
char osrel[LINUX_MAX_UTSNAME];
@@ -1346,11 +1345,7 @@ linux_getpid(struct thread *td, struct linux_getpid_args *args)
td->td_retval[0] = td->td_proc->p_pid;
PROC_UNLOCK(td->td_proc);
}
-#else
- PROC_LOCK(td->td_proc);
- td->td_retval[0] = td->td_proc->p_pid;
- PROC_UNLOCK(td->td_proc);
-#endif
+
return (0);
}
@@ -1370,7 +1365,6 @@ linux_gettid(struct thread *td, struct linux_gettid_args *args)
int
linux_getppid(struct thread *td, struct linux_getppid_args *args)
{
-#ifdef __i386__
struct linux_emuldata *em;
struct proc *p, *pp;
char osrel[LINUX_MAX_UTSNAME];
@@ -1412,9 +1406,6 @@ linux_getppid(struct thread *td, struct linux_getppid_args *args)
EMUL_UNLOCK(&emul_lock);
PROC_UNLOCK(pp);
-#else
- return getppid(td, (struct getppid_args *) args);
-#endif
return (0);
}
@@ -1481,7 +1472,6 @@ linux_sethostname(struct thread *td, struct linux_sethostname_args *args)
int
linux_exit_group(struct thread *td, struct linux_exit_group_args *args)
{
-#ifdef __i386__
struct linux_emuldata *em, *td_em, *tmp_em;
struct proc *sp;
char osrel[LINUX_MAX_UTSNAME];
@@ -1513,10 +1503,8 @@ linux_exit_group(struct thread *td, struct linux_exit_group_args *args)
EMUL_SHARED_RUNLOCK(&emul_shared_lock);
EMUL_UNLOCK(&emul_lock);
}
-#endif
exit1(td, W_EXITCODE(args->error_code,0));
return (0);
}
-
OpenPOWER on IntegriCloud