Index: generic/src/ddi/ddi.c
===================================================================
--- generic/src/ddi/ddi.c	(revision bdc5c516b811c2d1871bfaaf83a3c1fa14c86fc4)
+++ generic/src/ddi/ddi.c	(revision 4c89b095bec1df9ec64df69761ec941fb73fc8e3)
@@ -41,7 +41,7 @@
 #include <security/cap.h>
 #include <mm/frame.h>
-#include <mm/page.h>
 #include <mm/as.h>
 #include <synch/spinlock.h>
+#include <syscall/copy.h>
 #include <arch.h>
 #include <align.h>
@@ -184,6 +184,10 @@
 {
 	ddi_memarg_t arg;
-	
-	copy_from_uspace(&arg, uspace_mem_arg, sizeof(ddi_memarg_t));
+	int rc;
+	
+	rc = copy_from_uspace(&arg, uspace_mem_arg, sizeof(ddi_memarg_t));
+	if (rc != 0)
+		return (__native) rc;
+		
 	return (__native) ddi_physmem_map((task_id_t) arg.task_id, ALIGN_DOWN((__address) arg.phys_base, FRAME_SIZE),
 					  ALIGN_DOWN((__address) arg.virt_base, PAGE_SIZE), (count_t) arg.pages,
@@ -200,6 +204,10 @@
 {
 	ddi_ioarg_t arg;
-	
-	copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t));
+	int rc;
+	
+	rc = copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t));
+	if (rc != 0)
+		return (__native) rc;
+		
 	return (__native) ddi_iospace_enable((task_id_t) arg.task_id, (__address) arg.ioaddr, (size_t) arg.size);
 }
Index: generic/src/ipc/irq.c
===================================================================
--- generic/src/ipc/irq.c	(revision bdc5c516b811c2d1871bfaaf83a3c1fa14c86fc4)
+++ generic/src/ipc/irq.c	(revision 4c89b095bec1df9ec64df69761ec941fb73fc8e3)
@@ -48,4 +48,5 @@
 #include <ipc/irq.h>
 #include <atomic.h>
+#include <syscall/copy.h>
 
 typedef struct {
@@ -121,7 +122,12 @@
 	irq_code_t *code;
 	irq_cmd_t *ucmds;
+	int rc;
 
 	code = malloc(sizeof(*code), 0);
-	copy_from_uspace(code, ucode, sizeof(*code));
+	rc = copy_from_uspace(code, ucode, sizeof(*code));
+	if (rc != 0) {
+		free(code);
+		return NULL;
+	}
 	
 	if (code->cmdcount > IRQ_MAX_PROG_SIZE) {
@@ -131,5 +137,10 @@
 	ucmds = code->cmds;
 	code->cmds = malloc(sizeof(code->cmds[0]) * (code->cmdcount), 0);
-	copy_from_uspace(code->cmds, ucmds, sizeof(code->cmds[0]) * (code->cmdcount));
+	rc = copy_from_uspace(code->cmds, ucmds, sizeof(code->cmds[0]) * (code->cmdcount));
+	if (rc != 0) {
+		free(code->cmds);
+		free(code);
+		return NULL;
+	}
 
 	return code;
Index: generic/src/ipc/sysipc.c
===================================================================
--- generic/src/ipc/sysipc.c	(revision bdc5c516b811c2d1871bfaaf83a3c1fa14c86fc4)
+++ generic/src/ipc/sysipc.c	(revision 4c89b095bec1df9ec64df69761ec941fb73fc8e3)
@@ -29,7 +29,6 @@
 #include <arch.h>
 #include <proc/task.h>
-
+#include <proc/thread.h>
 #include <errno.h>
-#include <mm/page.h>
 #include <memstr.h>
 #include <debug.h>
@@ -39,8 +38,6 @@
 #include <ipc/ipcrsc.h>
 #include <arch/interrupt.h>
-
 #include <print.h>
-#include <arch.h>
-#include <proc/thread.h>
+#include <syscall/copy.h>
 
 #define GET_CHECK_PHONE(phone,phoneid,err) { \
@@ -229,7 +226,10 @@
 	phone_t *phone;
 	int res;
+	int rc;
 
 	ipc_call_static_init(&call);
-	copy_from_uspace(&call.data.args, &question->args, sizeof(call.data.args));
+	rc = copy_from_uspace(&call.data.args, &question->args, sizeof(call.data.args));
+	if (rc != 0)
+		return (__native) rc;
 
 	GET_CHECK_PHONE(phone, phoneid, return ENOENT);
@@ -241,5 +241,7 @@
 		IPC_SET_RETVAL(call.data, res);
 
-	STRUCT_TO_USPACE(&reply->args, &call.data.args);
+	rc = STRUCT_TO_USPACE(&reply->args, &call.data.args);
+	if (rc != 0)
+		return rc;
 
 	return 0;
@@ -298,4 +300,5 @@
 	phone_t *phone;
 	int res;
+	int rc;
 
 	if (check_call_limit())
@@ -305,5 +308,7 @@
 
 	call = ipc_call_alloc(0);
-	copy_from_uspace(&call->data.args, &data->args, sizeof(call->data.args));
+	rc = copy_from_uspace(&call->data.args, &data->args, sizeof(call->data.args));
+	if (rc != 0)
+		return (__native) rc;
 	if (!(res=request_preprocess(call)))
 		ipc_call(phone, call);
@@ -394,4 +399,5 @@
 	ipc_data_t saved_data;
 	int saveddata = 0;
+	int rc;
 
 	call = get_call(callid);
@@ -403,6 +409,8 @@
 		saveddata = 1;
 	}
-	copy_from_uspace(&call->data.args, &data->args, 
+	rc = copy_from_uspace(&call->data.args, &data->args, 
 			 sizeof(call->data.args));
+	if (rc != 0)
+		return rc;
 
 	answer_preprocess(call, saveddata ? &saved_data : NULL);
Index: generic/src/mm/as.c
===================================================================
--- generic/src/mm/as.c	(revision bdc5c516b811c2d1871bfaaf83a3c1fa14c86fc4)
+++ generic/src/mm/as.c	(revision 4c89b095bec1df9ec64df69761ec941fb73fc8e3)
@@ -58,4 +58,5 @@
 #include <adt/btree.h>
 #include <proc/task.h>
+#include <proc/thread.h>
 #include <arch/asm.h>
 #include <panic.h>
@@ -69,4 +70,6 @@
 #include <arch/types.h>
 #include <typedefs.h>
+#include <syscall/copy.h>
+#include <arch/interrupt.h>
 
 as_operations_t *as_operations = NULL;
@@ -478,8 +481,9 @@
  *
  * @param page Faulting page.
- *
- * @return 0 on page fault, 1 on success.
- */
-int as_page_fault(__address page)
+ * @param istate Pointer to interrupted state.
+ *
+ * @return 0 on page fault, 1 on success or 2 if the fault was caused by copy_to_uspace() or copy_from_uspace().
+ */
+int as_page_fault(__address page, istate_t *istate)
 {
 	pte_t *pte;
@@ -497,5 +501,5 @@
 		 */
 		spinlock_unlock(&AS->lock);
-		return 0;
+		goto page_fault;
 	}
 
@@ -507,5 +511,5 @@
 		spinlock_unlock(&area->lock);
 		spinlock_unlock(&AS->lock);
-		return 0;		
+		goto page_fault;		
 	}
 
@@ -555,5 +559,21 @@
 	spinlock_unlock(&area->lock);
 	spinlock_unlock(&AS->lock);
-	return 1;
+	return AS_PF_OK;
+
+page_fault:
+	if (!THREAD)
+		return AS_PF_FAULT;
+	
+	if (THREAD->in_copy_from_uspace) {
+		THREAD->in_copy_from_uspace = false;
+		istate_set_retaddr(istate, (__address) &memcpy_from_uspace_failover_address);
+	} else if (THREAD->in_copy_to_uspace) {
+		THREAD->in_copy_to_uspace = false;
+		istate_set_retaddr(istate, (__address) &memcpy_to_uspace_failover_address);
+	} else {
+		return AS_PF_FAULT;
+	}
+
+	return AS_PF_DEFER;
 }
 
@@ -885,6 +905,9 @@
 {
 	as_area_acptsnd_arg_t arg;
-	
-	copy_from_uspace(&arg, uspace_accept_arg, sizeof(as_area_acptsnd_arg_t));
+	int rc;
+	
+	rc = copy_from_uspace(&arg, uspace_accept_arg, sizeof(as_area_acptsnd_arg_t));
+	if (rc != 0)
+		return rc;
 	
 	if (!arg.size)
@@ -907,6 +930,9 @@
 {
 	as_area_acptsnd_arg_t arg;
-	
-	copy_from_uspace(&arg, uspace_send_arg, sizeof(as_area_acptsnd_arg_t));
+	int rc;
+	
+	rc = copy_from_uspace(&arg, uspace_send_arg, sizeof(as_area_acptsnd_arg_t));
+	if (rc != 0)
+		return rc;
 
 	if (!arg.size)
Index: generic/src/mm/slab.c
===================================================================
--- generic/src/mm/slab.c	(revision bdc5c516b811c2d1871bfaaf83a3c1fa14c86fc4)
+++ generic/src/mm/slab.c	(revision 4c89b095bec1df9ec64df69761ec941fb73fc8e3)
@@ -176,5 +176,5 @@
 		slab = data + fsize - sizeof(*slab);
 	}
-		
+	
 	/* Fill in slab structures */
 	for (i=0; i < (1 << cache->order); i++)
@@ -278,6 +278,6 @@
 		/* Allow recursion and reclaiming
 		 * - this should work, as the slab control structures
-		 *   are small and do not need to allocte with anything
-		 *   other ten frame_alloc when they are allocating,
+		 *   are small and do not need to allocate with anything
+		 *   other than frame_alloc when they are allocating,
 		 *   that's why we should get recursion at most 1-level deep
 		 */
@@ -880,5 +880,5 @@
 
 	ASSERT(_slab_initialized);
-	ASSERT( size && size <= (1 << SLAB_MAX_MALLOC_W));
+	ASSERT(size && size <= (1 << SLAB_MAX_MALLOC_W));
 	
 	if (size < (1 << SLAB_MIN_MALLOC_W))
@@ -890,5 +890,4 @@
 }
 
-
 void free(void *obj)
 {
Index: generic/src/printf/vsnprintf.c
===================================================================
--- generic/src/printf/vsnprintf.c	(revision bdc5c516b811c2d1871bfaaf83a3c1fa14c86fc4)
+++ generic/src/printf/vsnprintf.c	(revision 4c89b095bec1df9ec64df69761ec941fb73fc8e3)
@@ -40,7 +40,7 @@
 
 /** Write string to given buffer.
- * Write at most data->size characters including trailing zero. According to C99 has snprintf to return number
+ * Write at most data->size characters including trailing zero. According to C99, snprintf() has to return number
  * of characters that would have been written if enough space had been available. Hence the return value is not
- * number of really printed characters but size of input string. Number of really used characters 
+ * number of really printed characters but size of the input string. Number of really used characters 
  * is stored in data->len.
  * @param str source string to print
@@ -91,4 +91,2 @@
 	return printf_core(fmt, &ps, ap);
 }
-
-
Index: generic/src/proc/task.c
===================================================================
--- generic/src/proc/task.c	(revision bdc5c516b811c2d1871bfaaf83a3c1fa14c86fc4)
+++ generic/src/proc/task.c	(revision 4c89b095bec1df9ec64df69761ec941fb73fc8e3)
@@ -49,5 +49,5 @@
 #include <print.h>
 #include <elf.h>
-
+#include <syscall/copy.h>
 
 #ifndef LOADED_PROG_STACK_PAGES_NO
@@ -171,5 +171,5 @@
  * @param uspace_task_id Userspace address of 8-byte buffer where to store current task ID.
  *
- * @return Always returns 0.
+ * @return 0 on success or an error code from @ref errno.h.
  */
 __native sys_task_get_id(task_id_t *uspace_task_id)
@@ -179,7 +179,5 @@
 	 * remains constant for the lifespan of the task.
 	 */
-	copy_to_uspace(uspace_task_id, &TASK->taskid, sizeof(TASK->taskid));
-
-	return 0;
+	return (__native) copy_to_uspace(uspace_task_id, &TASK->taskid, sizeof(TASK->taskid));
 }
 
Index: generic/src/proc/thread.c
===================================================================
--- generic/src/proc/thread.c	(revision bdc5c516b811c2d1871bfaaf83a3c1fa14c86fc4)
+++ generic/src/proc/thread.c	(revision 4c89b095bec1df9ec64df69761ec941fb73fc8e3)
@@ -61,4 +61,6 @@
 #include <debug.h>
 #include <main/uinit.h>
+#include <syscall/copy.h>
+#include <errno.h>
 
 char *thread_states[] = {"Invalid", "Running", "Sleeping", "Ready", "Entering", "Exiting"}; /**< Thread states */
@@ -304,4 +306,7 @@
 	t->sleep_queue = NULL;
 	t->timeout_pending = 0;
+
+	t->in_copy_from_uspace = false;
+	t->in_copy_to_uspace = false;
 	
 	t->rwlock_holder_type = RWLOCK_NONE;
@@ -463,9 +468,16 @@
 	uspace_arg_t *kernel_uarg;
 	__u32 tid;
-
-	copy_from_uspace(namebuf, uspace_name, THREAD_NAME_BUFLEN);
+	int rc;
+
+	rc = copy_from_uspace(namebuf, uspace_name, THREAD_NAME_BUFLEN);
+	if (rc != 0)
+		return (__native) rc;
 
 	kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0);	
-	copy_from_uspace(kernel_uarg, uspace_uarg, sizeof(uspace_arg_t));
+	rc = copy_from_uspace(kernel_uarg, uspace_uarg, sizeof(uspace_arg_t));
+	if (rc != 0) {
+		free(kernel_uarg);
+		return (__native) rc;
+	}
 
 	if ((t = thread_create(uinit, kernel_uarg, TASK, 0, namebuf))) {
@@ -477,5 +489,5 @@
 	}
 
-	return (__native) -1;
+	return (__native) ENOMEM;
 }
 
Index: generic/src/smp/ipi.c
===================================================================
--- generic/src/smp/ipi.c	(revision bdc5c516b811c2d1871bfaaf83a3c1fa14c86fc4)
+++ generic/src/smp/ipi.c	(revision 4c89b095bec1df9ec64df69761ec941fb73fc8e3)
@@ -44,8 +44,8 @@
  * @param ipi Message to broadcast.
  *
- * @bugs The decision whether to actually send the IPI must be based
- *	 on a different criterion. The current version has
- *	 problems when some of the detected CPUs are marked
- *	 disabled in machine configuration.
+ * @bug The decision whether to actually send the IPI must be based
+ * 	on a different criterion. The current version has
+ *	problems when some of the detected CPUs are marked
+ *	disabled in machine configuration.
  */
 void ipi_broadcast(int ipi)
Index: generic/src/synch/waitq.c
===================================================================
--- generic/src/synch/waitq.c	(revision bdc5c516b811c2d1871bfaaf83a3c1fa14c86fc4)
+++ generic/src/synch/waitq.c	(revision 4c89b095bec1df9ec64df69761ec941fb73fc8e3)
@@ -31,5 +31,5 @@
  * @brief	Wait queue.
  *
- * Wait queue is the basic synchronization primitive upon all
+ * Wait queue is the basic synchronization primitive upon which all
  * other synchronization primitives build.
  *
Index: generic/src/syscall/copy.c
===================================================================
--- generic/src/syscall/copy.c	(revision 4c89b095bec1df9ec64df69761ec941fb73fc8e3)
+++ generic/src/syscall/copy.c	(revision 4c89b095bec1df9ec64df69761ec941fb73fc8e3)
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2006 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file	copy.c
+ * @brief	Copying between kernel and userspace.
+ *
+ * This file contains sanitized functions for copying data
+ * between kernel and userspace.
+ */
+
+#include <syscall/copy.h>
+#include <proc/thread.h>
+#include <mm/as.h>
+#include <macros.h>
+#include <arch.h>
+#include <errno.h>
+#include <typedefs.h>
+
+/** Copy data from userspace to kernel.
+ *
+ * Provisions are made to return value even after page fault.
+ *
+ * This function can be called only from syscall.
+ *
+ * @param dst Destination kernel address.
+ * @param uspace_src Source userspace address.
+ * @param size Size of the data to be copied.
+ *
+ * @return 0 on success or error code from @ref errno.h.
+ */
+int copy_from_uspace(void *dst, void *uspace_src, size_t size)
+{
+	ipl_t ipl;
+	int rc;
+	
+	ASSERT(THREAD);
+	ASSERT(!THREAD->in_copy_from_uspace);
+	
+	if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
+		if (overlaps((__address) uspace_src, size,
+			KERNEL_ADDRESS_SPACE_START, KERNEL_ADDRESS_SPACE_END-KERNEL_ADDRESS_SPACE_START)) {
+			/*
+			 * The userspace source block conflicts with kernel address space.
+			 */
+			return EPERM;
+		}
+	}
+	
+	ipl = interrupts_disable();
+	THREAD->in_copy_from_uspace = true;
+	
+	rc = memcpy_from_uspace(dst, uspace_src, size);
+
+	THREAD->in_copy_from_uspace = false;
+
+	interrupts_restore(ipl);
+	return !rc ? EPERM : 0;
+}
+
+/** Copy data from kernel to userspace.
+ *
+ * Provisions are made to return value even after page fault.
+ *
+ * This function can be called only from syscall.
+ *
+ * @param uspace_dst Destination userspace address.
+ * @param uspace_src Source kernel address.
+ * @param size Size of the data to be copied.
+ *
+ * @return 0 on success or error code from @ref errno.h.
+ */
+int copy_to_uspace(void *uspace_dst, void *src, size_t size)
+{
+	ipl_t ipl;
+	int rc;
+	
+	ASSERT(THREAD);
+	ASSERT(!THREAD->in_copy_from_uspace);
+	
+	if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
+		if (overlaps((__address) uspace_dst, size,
+			KERNEL_ADDRESS_SPACE_START, KERNEL_ADDRESS_SPACE_END-KERNEL_ADDRESS_SPACE_START)) {
+			/*
+			 * The userspace destination block conflicts with kernel address space.
+			 */
+			return EPERM;
+		}
+	}
+	
+	ipl = interrupts_disable();
+	THREAD->in_copy_from_uspace = true;
+	
+	rc = memcpy_to_uspace(uspace_dst, src, size);
+
+	THREAD->in_copy_from_uspace = false;
+
+	interrupts_restore(ipl);
+	return !rc ? EPERM : 0;
+}
