1 /* $NetBSD: linux_exec_elf32.c,v 1.72 2006/05/14 21:24:50 elad Exp $ */ 2 3 /*- 4 * Copyright (c) 1995, 1998, 2000, 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas, Frank van der Linden, Eric Haszlakiewicz and 9 * Emmanuel Dreyfus. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 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. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * based on exec_aout.c, sunos_exec.c and svr4_exec.c 42 */ 43 44 #include <sys/cdefs.h> 45 __KERNEL_RCSID(0, "$NetBSD: linux_exec_elf32.c,v 1.72 2006/05/14 21:24:50 elad Exp $"); 46 47 #ifndef ELFSIZE 48 /* XXX should die */ 49 #define ELFSIZE 32 50 #endif 51 52 #include <sys/param.h> 53 #include <sys/systm.h> 54 #include <sys/kernel.h> 55 #include <sys/proc.h> 56 #include <sys/malloc.h> 57 #include <sys/namei.h> 58 #include <sys/vnode.h> 59 #include <sys/mount.h> 60 #include <sys/exec.h> 61 #include <sys/exec_elf.h> 62 #include <sys/stat.h> 63 #include <sys/kauth.h> 64 65 #include <sys/mman.h> 66 #include <sys/sa.h> 67 #include <sys/syscallargs.h> 68 69 #include <machine/cpu.h> 70 #include <machine/reg.h> 71 72 #include <compat/linux/common/linux_types.h> 73 #include <compat/linux/common/linux_signal.h> 74 #include <compat/linux/common/linux_util.h> 75 #include <compat/linux/common/linux_exec.h> 76 #include <compat/linux/common/linux_machdep.h> 77 78 #include <compat/linux/linux_syscallargs.h> 79 #include <compat/linux/linux_syscall.h> 80 81 #ifdef DEBUG_LINUX 82 #define DPRINTF(a) uprintf a 83 #else 84 #define DPRINTF(a) 85 #endif 86 87 #ifdef LINUX_ATEXIT_SIGNATURE 88 /* 89 * On the PowerPC, statically linked Linux binaries are not recognized 90 * by linux_signature nor by linux_gcc_signature. Fortunately, thoses 91 * binaries features a __libc_atexit ELF section. We therefore assume we 92 * have a Linux binary if we find this section. 93 */ 94 int 95 ELFNAME2(linux,atexit_signature)(l, epp, eh) 96 struct lwp *l; 97 struct exec_package *epp; 98 Elf_Ehdr *eh; 99 { 100 size_t shsize; 101 int strndx; 102 size_t i; 103 static const char signature[] = "__libc_atexit"; 104 char *strtable = NULL; 105 Elf_Shdr *sh; 106 107 int error; 108 109 /* 110 * load the section header table 111 */ 112 shsize = eh->e_shnum * sizeof(Elf_Shdr); 113 sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 114 error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize); 115 if (error) 116 goto out; 117 118 /* 119 * Now let's find the string table. If it does not exists, give up. 120 */ 121 strndx = (int)(eh->e_shstrndx); 122 if (strndx == SHN_UNDEF) { 123 error = ENOEXEC; 124 goto out; 125 } 126 127 /* 128 * strndx is the index in section header table of the string table 129 * section get the whole string table in strtable, and then we get access to the names 130 * s->sh_name is the offset of the section name in strtable. 131 */ 132 strtable = malloc(sh[strndx].sh_size, M_TEMP, M_WAITOK); 133 error = exec_read_from(l, epp->ep_vp, sh[strndx].sh_offset, strtable, 134 sh[strndx].sh_size); 135 if (error) 136 goto out; 137 138 for (i = 0; i < eh->e_shnum; i++) { 139 Elf_Shdr *s = &sh[i]; 140 if (!memcmp((void*)(&(strtable[s->sh_name])), signature, 141 sizeof(signature))) { 142 DPRINTF(("linux_atexit_sig=%s\n", 143 &(strtable[s->sh_name]))); 144 error = 0; 145 goto out; 146 } 147 } 148 error = ENOEXEC; 149 150 out: 151 free(sh, M_TEMP); 152 if (strtable) 153 free(strtable, M_TEMP); 154 return (error); 155 } 156 #endif 157 158 #ifdef LINUX_GCC_SIGNATURE 159 /* 160 * Take advantage of the fact that all the linux binaries are compiled 161 * with gcc, and gcc sticks in the comment field a signature. Note that 162 * on SVR4 binaries, the gcc signature will follow the OS name signature, 163 * that will not be a problem. We don't bother to read in the string table, 164 * but we check all the progbits headers. 165 * 166 * XXX This only works in the i386. On the alpha (at least) 167 * XXX we have the same gcc signature which incorrectly identifies 168 * XXX NetBSD binaries as Linux. 169 */ 170 int 171 ELFNAME2(linux,gcc_signature)(l, epp, eh) 172 struct lwp *l; 173 struct exec_package *epp; 174 Elf_Ehdr *eh; 175 { 176 size_t shsize; 177 size_t i; 178 static const char signature[] = "\0GCC: (GNU) "; 179 char tbuf[sizeof(signature) - 1]; 180 Elf_Shdr *sh; 181 int error; 182 183 shsize = eh->e_shnum * sizeof(Elf_Shdr); 184 sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 185 error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize); 186 if (error) 187 goto out; 188 189 for (i = 0; i < eh->e_shnum; i++) { 190 Elf_Shdr *s = &sh[i]; 191 192 /* 193 * Identify candidates for the comment header; 194 * Header cannot have a load address, or flags and 195 * it must be large enough. 196 */ 197 if (s->sh_type != SHT_PROGBITS || 198 s->sh_addr != 0 || 199 s->sh_flags != 0 || 200 s->sh_size < sizeof(signature) - 1) 201 continue; 202 203 error = exec_read_from(l, epp->ep_vp, s->sh_offset, tbuf, 204 sizeof(signature) - 1); 205 if (error) 206 continue; 207 208 /* 209 * error is 0, if the signatures match we are done. 210 */ 211 DPRINTF(("linux_gcc_sig: sig=%s\n", tbuf)); 212 if (!memcmp(tbuf, signature, sizeof(signature) - 1)) { 213 error = 0; 214 goto out; 215 } 216 } 217 error = ENOEXEC; 218 219 out: 220 free(sh, M_TEMP); 221 return (error); 222 } 223 #endif 224 225 int 226 ELFNAME2(linux,signature)(l, epp, eh, itp) 227 struct lwp *l; 228 struct exec_package *epp; 229 Elf_Ehdr *eh; 230 char *itp; 231 { 232 size_t i; 233 Elf_Phdr *ph; 234 size_t phsize; 235 int error; 236 static const char linux[] = "Linux"; 237 238 if (eh->e_ident[EI_OSABI] == 3 || 239 memcmp(&eh->e_ident[EI_ABIVERSION], linux, sizeof(linux)) == 0) 240 return 0; 241 242 phsize = eh->e_phnum * sizeof(Elf_Phdr); 243 ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 244 error = exec_read_from(l, epp->ep_vp, eh->e_phoff, ph, phsize); 245 if (error) 246 goto out; 247 248 for (i = 0; i < eh->e_phnum; i++) { 249 Elf_Phdr *ephp = &ph[i]; 250 Elf_Nhdr *np; 251 u_int32_t *abi; 252 253 if (ephp->p_type != PT_NOTE || 254 ephp->p_filesz > 1024 || 255 ephp->p_filesz < sizeof(Elf_Nhdr) + 20) 256 continue; 257 258 np = (Elf_Nhdr *)malloc(ephp->p_filesz, M_TEMP, M_WAITOK); 259 error = exec_read_from(l, epp->ep_vp, ephp->p_offset, np, 260 ephp->p_filesz); 261 if (error) 262 goto next; 263 264 if (np->n_type != ELF_NOTE_TYPE_ABI_TAG || 265 np->n_namesz != ELF_NOTE_ABI_NAMESZ || 266 np->n_descsz != ELF_NOTE_ABI_DESCSZ || 267 memcmp((caddr_t)(np + 1), ELF_NOTE_ABI_NAME, 268 ELF_NOTE_ABI_NAMESZ)) 269 goto next; 270 271 /* Make sure the OS is Linux. */ 272 abi = (u_int32_t *)((caddr_t)np + sizeof(Elf_Nhdr) + 273 np->n_namesz); 274 if (abi[0] == ELF_NOTE_ABI_OS_LINUX) 275 error = 0; 276 else 277 error = ENOEXEC; 278 free(np, M_TEMP); 279 goto out; 280 281 next: 282 free(np, M_TEMP); 283 continue; 284 } 285 286 /* Check for certain intepreter names. */ 287 if (itp) { 288 if (!strncmp(itp, "/lib/ld-linux", 13) || 289 #if (ELFSIZE == 64) 290 !strncmp(itp, "/lib64/ld-linux", 15) || 291 #endif 292 !strncmp(itp, "/lib/ld.so.", 11)) 293 error = 0; 294 else 295 error = ENOEXEC; 296 goto out; 297 } 298 299 error = ENOEXEC; 300 out: 301 free(ph, M_TEMP); 302 return (error); 303 } 304 305 int 306 ELFNAME2(linux,probe)(l, epp, eh, itp, pos) 307 struct lwp *l; 308 struct exec_package *epp; 309 void *eh; 310 char *itp; 311 vaddr_t *pos; 312 { 313 int error; 314 315 if (((error = ELFNAME2(linux,signature)(l, epp, eh, itp)) != 0) && 316 #ifdef LINUX_GCC_SIGNATURE 317 ((error = ELFNAME2(linux,gcc_signature)(l, epp, eh)) != 0) && 318 #endif 319 #ifdef LINUX_ATEXIT_SIGNATURE 320 ((error = ELFNAME2(linux,atexit_signature)(l, epp, eh)) != 0) && 321 #endif 322 1) 323 return error; 324 325 if (itp) { 326 if ((error = emul_find_interp(l, epp->ep_esch->es_emul->e_path, 327 itp))) 328 return (error); 329 } 330 DPRINTF(("linux_probe: returning 0\n")); 331 return 0; 332 } 333 334 #ifndef LINUX_MACHDEP_ELF_COPYARGS 335 /* 336 * Copy arguments onto the stack in the normal way, but add some 337 * extra information in case of dynamic binding. 338 */ 339 int 340 ELFNAME2(linux,copyargs)(struct lwp *l, struct exec_package *pack, 341 struct ps_strings *arginfo, char **stackp, void *argp) 342 { 343 struct proc *p = l->l_proc; 344 size_t len; 345 AuxInfo ai[LINUX_ELF_AUX_ENTRIES], *a; 346 struct elf_args *ap; 347 int error; 348 struct vattr *vap; 349 350 if ((error = copyargs(l, pack, arginfo, stackp, argp)) != 0) 351 return error; 352 353 a = ai; 354 355 /* 356 * Push extra arguments used by glibc on the stack. 357 */ 358 359 a->a_type = AT_PAGESZ; 360 a->a_v = PAGE_SIZE; 361 a++; 362 363 if ((ap = (struct elf_args *)pack->ep_emul_arg)) { 364 365 a->a_type = AT_PHDR; 366 a->a_v = ap->arg_phaddr; 367 a++; 368 369 a->a_type = AT_PHENT; 370 a->a_v = ap->arg_phentsize; 371 a++; 372 373 a->a_type = AT_PHNUM; 374 a->a_v = ap->arg_phnum; 375 a++; 376 377 a->a_type = AT_BASE; 378 a->a_v = ap->arg_interp; 379 a++; 380 381 a->a_type = AT_FLAGS; 382 a->a_v = 0; 383 a++; 384 385 a->a_type = AT_ENTRY; 386 a->a_v = ap->arg_entry; 387 a++; 388 389 free(pack->ep_emul_arg, M_TEMP); 390 pack->ep_emul_arg = NULL; 391 } 392 393 /* Linux-specific items */ 394 a->a_type = LINUX_AT_CLKTCK; 395 a->a_v = hz; 396 a++; 397 398 vap = pack->ep_vap; 399 400 a->a_type = LINUX_AT_UID; 401 a->a_v = kauth_cred_getuid(p->p_cred); 402 a++; 403 404 a->a_type = LINUX_AT_EUID; 405 if (vap->va_mode & S_ISUID) 406 a->a_v = vap->va_uid; 407 else 408 a->a_v = kauth_cred_geteuid(p->p_cred); 409 a++; 410 411 a->a_type = LINUX_AT_GID; 412 a->a_v = kauth_cred_getgid(p->p_cred); 413 a++; 414 415 a->a_type = LINUX_AT_EGID; 416 if (vap->va_mode & S_ISGID) 417 a->a_v = vap->va_gid; 418 else 419 a->a_v = kauth_cred_getegid(p->p_cred); 420 a++; 421 422 a->a_type = AT_NULL; 423 a->a_v = 0; 424 a++; 425 426 len = (a - ai) * sizeof(AuxInfo); 427 if ((error = copyout(ai, *stackp, len)) != 0) 428 return error; 429 *stackp += len; 430 431 return 0; 432 } 433 #endif /* !LINUX_MACHDEP_ELF_COPYARGS */ 434