Пример #1
0
static int sys_sbrk(int size) {
	process_t * proc = (process_t *)current_process;
	if (proc->group != 0) {
		proc = process_from_pid(proc->group);
	}
	spin_lock(proc->image.lock);
	uintptr_t ret = proc->image.heap;
	uintptr_t i_ret = ret;
	ret = (ret + 0xfff) & ~0xfff; /* Rounds ret to 0x1000 in O(1) */
	proc->image.heap += (ret - i_ret) + size;
	while (proc->image.heap > proc->image.heap_actual) {
		proc->image.heap_actual += 0x1000;
		assert(proc->image.heap_actual % 0x1000 == 0);
		alloc_frame(get_page(proc->image.heap_actual, 1, current_directory), 0, 1);
		invalidate_tables_at(proc->image.heap_actual);
	}
	spin_unlock(proc->image.lock);
	return ret;
}
Пример #2
0
int exec_elf(char * path, fs_node_t * file, int argc, char ** argv, char ** env, int interp) {
	Elf32_Header header;

	read_fs(file, 0, sizeof(Elf32_Header), (uint8_t *)&header);

	if (header.e_ident[0] != ELFMAG0 ||
	    header.e_ident[1] != ELFMAG1 ||
	    header.e_ident[2] != ELFMAG2 ||
	    header.e_ident[3] != ELFMAG3) {
		debug_print(ERROR, "Not a valid ELF executable.");
		close_fs(file);
		return -1;
	}

	if (!interp) {
		current_process->name = strdup(path);
		current_process->cmdline = argv;
	}

	if (file->mask & 0x800) {
		debug_print(WARNING, "setuid binary executed [%s, uid:%d]", file->name, file->uid);
		current_process->user = file->uid;
	}

	for (uintptr_t x = 0; x < (uint32_t)header.e_phentsize * header.e_phnum; x += header.e_phentsize) {
		Elf32_Phdr phdr;
		read_fs(file, header.e_phoff + x, sizeof(Elf32_Phdr), (uint8_t *)&phdr);
		if (phdr.p_type == PT_DYNAMIC) {
			/* Dynamic */
			close_fs(file);

			/* Find interpreter? */
			debug_print(WARNING, "Dynamic executable");

			unsigned int nargc = argc + 3;
			char * args[nargc];
			args[0] = "ld.so";
			args[1] = "-e";
			args[2] = strdup(current_process->name);
			int j = 3;
			for (int i = 0; i < argc; ++i, ++j) {
				args[j] = argv[i];
			}
			args[j] = NULL;

			fs_node_t * file = kopen("/lib/ld.so",0);
			if (!file) return -1;

			return exec_elf(NULL, file, nargc, args, env, 1);
		}
	}

	uintptr_t entry = (uintptr_t)header.e_entry;
	uintptr_t base_addr = 0xFFFFFFFF;
	uintptr_t end_addr  = 0x0;

	for (uintptr_t x = 0; x < (uint32_t)header.e_phentsize * header.e_phnum; x += header.e_phentsize) {
		Elf32_Phdr phdr;
		read_fs(file, header.e_phoff + x, sizeof(Elf32_Phdr), (uint8_t *)&phdr);
		if (phdr.p_type == PT_LOAD) {
			if (phdr.p_vaddr < base_addr) {
				base_addr = phdr.p_vaddr;
			}
			if (phdr.p_memsz + phdr.p_vaddr > end_addr) {
				end_addr = phdr.p_memsz + phdr.p_vaddr;
			}
		}
	}

	current_process->image.entry = base_addr;
	current_process->image.size  = end_addr - base_addr;

	release_directory_for_exec(current_directory);
	invalidate_page_tables();


	for (uintptr_t x = 0; x < (uint32_t)header.e_phentsize * header.e_phnum; x += header.e_phentsize) {
		Elf32_Phdr phdr;
		read_fs(file, header.e_phoff + x, sizeof(Elf32_Phdr), (uint8_t *)&phdr);
		if (phdr.p_type == PT_LOAD) {
			for (uintptr_t i = phdr.p_vaddr; i < phdr.p_vaddr + phdr.p_memsz; i += 0x1000) {
				/* This doesn't care if we already allocated this page */
				alloc_frame(get_page(i, 1, current_directory), 0, 1);
				invalidate_tables_at(i);
			}
			IRQ_RES;
			read_fs(file, phdr.p_offset, phdr.p_filesz, (uint8_t *)phdr.p_vaddr);
			IRQ_OFF;
			size_t r = phdr.p_filesz;
			while (r < phdr.p_memsz) {
				*(char *)(phdr.p_vaddr + r) = 0;
				r++;
			}
		}
	}

	close_fs(file);

	for (uintptr_t stack_pointer = USER_STACK_BOTTOM; stack_pointer < USER_STACK_TOP; stack_pointer += 0x1000) {
		alloc_frame(get_page(stack_pointer, 1, current_directory), 0, 1);
		invalidate_tables_at(stack_pointer);
	}

	/* Collect arguments */
	int envc = 0;
	for (envc = 0; env[envc] != NULL; ++envc);

	/* Format auxv */
	Elf32_auxv auxv[] = {
		{256, 0xDEADBEEF},
		{0, 0}
	};
	int auxvc = 0;
	for (auxvc = 0; auxv[auxvc].id != 0; ++auxvc);
	auxvc++;

	uintptr_t heap = current_process->image.entry + current_process->image.size;
	while (heap & 0xFFF) heap++;
	alloc_frame(get_page(heap, 1, current_directory), 0, 1);
	invalidate_tables_at(heap);
	char ** argv_ = (char **)heap;
	heap += sizeof(char *) * (argc + 1);
	char ** env_ = (char **)heap;
	heap += sizeof(char *) * (envc + 1);
	void * auxv_ptr = (void *)heap;
	heap += sizeof(Elf32_auxv) * (auxvc);

	for (int i = 0; i < argc; ++i) {
		size_t size = strlen(argv[i]) * sizeof(char) + 1;
		for (uintptr_t x = heap; x < heap + size + 0x1000; x += 0x1000) {
			alloc_frame(get_page(x, 1, current_directory), 0, 1);
		}
		invalidate_tables_at(heap);
		argv_[i] = (char *)heap;
		memcpy((void *)heap, argv[i], size);
		heap += size;
	}
	/* Don't forget the NULL at the end of that... */
	argv_[argc] = 0;

	for (int i = 0; i < envc; ++i) {
		size_t size = strlen(env[i]) * sizeof(char) + 1;
		for (uintptr_t x = heap; x < heap + size + 0x1000; x += 0x1000) {
			alloc_frame(get_page(x, 1, current_directory), 0, 1);
		}
		invalidate_tables_at(heap);
		env_[i] = (char *)heap;
		memcpy((void *)heap, env[i], size);
		heap += size;
	}
	env_[envc] = 0;

	memcpy(auxv_ptr, auxv, sizeof(Elf32_auxv) * (auxvc));

	current_process->image.heap        = heap; /* heap end */
	current_process->image.heap_actual = heap + (0x1000 - heap % 0x1000);
	alloc_frame(get_page(current_process->image.heap_actual, 1, current_directory), 0, 1);
	invalidate_tables_at(current_process->image.heap_actual);
	current_process->image.user_stack  = USER_STACK_TOP;

	current_process->image.start = entry;

	/* Go go go */
	enter_user_jmp(entry, argc, argv_, USER_STACK_TOP);

	/* We should never reach this code */
	return -1;
}