1/* $NetBSD: linux_exec_elf32.c,v 1.86 2012/02/12 16:34:10 matt 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 * 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. 31 */ 32 33/* 34 * based on exec_aout.c, sunos_exec.c and svr4_exec.c 35 */ 36 37#include <sys/cdefs.h> 38__KERNEL_RCSID(0, "$NetBSD: linux_exec_elf32.c,v 1.86 2012/02/12 16:34:10 matt Exp $"); 39 40#ifndef ELFSIZE 41/* XXX should die */ 42#define ELFSIZE 32 43#endif 44 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/kernel.h> 48#include <sys/proc.h> 49#include <sys/malloc.h> 50#include <sys/namei.h> 51#include <sys/vnode.h> 52#include <sys/mount.h> 53#include <sys/exec.h> 54#include <sys/exec_elf.h> 55#include <sys/stat.h> 56#include <sys/kauth.h> 57 58#include <sys/mman.h> 59#include <sys/syscallargs.h> 60 61#include <sys/cpu.h> 62#include <machine/reg.h> 63 64#include <compat/linux/common/linux_types.h> 65#include <compat/linux/common/linux_signal.h> 66#include <compat/linux/common/linux_util.h> 67#include <compat/linux/common/linux_exec.h> 68#include <compat/linux/common/linux_machdep.h> 69#include <compat/linux/common/linux_ipc.h> 70#include <compat/linux/common/linux_sem.h> 71 72#include <compat/linux/linux_syscallargs.h> 73#include <compat/linux/linux_syscall.h> 74 75#ifdef DEBUG_LINUX 76#define DPRINTF(a) uprintf a 77#else 78#define DPRINTF(a) 79#endif 80 81#ifdef LINUX_ATEXIT_SIGNATURE 82/* 83 * On the PowerPC, statically linked Linux binaries are not recognized 84 * by linux_signature nor by linux_gcc_signature. Fortunately, thoses 85 * binaries features a __libc_atexit ELF section. We therefore assume we 86 * have a Linux binary if we find this section. 87 */ 88int 89ELFNAME2(linux,atexit_signature)( 90 struct lwp *l, 91 struct exec_package *epp, 92 Elf_Ehdr *eh) 93{ 94 Elf_Shdr *sh; 95 size_t shsize; 96 u_int shstrndx; 97 size_t i; 98 static const char signature[] = "__libc_atexit"; 99 const size_t sigsz = sizeof(signature); 100 char tbuf[sizeof(signature)]; 101 int error; 102 103 /* Load the section header table. */ 104 shsize = eh->e_shnum * sizeof(Elf_Shdr); 105 sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 106 error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize); 107 if (error) 108 goto out; 109 110 /* Now let's find the string table. If it does not exist, give up. */ 111 shstrndx = eh->e_shstrndx; 112 if (shstrndx == SHN_UNDEF || shstrndx >= eh->e_shnum) { 113 error = ENOEXEC; 114 goto out; 115 } 116 117 /* Check if any section has the name we're looking for. */ 118 const off_t stroff = sh[shstrndx].sh_offset; 119 for (i = 0; i < eh->e_shnum; i++) { 120 Elf_Shdr *s = &sh[i]; 121 122 if (s->sh_name + sigsz > sh[shstrndx].sh_size) 123 continue; 124 125 error = exec_read_from(l, epp->ep_vp, stroff + s->sh_name, tbuf, 126 sigsz); 127 if (error) 128 goto out; 129 if (!memcmp(tbuf, signature, sigsz)) { 130 DPRINTF(("linux_atexit_sig=%s\n", tbuf)); 131 error = 0; 132 goto out; 133 } 134 } 135 error = ENOEXEC; 136 137out: 138 free(sh, M_TEMP); 139 return (error); 140} 141#endif 142 143#ifdef LINUX_GCC_SIGNATURE 144/* 145 * Take advantage of the fact that all the linux binaries are compiled 146 * with gcc, and gcc sticks in the comment field a signature. Note that 147 * on SVR4 binaries, the gcc signature will follow the OS name signature, 148 * that will not be a problem. We don't bother to read in the string table, 149 * but we check all the progbits headers. 150 * 151 * XXX This only works in the i386. On the alpha (at least) 152 * XXX we have the same gcc signature which incorrectly identifies 153 * XXX NetBSD binaries as Linux. 154 */ 155int 156ELFNAME2(linux,gcc_signature)( 157 struct lwp *l, 158 struct exec_package *epp, 159 Elf_Ehdr *eh) 160{ 161 size_t shsize; 162 size_t i; 163 static const char signature[] = "\0GCC: (GNU) "; 164 char tbuf[sizeof(signature) - 1]; 165 Elf_Shdr *sh; 166 int error; 167 168 shsize = eh->e_shnum * sizeof(Elf_Shdr); 169 sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 170 error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize); 171 if (error) 172 goto out; 173 174 for (i = 0; i < eh->e_shnum; i++) { 175 Elf_Shdr *s = &sh[i]; 176 177 /* 178 * Identify candidates for the comment header; 179 * Header cannot have a load address, or flags and 180 * it must be large enough. 181 */ 182 if (s->sh_type != SHT_PROGBITS || 183 s->sh_addr != 0 || 184 s->sh_flags != 0 || 185 s->sh_size < sizeof(signature) - 1) 186 continue; 187 188 error = exec_read_from(l, epp->ep_vp, s->sh_offset, tbuf, 189 sizeof(signature) - 1); 190 if (error) 191 continue; 192 193 /* 194 * error is 0, if the signatures match we are done. 195 */ 196 DPRINTF(("linux_gcc_sig: sig=%s\n", tbuf)); 197 if (!memcmp(tbuf, signature, sizeof(signature) - 1)) { 198 error = 0; 199 goto out; 200 } 201 } 202 error = ENOEXEC; 203 204out: 205 free(sh, M_TEMP); 206 return (error); 207} 208#endif 209 210#ifdef LINUX_DEBUGLINK_SIGNATURE 211/* 212 * Look for a .gnu_debuglink, specific to x86_64 interpreter 213 */ 214int 215ELFNAME2(linux,debuglink_signature)(struct lwp *l, struct exec_package *epp, Elf_Ehdr *eh) 216{ 217 Elf_Shdr *sh; 218 size_t shsize; 219 u_int shstrndx; 220 size_t i; 221 static const char signature[] = ".gnu_debuglink"; 222 const size_t sigsz = sizeof(signature); 223 char tbuf[sizeof(signature)]; 224 int error; 225 226 /* Load the section header table. */ 227 shsize = eh->e_shnum * sizeof(Elf_Shdr); 228 sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 229 error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize); 230 if (error) 231 goto out; 232 233 /* Now let's find the string table. If it does not exist, give up. */ 234 shstrndx = eh->e_shstrndx; 235 if (shstrndx == SHN_UNDEF || shstrndx >= eh->e_shnum) { 236 error = ENOEXEC; 237 goto out; 238 } 239 240 /* Check if any section has the name we're looking for. */ 241 const off_t stroff = sh[shstrndx].sh_offset; 242 for (i = 0; i < eh->e_shnum; i++) { 243 Elf_Shdr *s = &sh[i]; 244 245 if (s->sh_name + sigsz > sh[shstrndx].sh_size) 246 continue; 247 248 error = exec_read_from(l, epp->ep_vp, stroff + s->sh_name, tbuf, 249 sigsz); 250 if (error) 251 goto out; 252 if (!memcmp(tbuf, signature, sigsz)) { 253 DPRINTF(("linux_debuglink_sig=%s\n", tbuf)); 254 error = 0; 255 goto out; 256 } 257 } 258 error = ENOEXEC; 259 260out: 261 free(sh, M_TEMP); 262 return (error); 263} 264#endif 265 266int 267ELFNAME2(linux,signature)(struct lwp *l, struct exec_package *epp, Elf_Ehdr *eh, char *itp) 268{ 269 size_t i; 270 Elf_Phdr *ph; 271 size_t phsize; 272 int error; 273 static const char linux[] = "Linux"; 274 275 if (eh->e_ident[EI_OSABI] == 3 || 276 memcmp(&eh->e_ident[EI_ABIVERSION], linux, sizeof(linux)) == 0) 277 return 0; 278 279 phsize = eh->e_phnum * sizeof(Elf_Phdr); 280 ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 281 error = exec_read_from(l, epp->ep_vp, eh->e_phoff, ph, phsize); 282 if (error) 283 goto out; 284 285 for (i = 0; i < eh->e_phnum; i++) { 286 Elf_Phdr *ephp = &ph[i]; 287 Elf_Nhdr *np; 288 u_int32_t *abi; 289 290 if (ephp->p_type != PT_NOTE || 291 ephp->p_filesz > 1024 || 292 ephp->p_filesz < sizeof(Elf_Nhdr) + 20) 293 continue; 294 295 np = (Elf_Nhdr *)malloc(ephp->p_filesz, M_TEMP, M_WAITOK); 296 error = exec_read_from(l, epp->ep_vp, ephp->p_offset, np, 297 ephp->p_filesz); 298 if (error) 299 goto next; 300 301 if (np->n_type != ELF_NOTE_TYPE_ABI_TAG || 302 np->n_namesz != ELF_NOTE_ABI_NAMESZ || 303 np->n_descsz != ELF_NOTE_ABI_DESCSZ || 304 memcmp((void *)(np + 1), ELF_NOTE_ABI_NAME, 305 ELF_NOTE_ABI_NAMESZ)) 306 goto next; 307 308 /* Make sure the OS is Linux. */ 309 abi = (u_int32_t *)((char *)np + sizeof(Elf_Nhdr) + 310 np->n_namesz); 311 if (abi[0] == ELF_NOTE_ABI_OS_LINUX) 312 error = 0; 313 else 314 error = ENOEXEC; 315 free(np, M_TEMP); 316 goto out; 317 318 next: 319 free(np, M_TEMP); 320 continue; 321 } 322 323 /* Check for certain interpreter names. */ 324 if (itp) { 325 if (!strncmp(itp, "/lib/ld-linux", 13) || 326#if (ELFSIZE == 64) 327 !strncmp(itp, "/lib64/ld-linux", 15) || 328#endif 329 !strncmp(itp, "/lib/ld.so.", 11)) 330 error = 0; 331 else 332 error = ENOEXEC; 333 goto out; 334 } 335 336 error = ENOEXEC; 337out: 338 free(ph, M_TEMP); 339 return (error); 340} 341 342int 343ELFNAME2(linux,probe)(struct lwp *l, struct exec_package *epp, void *eh, 344 char *itp, vaddr_t *pos) 345{ 346 int error; 347 348 if (((error = ELFNAME2(linux,signature)(l, epp, eh, itp)) != 0) && 349#ifdef LINUX_GCC_SIGNATURE 350 ((error = ELFNAME2(linux,gcc_signature)(l, epp, eh)) != 0) && 351#endif 352#ifdef LINUX_ATEXIT_SIGNATURE 353 ((error = ELFNAME2(linux,atexit_signature)(l, epp, eh)) != 0) && 354#endif 355#ifdef LINUX_DEBUGLINK_SIGNATURE 356 ((error = ELFNAME2(linux,debuglink_signature)(l, epp, eh)) != 0) && 357#endif 358 1) { 359 DPRINTF(("linux_probe: returning %d\n", error)); 360 return error; 361 } 362 363 if (itp) { 364 if ((error = emul_find_interp(l, epp, itp))) 365 return (error); 366 } 367 epp->ep_flags |= EXEC_FORCEAUX; 368 DPRINTF(("linux_probe: returning 0\n")); 369 return 0; 370} 371 372#ifndef LINUX_MACHDEP_ELF_COPYARGS 373/* 374 * Copy arguments onto the stack in the normal way, but add some 375 * extra information in case of dynamic binding. 376 */ 377int 378ELFNAME2(linux,copyargs)(struct lwp *l, struct exec_package *pack, 379 struct ps_strings *arginfo, char **stackp, void *argp) 380{ 381 size_t len; 382 AuxInfo ai[LINUX_ELF_AUX_ENTRIES], *a; 383 struct elf_args *ap; 384 int error; 385 struct vattr *vap; 386 387 if ((error = copyargs(l, pack, arginfo, stackp, argp)) != 0) 388 return error; 389 390 a = ai; 391 392 /* 393 * Push extra arguments used by glibc on the stack. 394 */ 395 396 a->a_type = AT_PAGESZ; 397 a->a_v = PAGE_SIZE; 398 a++; 399 400 if ((ap = (struct elf_args *)pack->ep_emul_arg)) { 401 402 a->a_type = AT_PHDR; 403 a->a_v = ap->arg_phaddr; 404 a++; 405 406 a->a_type = AT_PHENT; 407 a->a_v = ap->arg_phentsize; 408 a++; 409 410 a->a_type = AT_PHNUM; 411 a->a_v = ap->arg_phnum; 412 a++; 413 414 a->a_type = AT_BASE; 415 a->a_v = ap->arg_interp; 416 a++; 417 418 a->a_type = AT_FLAGS; 419 a->a_v = 0; 420 a++; 421 422 a->a_type = AT_ENTRY; 423 a->a_v = ap->arg_entry; 424 a++; 425 426 exec_free_emul_arg(pack); 427 } 428 429 /* Linux-specific items */ 430 a->a_type = LINUX_AT_CLKTCK; 431 a->a_v = hz; 432 a++; 433 434 vap = pack->ep_vap; 435 436 a->a_type = LINUX_AT_UID; 437 a->a_v = kauth_cred_getuid(l->l_cred); 438 a++; 439 440 a->a_type = LINUX_AT_EUID; 441 if (vap->va_mode & S_ISUID) 442 a->a_v = vap->va_uid; 443 else 444 a->a_v = kauth_cred_geteuid(l->l_cred); 445 a++; 446 447 a->a_type = LINUX_AT_GID; 448 a->a_v = kauth_cred_getgid(l->l_cred); 449 a++; 450 451 a->a_type = LINUX_AT_EGID; 452 if (vap->va_mode & S_ISGID) 453 a->a_v = vap->va_gid; 454 else 455 a->a_v = kauth_cred_getegid(l->l_cred); 456 a++; 457 458 a->a_type = AT_NULL; 459 a->a_v = 0; 460 a++; 461 462 len = (a - ai) * sizeof(AuxInfo); 463 if ((error = copyout(ai, *stackp, len)) != 0) 464 return error; 465 *stackp += len; 466 467 return 0; 468} 469#endif /* !LINUX_MACHDEP_ELF_COPYARGS */ 470