예제 #1
0
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;
}
예제 #2
0
파일: elf.c 프로젝트: cheako/atratus
/* 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;
}