1 /* $NetBSD: linux_exec.c,v 1.112 2009/03/15 15:55:51 cegger Exp $ */
4 * Copyright (c) 1994, 1995, 1998, 2000, 2007, 2008 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas, Frank van der Linden, Eric Haszlakiewicz and
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: linux_exec.c,v 1.112 2009/03/15 15:55:51 cegger Exp $");
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/namei.h>
42 #include <sys/vnode.h>
43 #include <sys/mount.h>
45 #include <sys/exec_elf.h>
48 #include <sys/syscallargs.h>
50 #include <sys/ptrace.h> /* For proc_reparent() */
52 #include <uvm/uvm_extern.h>
55 #include <machine/reg.h>
57 #include <compat/linux/common/linux_types.h>
58 #include <compat/linux/common/linux_signal.h>
59 #include <compat/linux/common/linux_util.h>
60 #include <compat/linux/common/linux_sched.h>
61 #include <compat/linux/common/linux_machdep.h>
62 #include <compat/linux/common/linux_exec.h>
63 #include <compat/linux/common/linux_futex.h>
64 #include <compat/linux/common/linux_ipc.h>
65 #include <compat/linux/common/linux_sem.h>
67 #include <compat/linux/linux_syscallargs.h>
68 #include <compat/linux/linux_syscall.h>
69 #include <compat/linux/common/linux_misc.h>
70 #include <compat/linux/common/linux_errno.h>
71 #include <compat/linux/common/linux_emuldata.h>
73 extern struct sysent linux_sysent
[];
74 extern const char * const linux_syscallnames
[];
75 extern char linux_sigcode
[], linux_esigcode
[];
77 static void linux_e_proc_exec(struct proc
*, struct exec_package
*);
78 static void linux_e_proc_fork(struct proc
*, struct proc
*, int);
79 static void linux_e_proc_exit(struct proc
*);
80 static void linux_e_proc_init(struct proc
*, struct proc
*, int);
83 void linux_userret(void);
90 struct uvm_object
*emul_linux_object
;
92 struct emul emul_linux
= {
94 .e_path
= "/emul/linux",
95 #ifndef __HAVE_MINIMAL_EMUL
97 .e_errno
= (const int *)native_to_linux_errno
,
98 .e_nosys
= LINUX_SYS_syscall
,
99 .e_nsysent
= LINUX_SYS_NSYSENT
,
101 .e_sysent
= linux_sysent
,
102 .e_syscallnames
= linux_syscallnames
,
103 .e_sendsig
= linux_sendsig
,
104 .e_trapsignal
= linux_trapsignal
,
106 .e_sigcode
= linux_sigcode
,
107 .e_esigcode
= linux_esigcode
,
108 .e_sigobject
= &emul_linux_object
,
109 .e_setregs
= linux_setregs
,
110 .e_proc_exec
= linux_e_proc_exec
,
111 .e_proc_fork
= linux_e_proc_fork
,
112 .e_proc_exit
= linux_e_proc_exit
,
115 #ifdef __HAVE_SYSCALL_INTERN
116 .e_syscall_intern
= linux_syscall_intern
,
118 #error Implement __HAVE_SYSCALL_INTERN for this platform
120 .e_sysctlovly
= NULL
,
122 .e_vm_default_addr
= uvm_default_mapaddr
,
123 .e_usertrap
= linux_usertrap
,
130 linux_e_proc_init(struct proc
*p
, struct proc
*parent
, int forkflags
)
132 struct linux_emuldata
*e
= p
->p_emuldata
;
133 struct linux_emuldata_shared
*s
;
134 struct linux_emuldata
*ep
= NULL
;
137 /* allocate new Linux emuldata */
138 e
= malloc(sizeof(struct linux_emuldata
),
139 M_EMULDATA
, M_WAITOK
);
141 mutex_enter(proc_lock
);
144 free(e
->s
, M_EMULDATA
);
145 mutex_exit(proc_lock
);
148 memset(e
, '\0', sizeof(struct linux_emuldata
));
151 e
->robust_futexes
= NULL
;
154 ep
= parent
->p_emuldata
;
156 if (forkflags
& FORK_SHAREVM
) {
157 mutex_enter(proc_lock
);
160 killproc(p
, "FORK_SHAREVM while emuldata is NULL\n");
161 mutex_exit(proc_lock
);
171 s
= malloc(sizeof(struct linux_emuldata_shared
),
172 M_EMULDATA
, M_WAITOK
);
176 * Set the process idea of the break to the real value.
177 * For fork, we use parent's vmspace since our's
178 * is not setup at the time of this call and is going
179 * to be copy of parent's anyway. For exec, just
180 * use our own vmspace.
182 vm
= (parent
) ? parent
->p_vmspace
: p
->p_vmspace
;
183 s
->p_break
= (char *)vm
->vm_daddr
+ ctob(vm
->vm_dsize
);
186 * Linux threads are emulated as NetBSD processes (not lwp)
187 * We use native PID for Linux TID. The Linux TID is the
188 * PID of the first process in the group. It is stored
191 s
->group_pid
= p
->p_pid
;
194 * Initialize the list of threads in the group
196 LIST_INIT(&s
->threads
);
200 mutex_enter(proc_lock
);
206 * Add this thread in the group thread list
208 LIST_INSERT_HEAD(&s
->threads
, e
, threads
);
212 e
->parent_tidptr
= ep
->parent_tidptr
;
213 e
->child_tidptr
= ep
->child_tidptr
;
214 e
->clone_flags
= ep
->clone_flags
;
216 #endif /* LINUX_NPTL */
218 mutex_exit(proc_lock
);
223 * Allocate new per-process structures. Called when executing Linux
224 * process. We can reuse the old emuldata - if it's not null,
225 * the executed process is of same emulation as original forked one.
228 linux_e_proc_exec(struct proc
*p
, struct exec_package
*epp
)
231 /* exec, use our vmspace */
232 linux_e_proc_init(p
, NULL
, 0);
236 * Emulation per-process exit hook.
239 linux_e_proc_exit(struct proc
*p
)
241 struct linux_emuldata
*e
= p
->p_emuldata
;
244 linux_nptl_proc_exit(p
);
248 /* Remove the thread for the group thread list */
249 mutex_enter(proc_lock
);
250 LIST_REMOVE(e
, threads
);
252 /* free Linux emuldata and set the pointer to null */
255 free(e
->s
, M_EMULDATA
);
256 p
->p_emuldata
= NULL
;
257 mutex_exit(proc_lock
);
262 * Emulation fork hook.
265 linux_e_proc_fork(struct proc
*p
, struct proc
*parent
, int forkflags
)
269 * The new process might share some vmspace-related stuff
270 * with parent, depending on fork flags (CLONE_VM et.al).
271 * Force allocation of new base emuldata, and share the
272 * VM-related parts only if necessary.
274 p
->p_emuldata
= NULL
;
275 linux_e_proc_init(p
, parent
, forkflags
);
278 linux_nptl_proc_fork(p
, parent
, linux_userret
);
288 struct lwp
*l
= curlwp
;
289 struct proc
*p
= l
->l_proc
;
290 struct linux_emuldata
*led
= p
->p_emuldata
;
293 /* LINUX_CLONE_CHILD_SETTID: copy child's TID to child's memory */
294 if (led
->clone_flags
& LINUX_CLONE_CHILD_SETTID
) {
295 if ((error
= copyout(&l
->l_proc
->p_pid
,
296 led
->child_tidptr
, sizeof(l
->l_proc
->p_pid
))) != 0)
297 printf("linux_userret: LINUX_CLONE_CHILD_SETTID "
298 "failed (led->child_tidptr = %p, p->p_pid = %d)\n",
299 led
->child_tidptr
, p
->p_pid
);
302 /* LINUX_CLONE_SETTLS: allocate a new TLS */
303 if (led
->clone_flags
& LINUX_CLONE_SETTLS
) {
304 if (linux_set_newtls(l
, linux_get_newtls(l
)) != 0)
305 printf("linux_userret: linux_set_tls failed");
312 linux_nptl_proc_exit(struct proc
*p
)
314 struct linux_emuldata
*e
= p
->p_emuldata
;
316 mutex_enter(proc_lock
);
319 * Check if we are a thread group leader victim of another
320 * thread doing exit_group(). If we are, change the exit code.
322 if ((e
->s
->group_pid
== p
->p_pid
) &&
323 (e
->s
->flags
& LINUX_LES_INEXITGROUP
)) {
324 p
->p_xstat
= e
->s
->xstat
;
328 * Members of the thread groups others than the leader should
329 * exit quietely: no zombie stage, no signal. We do that by
330 * reparenting to init. init will collect us and nobody will
331 * notice what happened.
334 printf("%s:%d e->s->group_pid = %d, p->p_pid = %d, flags = 0x%x\n",
335 __func__
, __LINE__
, e
->s
->group_pid
, p
->p_pid
, e
->s
->flags
);
337 if ((e
->s
->group_pid
!= p
->p_pid
) &&
338 (e
->clone_flags
& LINUX_CLONE_THREAD
)) {
339 proc_reparent(p
, initproc
);
340 cv_broadcast(&initproc
->p_waitcv
);
343 mutex_exit(proc_lock
);
345 /* Emulate LINUX_CLONE_CHILD_CLEARTID */
346 if (e
->clear_tid
!= NULL
) {
349 struct linux_sys_futex_args cup
;
352 error
= copyout(&null
, e
->clear_tid
, sizeof(null
));
355 printf("%s: cannot clear TID\n", __func__
);
358 SCARG(&cup
, uaddr
) = e
->clear_tid
;
359 SCARG(&cup
, op
) = LINUX_FUTEX_WAKE
;
360 SCARG(&cup
, val
) = 0x7fffffff; /* Awake everyone */
361 SCARG(&cup
, timeout
) = NULL
;
362 SCARG(&cup
, uaddr2
) = NULL
;
363 SCARG(&cup
, val3
) = 0;
364 if ((error
= linux_sys_futex(curlwp
, &cup
, &retval
)) != 0)
365 printf("%s: linux_sys_futex failed\n", __func__
);
372 linux_nptl_proc_fork(struct proc
*p
, struct proc
*parent
, void (*luserret
)(void))
374 struct linux_emuldata
*e
= p
->p_emuldata
;
376 /* LINUX_CLONE_CHILD_CLEARTID: clear TID in child's memory on exit() */
377 if (e
->clone_flags
& LINUX_CLONE_CHILD_CLEARTID
)
378 e
->clear_tid
= e
->child_tidptr
;
380 /* LINUX_CLONE_PARENT_SETTID: set child's TID in parent's memory */
381 if (e
->clone_flags
& LINUX_CLONE_PARENT_SETTID
) {
382 if (copyout_proc(parent
, &p
->p_pid
,
383 e
->parent_tidptr
, sizeof(p
->p_pid
)) != 0)
384 printf("%s: LINUX_CLONE_PARENT_SETTID "
385 "failed (e->parent_tidptr = %p, "
386 "parent->p_pid = %d, p->p_pid = %d)\n",
387 __func__
, e
->parent_tidptr
,
388 parent
->p_pid
, p
->p_pid
);
392 * CLONE_CHILD_SETTID and LINUX_CLONE_SETTLS require child's VM
393 * setup to be completed, we postpone them until userret time.
396 (LINUX_CLONE_CHILD_CLEARTID
| LINUX_CLONE_SETTLS
))
397 p
->p_userret
= luserret
;
403 linux_nptl_proc_init(struct proc
*p
, struct proc
*parent
)
405 struct linux_emuldata
*e
= p
->p_emuldata
;
406 struct linux_emuldata
*ep
;
408 if ((parent
!= NULL
) && (parent
->p_emuldata
!= NULL
)) {
409 ep
= parent
->p_emuldata
;
411 e
->parent_tidptr
= ep
->parent_tidptr
;
412 e
->child_tidptr
= ep
->child_tidptr
;
413 e
->clone_flags
= ep
->clone_flags
;
418 #endif /* LINUX_NPTL */