Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision 239accea911999a74c21f7fa9be7459cd336901e)
+++ kernel/generic/include/ipc/ipc.h	(revision cd671c3d0b2c39e24a8731d0ec7f631bdb39f864)
@@ -116,4 +116,6 @@
 	link_t ta_link;
 
+	atomic_t refcnt;
+
 	/** Answerbox link. */
 	link_t ab_link;
@@ -166,4 +168,6 @@
 extern call_t *ipc_call_alloc(unsigned int);
 extern void ipc_call_free(call_t *);
+extern void ipc_call_hold(call_t *);
+extern void ipc_call_release(call_t *);
 
 extern int ipc_call(phone_t *, call_t *);
Index: kernel/generic/include/ipc/sysipc_ops.h
===================================================================
--- kernel/generic/include/ipc/sysipc_ops.h	(revision 239accea911999a74c21f7fa9be7459cd336901e)
+++ kernel/generic/include/ipc/sysipc_ops.h	(revision cd671c3d0b2c39e24a8731d0ec7f631bdb39f864)
@@ -55,5 +55,6 @@
 	 * Context:		caller
 	 * Caller alive:	guaranteed
-	 * Races with:		request_process(), answer_cleanup()
+	 * Races with:		request_process(), answer_cleanup(),
+	 *			_ipc_answer_free_call()
 	 * Invoked on:		all forgotten calls
 	 */	
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision 239accea911999a74c21f7fa9be7459cd336901e)
+++ kernel/generic/src/ipc/ipc.c	(revision cd671c3d0b2c39e24a8731d0ec7f631bdb39f864)
@@ -80,4 +80,18 @@
 }
 
+void ipc_call_hold(call_t *call)
+{
+	atomic_inc(&call->refcnt);
+}
+
+void ipc_call_release(call_t *call)
+{
+	if (atomic_predec(&call->refcnt) == 0) {
+		if (call->buffer)
+			free(call->buffer);
+		slab_free(ipc_call_slab, call);
+	}
+}
+
 /** Allocate and initialize a call structure.
  *
@@ -88,5 +102,5 @@
  *
  * @return If flags permit it, return NULL, or initialized kernel
- *         call structure.
+ *         call structure with one reference.
  *
  */
@@ -94,6 +108,8 @@
 {
 	call_t *call = slab_alloc(ipc_call_slab, flags);
-	if (call)
+	if (call) {
 		_ipc_call_init(call);
+		ipc_call_hold(call);
+	}
 	
 	return call;
@@ -107,8 +123,5 @@
 void ipc_call_free(call_t *call)
 {
-	/* Check to see if we have data in the IPC_M_DATA_SEND buffer. */
-	if (call->buffer)
-		free(call->buffer);
-	slab_free(ipc_call_slab, call);
+	ipc_call_release(call);
 }
 
@@ -605,4 +618,11 @@
 	list_remove(&call->ta_link);
 
+	/*
+	 * The call may be freed by _ipc_answer_free_call() before we are done
+	 * with it; to avoid working with a destroyed call_t structure, we
+	 * must hold a reference to it.
+	 */
+	ipc_call_hold(call);
+
 	spinlock_unlock(&call->forget_lock);
 	spinlock_unlock(&TASK->active_calls_lock);
@@ -613,4 +633,6 @@
 	if (ops->request_forget)
 		ops->request_forget(call);
+
+	ipc_call_release(call);
 
 	goto restart;
