diff options
Diffstat (limited to 'sys/compat')
-rw-r--r-- | sys/compat/linux/linux_misc.c | 98 | ||||
-rw-r--r-- | sys/compat/linux/linux_signal.c | 58 | ||||
-rw-r--r-- | sys/compat/linux/linux_util.c | 9 |
3 files changed, 163 insertions, 2 deletions
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index e85fec31ab35..848c11493046 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -74,6 +74,7 @@ __FBSDID("$FreeBSD$"); #include <posix4/sched.h> #include <compat/linux/linux_sysproto.h> +#include <compat/linux/linux_emul.h> #ifdef COMPAT_LINUX32 #include <machine/../linux32/linux.h> @@ -93,6 +94,9 @@ __FBSDID("$FreeBSD$"); #define BSD_TO_LINUX_SIGNAL(sig) \ (((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig) +extern struct sx emul_shared_lock; +extern struct sx emul_lock; + static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = { RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK, RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE, @@ -1330,11 +1334,69 @@ linux_reboot(struct thread *td, struct linux_reboot_args *args) int linux_getpid(struct thread *td, struct linux_getpid_args *args) { + struct linux_emuldata *em; + + em = em_find(td->td_proc, EMUL_UNLOCKED); + + KASSERT(em != NULL, ("getpid: emuldata not found.\n")); + + td->td_retval[0] = em->shared->group_pid; + EMUL_UNLOCK(&emul_lock); + return (0); +} + +int +linux_gettid(struct thread *td, struct linux_gettid_args *args) +{ +#ifdef DEBUG + if (ldebug(gettid)) + printf(ARGS(gettid, "")); +#endif td->td_retval[0] = td->td_proc->p_pid; return (0); } + +int +linux_getppid(struct thread *td, struct linux_getppid_args *args) +{ + struct linux_emuldata *em; + struct proc *p, *pp; + + em = em_find(td->td_proc, EMUL_UNLOCKED); + + KASSERT(em != NULL, ("getppid: process emuldata not found.\n")); + + /* find the group leader */ + p = pfind(em->shared->group_pid); + + if (p == NULL) { +#ifdef DEBUG + printf(LMSG("parent process not found.\n")); +#endif + return (0); + } + + pp = p->p_pptr; /* switch to parent */ + PROC_LOCK(pp); + PROC_UNLOCK(p); + + /* if its also linux process */ + if (pp->p_sysent == &elf_linux_sysvec) { + em = em_find(pp, EMUL_LOCKED); + KASSERT(em != NULL, ("getppid: parent emuldata not found.\n")); + + td->td_retval[0] = em->shared->group_pid; + } else + td->td_retval[0] = pp->p_pid; + + EMUL_UNLOCK(&emul_lock); + PROC_UNLOCK(pp); + + return (0); +} + int linux_getgid(struct thread *td, struct linux_getgid_args *args) { @@ -1394,3 +1456,39 @@ linux_sethostname(struct thread *td, struct linux_sethostname_args *args) args->len, 0, 0)); } +int +linux_exit_group(struct thread *td, struct linux_exit_group_args *args) +{ + struct linux_emuldata *em, *td_em, *tmp_em; + struct proc *sp; + +#ifdef DEBUG + if (ldebug(exit_group)) + printf(ARGS(exit_group, "%i"), args->error_code); +#endif + + td_em = em_find(td->td_proc, EMUL_UNLOCKED); + + KASSERT(td_em != NULL, ("exit_group: emuldata not found.\n")); + + EMUL_SHARED_RLOCK(&emul_shared_lock); + LIST_FOREACH_SAFE(em, &td_em->shared->threads, threads, tmp_em) { + if (em->pid == td_em->pid) + continue; + + sp = pfind(em->pid); + psignal(sp, SIGKILL); + PROC_UNLOCK(sp); +#ifdef DEBUG + printf(LMSG("linux_sys_exit_group: kill PID %d\n"), em->pid); +#endif + } + + EMUL_SHARED_RUNLOCK(&emul_shared_lock); + EMUL_UNLOCK(&emul_lock); + + exit1(td, W_EXITCODE(args->error_code,0)); + + return (0); +} + diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c index 081b7c0b8035..50a05fa434e1 100644 --- a/sys/compat/linux/linux_signal.c +++ b/sys/compat/linux/linux_signal.c @@ -49,6 +49,10 @@ __FBSDID("$FreeBSD$"); #endif #include <compat/linux/linux_signal.h> #include <compat/linux/linux_util.h> +#include <compat/linux/linux_emul.h> + +extern struct sx emul_shared_lock; +extern struct sx emul_lock; void linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss) @@ -447,3 +451,57 @@ linux_kill(struct thread *td, struct linux_kill_args *args) tmp.pid = args->pid; return (kill(td, &tmp)); } + +int +linux_tgkill(struct thread *td, struct linux_tgkill_args *args) +{ + struct linux_emuldata *em; + struct linux_kill_args ka; + struct proc *p; + +#ifdef DEBUG + if (ldebug(tgkill)) + printf(ARGS(tgkill, "%d, %d, %d"), args->tgid, args->pid, args->sig); +#endif + + ka.pid = args->pid; + ka.signum = args->sig; + + if (args->tgid == -1) + return linux_kill(td, &ka); + + if ((p = pfind(args->pid)) == NULL) + return ESRCH; + + if (p->p_sysent != &elf_linux_sysvec) + return ESRCH; + + PROC_UNLOCK(p); + + em = em_find(p, EMUL_UNLOCKED); + + if (em == NULL) { +#ifdef DEBUG + printf("emuldata not found in tgkill.\n"); +#endif + return ESRCH; + } + + if (em->shared->group_pid != args->tgid) + return ESRCH; + + EMUL_UNLOCK(&emul_lock); + + return linux_kill(td, &ka); +} + +int +linux_tkill(struct thread *td, struct linux_tkill_args *args) +{ +#ifdef DEBUG + if (ldebug(tkill)) + printf(ARGS(tkill, "%i, %i"), args->tid, args->sig); +#endif + + return (linux_kill(td, (struct linux_kill_args *) args)); +} diff --git a/sys/compat/linux/linux_util.c b/sys/compat/linux/linux_util.c index 09c51311dc7c..8103c3a90838 100644 --- a/sys/compat/linux/linux_util.c +++ b/sys/compat/linux/linux_util.c @@ -32,6 +32,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include "opt_compat.h" + #include <sys/param.h> #include <sys/bus.h> #include <sys/lock.h> @@ -47,6 +49,11 @@ __FBSDID("$FreeBSD$"); #include <machine/stdarg.h> #include <compat/linux/linux_util.h> +#ifdef COMPAT_LINUX32 +#include <machine/../linux32/linux.h> +#else +#include <machine/../linux/linux.h> +#endif const char linux_emul_path[] = "/compat/linux"; @@ -85,8 +92,6 @@ linux_msg(const struct thread *td, const char *fmt, ...) printf("\n"); } -MALLOC_DECLARE(M_LINUX); - struct device_element { TAILQ_ENTRY(device_element) list; |