Index: generic/include/mm/as.h
===================================================================
--- generic/include/mm/as.h	(revision e74cb73cbab961321532b012b1090380dd325f74)
+++ generic/include/mm/as.h	(revision 5be19237d21f74d46fb963baab938dd33e90755e)
@@ -108,4 +108,5 @@
 extern int as_page_fault(__address page);
 extern void as_switch(as_t *old, as_t *new);
+extern void as_free(as_t *as);
 
 /* Interface to be implemented by architectures. */
Index: generic/include/proc/task.h
===================================================================
--- generic/include/proc/task.h	(revision e74cb73cbab961321532b012b1090380dd325f74)
+++ generic/include/proc/task.h	(revision 5be19237d21f74d46fb963baab938dd33e90755e)
@@ -50,4 +50,5 @@
 extern void task_init(void);
 extern task_t *task_create(as_t *as);
+extern task_t *task_run_program(void * program_addr);
 
 #endif
Index: generic/src/lib/elf.c
===================================================================
--- generic/src/lib/elf.c	(revision e74cb73cbab961321532b012b1090380dd325f74)
+++ generic/src/lib/elf.c	(revision 5be19237d21f74d46fb963baab938dd33e90755e)
@@ -186,14 +186,12 @@
 		return EE_UNSUPPORTED;
 
-	/*
-	 * Copying the segment out is certainly necessary for segments with p_filesz < p_memsz
-	 * because of the effect of .bss-like sections. For security reasons, it looks like a
-	 * good idea to copy the segment anyway.
-	 */
 	segment_size = ALIGN_UP(max(entry->p_filesz, entry->p_memsz), PAGE_SIZE);
-	segment = malloc(segment_size, 0);
-	if (entry->p_filesz < entry->p_memsz)
+	if ((entry->p_flags & PF_W)) {
+		/* If writable, copy data (should be COW in the future) */
+		segment = malloc(segment_size, 0);
 		memsetb((__address) (segment + entry->p_filesz), segment_size - entry->p_filesz, 0);
-	memcpy(segment, (void *) (((__address) elf) + entry->p_offset), entry->p_filesz);
+		memcpy(segment, (void *) (((__address) elf) + entry->p_offset), entry->p_filesz);
+	} else /* Map identically original data */
+		segment = ((void *) elf) + entry->p_offset;
 
 	a = as_area_create(as, type, SIZE2FRAMES(entry->p_memsz), entry->p_vaddr);
Index: generic/src/main/kinit.c
===================================================================
--- generic/src/main/kinit.c	(revision e74cb73cbab961321532b012b1090380dd325f74)
+++ generic/src/main/kinit.c	(revision 5be19237d21f74d46fb963baab938dd33e90755e)
@@ -28,5 +28,4 @@
 
 #include <main/kinit.h>
-#include <main/uinit.h>
 #include <config.h>
 #include <arch.h>
@@ -47,5 +46,4 @@
 #include <interrupt.h>
 #include <console/kconsole.h>
-#include <elf.h>
 #include <ipc/ns.h>
 
@@ -72,8 +70,4 @@
 {
 	thread_t *t;
-	as_t *as;
-	as_area_t *a;
-	int rc;
-	task_t *u;
 
 	interrupts_disable();
@@ -150,28 +144,7 @@
 		if (config.init_addr % FRAME_SIZE)
 			panic("config.init_addr is not frame aligned");
-		
-		as = as_create(0);
-		if (!as)
-			panic("as_create\n");
 
-		rc = elf_load((elf_header_t *) config.init_addr, as);
-		if (rc != EE_OK) {
-			printf("elf_load failed: %s\n", elf_error(rc));
-		} else {
-			u = task_create(as);
-			if (!u)
-				panic("task_create\n");
-			t = thread_create(uinit, (void *)((elf_header_t *) config.init_addr)->e_entry, u, THREAD_USER_STACK);
-			if (!t)
-				panic("thread_create\n");
-		
-			/*
-			 * Create the data as_area.
-			 */
-			a = as_area_create(as, AS_AREA_STACK, 1, USTACK_ADDRESS);
-			if (!a)
-				panic("as_area_create: stack\n");
-
-			thread_ready(t);
+		if (!task_run_program((void *)config.init_addr)) {
+			printf("Userspace not started.\n");
 		}
 	}
Index: generic/src/mm/as.c
===================================================================
--- generic/src/mm/as.c	(revision e74cb73cbab961321532b012b1090380dd325f74)
+++ generic/src/mm/as.c	(revision 5be19237d21f74d46fb963baab938dd33e90755e)
@@ -104,4 +104,14 @@
 }
 
+/** Free Adress space */
+void as_free(as_t *as)
+{
+	ASSERT(as->refcount == 0);
+
+	/* TODO: free as_areas and other resources held by as */
+	/* TODO: free page table */
+	free(as);
+}
+
 /** Create address space area of common attributes.
  *
Index: generic/src/proc/task.c
===================================================================
--- generic/src/proc/task.c	(revision e74cb73cbab961321532b012b1090380dd325f74)
+++ generic/src/proc/task.c	(revision 5be19237d21f74d46fb963baab938dd33e90755e)
@@ -27,4 +27,5 @@
  */
 
+#include <main/uinit.h>
 #include <proc/thread.h>
 #include <proc/task.h>
@@ -39,4 +40,6 @@
 #include <ipc/ns.h>
 #include <memstr.h>
+
+#include <elf.h>
 
 SPINLOCK_INITIALIZE(tasks_lock);
@@ -60,5 +63,5 @@
  * @param as Task's address space.
  *
- * @return New task's structure on success, NULL on failure.
+ * @return New task's structure
  *
  */
@@ -89,2 +92,35 @@
 }
 
+/** Create new task with 1 thread and run it
+ *
+ * @return Task of the running program or NULL on error
+ */
+task_t * task_run_program(void *program_addr)
+{
+	as_t *as;
+	as_area_t *a;
+	int rc;
+	thread_t *t;
+	task_t *task;
+
+	as = as_create(0);
+
+	rc = elf_load((elf_header_t *) config.init_addr, as);
+	if (rc != EE_OK) {
+		as_free(as);
+		return NULL;
+	} 
+	
+	task = task_create(as);
+	t = thread_create(uinit, (void *)((elf_header_t *) config.init_addr)->e_entry, 
+			  task, THREAD_USER_STACK);
+	
+	/*
+	 * Create the data as_area.
+	 */
+	a = as_area_create(as, AS_AREA_STACK, 1, USTACK_ADDRESS);
+	
+	thread_ready(t);
+
+	return task;
+}
