static void init_user_stack(elf_prog_t *prog, int prot) { long argc = strings_count(prog->argv), envc = strings_count(prog->envp), auxc = auxv_count(prog->auxv); char *tmp_argv[argc+1], *tmp_envp[envc+1], *platform = (char *)get_aux(prog->auxv, AT_PLATFORM), *base_platform = (char *)get_aux(prog->auxv, AT_BASE_PLATFORM), *rand_bytes = (char *)get_aux(prog->auxv, AT_RANDOM); char *sp = (char *)(prog->task_size-get_stack_random_shift(prog->auxv)); sp -= sizeof(long); sp = prog->filename = stack_push_string(sp, prog->filename); char *untrusted_data_end=sp; sp = stack_push_strings(sp, tmp_envp, prog->envp); sp = stack_push_strings(sp, tmp_argv, prog->argv); taint_mem(sp, untrusted_data_end-sp, TAINT_ENV); sp = (char *)(((long)sp-0x100)&~0xf); if (platform) sp = platform = stack_push_string(sp, platform); if (base_platform) sp = base_platform = stack_push_string(sp, base_platform); if (rand_bytes) sp = rand_bytes = stack_push_data(sp, rand_bytes, 16); sp = (char *)((long)sp&~0xf); sp = stack_push_data(sp, prog->auxv, (auxc+1)*2*sizeof(long)); prog->auxv = (long *)sp; sp = stack_push_data(sp, tmp_envp, (envc+1)*sizeof(char *)); prog->envp = (char **)sp; sp = stack_push_data(sp, tmp_argv, (argc+1)*sizeof(char *)); prog->argv = (char **)sp; sp = stack_push_data(sp, &argc, sizeof(long)); set_aux(prog->auxv, AT_EXECFN, (long)prog->filename); set_aux(prog->auxv, AT_PLATFORM, (long)platform); set_aux(prog->auxv, AT_BASE_PLATFORM, (long)base_platform); set_aux(prog->auxv, AT_RANDOM, (long)rand_bytes); set_aux(prog->auxv, AT_PHDR, (long)prog->bin.phdr); set_aux(prog->auxv, AT_PHNUM, prog->bin.hdr.e_phnum); set_aux(prog->auxv, AT_BASE, prog->bin.base); set_aux(prog->auxv, AT_ENTRY, prog->bin.base + prog->bin.hdr.e_entry); prog->sp = (long *)sp; }
/* stack: argc argv[0] ... argv[argc] env[0] ... env[n] NULL av[0] ... av[n] NULL */ int elf_stack_setup(struct process *context, user_ptr_t stack, size_t stack_size, char **argv, char **env, struct elf_module *m, struct elf_module *interp) { Elf32Aux aux[30]; int n = 0; int i; char *p; user_ptr_t *init_stack; int pointer_space; int string_space; int offset; user_ptr_t addr; size_t sz; int r; user_ptr_t vdso = 0; r = elf_alloc_vdso(context, &vdso); if (r < 0) return r; memset(&aux, 0, sizeof aux); aux[n].a_type = AT_PHDR; aux[n++].a_value = m->base + m->ehdr.e_phoff; aux[n].a_type = AT_PHENT; aux[n++].a_value = sizeof (Elf32_Phdr); aux[n].a_type = AT_PHNUM; aux[n++].a_value = m->ehdr.e_phnum; if (interp) { aux[n].a_type = AT_BASE; /* interpreter (libc) address */ aux[n++].a_value = (int) interp->base; } aux[n].a_type = AT_FLAGS; aux[n++].a_value = 0; aux[n].a_type = AT_PAGESZ; aux[n++].a_value = pagesize; aux[n].a_type = AT_ENTRY; aux[n++].a_value = (int)m->entry_point; aux[n].a_type = AT_UID; aux[n++].a_value = context->uid; aux[n].a_type = AT_EUID; aux[n++].a_value = context->euid; aux[n].a_type = AT_GID; aux[n++].a_value = context->gid; aux[n].a_type = AT_EGID; aux[n++].a_value = context->egid; aux[n].a_type = AT_SECURE; aux[n++].a_value = 0; aux[n].a_type = AT_SYSINFO; aux[n++].a_value = (int) vdso; assert(n <= sizeof aux/sizeof aux[0]); dprintf("entry is %08x\n", m->entry_point); /* entry, &argc, argv[0..argc-1], NULL, env[0..], NULL, auxv[0..], NULL */ int argc = strv_count(argv); pointer_space = (5 + argc + strv_count(env) + auxv_count(aux)*2); pointer_space *= sizeof (user_ptr_t*); /* env space rounded */ string_space = (strv_length(argv) + strv_length(env) + 3) & ~3; dprintf("%08x bytes for strings\n", string_space); /* * Construct stack in the heap then * write everything to the client in one go */ p = malloc(pointer_space + string_space); if (!p) return -_L(ENOMEM); n = 0; /* base address on local heap */ init_stack = (user_ptr_t*) p; /* base address in client address space */ addr = stack + stack_size - (pointer_space + string_space); /* offset from base address */ offset = pointer_space; /* copy argc, argv arrays onto the allocated memory */ init_stack[n++] = argc; for (i = 0; argv[i]; i++) { dprintf("adding arg %s at %08x\n", argv[i], addr + offset); init_stack[n++] = addr + offset; strcpy(&p[offset], argv[i]); offset += strlen(argv[i]) + 1; } init_stack[n++] = 0; /* gcc optimizes out these assignments if volatile is not used */ for (i = 0; env[i]; i++) { dprintf("adding env %s at %08x\n", env[i], addr + offset); init_stack[n++] = addr + offset; strcpy(&p[offset], env[i]); offset += strlen(env[i]) + 1; } init_stack[n++] = 0; /* set the auxilary vector */ for (i = 0; aux[i].a_type; i++) { init_stack[n++] = aux[i].a_type; init_stack[n++] = aux[i].a_value; } init_stack[n++] = 0; sz = (pointer_space + string_space); r = vm_memcpy_to_process(context, addr, p, sz); free(p); if (r < 0) { printf("vm_memcpy_to_process failed\n"); return r; } context->regs.esp = addr; context->regs.eax = 0; context->regs.ebx = 0; context->regs.ecx = 0; context->regs.edx = 0; context->regs.esi = 0; context->regs.edi = 0; context->regs.ebp = 0; return 0; }