1 /* $NetBSD: linux32_exec_elf32.c,v 1.8 2008/04/28 20:23:44 martin Exp $ */
4 * Copyright (c) 1995, 1998, 2000, 2001,2006 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: linux32_exec_elf32.c,v 1.8 2008/04/28 20:23:44 martin Exp $");
38 #include <sys/param.h>
39 #include <sys/systm.h>
41 #include <sys/malloc.h>
42 #include <sys/vnode.h>
44 #include <sys/exec_elf.h>
45 #include <sys/kauth.h>
46 #include <sys/kernel.h>
47 #include <sys/resourcevar.h>
48 #include <sys/signal.h>
49 #include <sys/signalvar.h>
51 #include <compat/linux/common/linux_exec.h>
52 #include <compat/netbsd32/netbsd32.h>
53 #include <compat/netbsd32/netbsd32_exec.h>
54 #include <compat/linux32/common/linux32_exec.h>
56 #include <machine/frame.h>
59 #define DPRINTF(a) uprintf a
64 int linux32_copyinargs(struct exec_package
*, struct ps_strings
*,
65 void *, size_t, const void *, const void *);
68 ELFNAME2(linux32
,probe
)(struct lwp
*l
, struct exec_package
*epp
,
69 void *eh
, char *itp
, vaddr_t
*pos
)
73 if (((error
= ELFNAME2(linux
,signature
)(l
, epp
, eh
, itp
)) != 0) &&
74 #ifdef LINUX32_GCC_SIGNATURE
75 ((error
= ELFNAME2(linux
,gcc_signature
)(l
, epp
, eh
)) != 0) &&
77 #ifdef LINUX32_ATEXIT_SIGNATURE
78 ((error
= ELFNAME2(linux
,atexit_signature
)(l
, epp
, eh
)) != 0) &&
80 #ifdef LINUX32_DEBUGLINK_SIGNATURE
81 ((error
= ELFNAME2(linux
,debuglink_signature
)(l
, epp
, eh
)) != 0) &&
87 if ((error
= emul_find_interp(l
, epp
, itp
)))
91 DPRINTF(("linux32_probe: returning 0\n"));
94 epp
->ep_flags
|= EXEC_32
;
95 epp
->ep_vm_minaddr
= VM_MIN_ADDRESS
;
96 epp
->ep_vm_maxaddr
= USRSTACK32
;
101 /* round up and down to page boundaries. */
102 #define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1))
103 #define ELF_TRUNC(a, b) ((a) & ~((b) - 1))
106 * Copy arguments onto the stack in the normal way, but add some
107 * extra information in case of dynamic binding.
110 linux32_elf32_copyargs(struct lwp
*l
, struct exec_package
*pack
,
111 struct ps_strings
*arginfo
, char **stackp
, void *argp
)
113 struct linux32_extra_stack_data
*esdp
, esd
;
123 if ((error
= netbsd32_copyargs(l
, pack
, arginfo
, stackp
, argp
)) != 0)
127 * Push extra arguments on the stack needed by dynamically
128 * linked binaries and static binaries as well.
130 memset(&esd
, 0, sizeof(esd
));
131 esdp
= (struct linux32_extra_stack_data
*)(*stackp
);
132 ap
= (struct elf_args
*)pack
->ep_emul_arg
;
134 eh
= (Elf_Ehdr
*)pack
->ep_hdr
;
137 * We forgot this, so we ned to reload it now. XXX keep track of it?
140 phsize
= eh
->e_phnum
* sizeof(Elf_Phdr
);
141 ph
= (Elf_Phdr
*)malloc(phsize
, M_TEMP
, M_WAITOK
);
142 error
= exec_read_from(l
, pack
->ep_vp
, eh
->e_phoff
, ph
, phsize
);
144 for (i
= 0; i
< eh
->e_phnum
; i
++) {
145 if (ph
[i
].p_type
== PT_PHDR
) {
146 phdr
= ph
[i
].p_vaddr
;
156 * The exec_package doesn't have a proc pointer and it's not
157 * exactly trivial to add one since the credentials are
158 * changing. XXX Linux uses curlwp's credentials.
159 * Why can't we use them too? XXXad we do now; what's different
160 * about Linux's LWP creds?
164 esd
.ai
[i
].a_type
= LINUX_AT_SYSINFO
;
165 esd
.ai
[i
++].a_v
= NETBSD32PTR32I(&esdp
->kernel_vsyscall
[0]);
167 esd
.ai
[i
].a_type
= LINUX_AT_SYSINFO_EHDR
;
168 esd
.ai
[i
++].a_v
= NETBSD32PTR32I(&esdp
->elfhdr
);
170 esd
.ai
[i
].a_type
= LINUX_AT_HWCAP
;
171 esd
.ai
[i
++].a_v
= LINUX32_CPUCAP
;
173 esd
.ai
[i
].a_type
= AT_PAGESZ
;
174 esd
.ai
[i
++].a_v
= PAGE_SIZE
;
176 esd
.ai
[i
].a_type
= LINUX_AT_CLKTCK
;
177 esd
.ai
[i
++].a_v
= hz
;
179 esd
.ai
[i
].a_type
= AT_PHDR
;
180 esd
.ai
[i
++].a_v
= (ap
? ap
->arg_phaddr
: phdr
);
182 esd
.ai
[i
].a_type
= AT_PHENT
;
183 esd
.ai
[i
++].a_v
= (ap
? ap
->arg_phentsize
: eh
->e_phentsize
);
185 esd
.ai
[i
].a_type
= AT_PHNUM
;
186 esd
.ai
[i
++].a_v
= (ap
? ap
->arg_phnum
: eh
->e_phnum
);
188 esd
.ai
[i
].a_type
= AT_BASE
;
189 esd
.ai
[i
++].a_v
= (ap
? ap
->arg_interp
: 0);
191 esd
.ai
[i
].a_type
= AT_FLAGS
;
194 esd
.ai
[i
].a_type
= AT_ENTRY
;
195 esd
.ai
[i
++].a_v
= (ap
? ap
->arg_entry
: eh
->e_entry
);
197 esd
.ai
[i
].a_type
= LINUX_AT_EGID
;
198 esd
.ai
[i
++].a_v
= ((vap
->va_mode
& S_ISGID
) ?
199 vap
->va_gid
: kauth_cred_getegid(l
->l_cred
));
201 esd
.ai
[i
].a_type
= LINUX_AT_GID
;
202 esd
.ai
[i
++].a_v
= kauth_cred_getgid(l
->l_cred
);
204 esd
.ai
[i
].a_type
= LINUX_AT_EUID
;
205 esd
.ai
[i
++].a_v
= ((vap
->va_mode
& S_ISUID
) ?
206 vap
->va_uid
: kauth_cred_geteuid(l
->l_cred
));
208 esd
.ai
[i
].a_type
= LINUX_AT_UID
;
209 esd
.ai
[i
++].a_v
= kauth_cred_getuid(l
->l_cred
);
211 esd
.ai
[i
].a_type
= LINUX_AT_SECURE
;
214 esd
.ai
[i
].a_type
= LINUX_AT_PLATFORM
;
215 esd
.ai
[i
++].a_v
= NETBSD32PTR32I(&esdp
->hw_platform
[0]);
217 esd
.ai
[i
].a_type
= AT_NULL
;
221 if (i
!= LINUX32_ELF_AUX_ENTRIES
) {
222 printf("linux32_elf32_copyargs: %d Aux entries\n", i
);
227 memcpy(esd
.kernel_vsyscall
, linux32_kernel_vsyscall
,
228 sizeof(linux32_kernel_vsyscall
));
230 memcpy(&esd
.elfhdr
, eh
, sizeof(*eh
));
232 strcpy(esd
.hw_platform
, LINUX32_PLATFORM
);
235 free((char *)ap
, M_TEMP
);
236 pack
->ep_emul_arg
= NULL
;
240 * Copy out the ELF auxiliary table and hw platform name
242 if ((error
= copyout(&esd
, esdp
, sizeof(esd
))) != 0)
244 *stackp
+= sizeof(esd
);