Index: kernel/generic/include/cap/cap.h
===================================================================
--- kernel/generic/include/cap/cap.h	(revision 30f1a25ef3be685966ce1377e11888810d47aab9)
+++ kernel/generic/include/cap/cap.h	(revision e6d670fd4926748dbee919b7e1014dcb33cb1748)
@@ -64,7 +64,5 @@
 struct phone;
 
-struct kobject;
 typedef struct kobject_ops {
-	bool (*reclaim)(struct kobject *);
 	void (*destroy)(void *);
 } kobject_ops_t;
Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision 30f1a25ef3be685966ce1377e11888810d47aab9)
+++ kernel/generic/include/ipc/ipc.h	(revision e6d670fd4926748dbee919b7e1014dcb33cb1748)
@@ -82,4 +82,9 @@
 	waitq_t wq;
 
+	/**
+	 * Number of answers the answerbox is expecting to eventually arrive.
+	 */
+	atomic_t active_calls;
+
 	/** Phones connected to this answerbox. */
 	list_t connected_phones;
@@ -177,5 +182,5 @@
 extern slab_cache_t *phone_cache;
 
-extern answerbox_t *ipc_phone_0;
+extern answerbox_t *ipc_box_0;
 
 extern void ipc_init(void);
Index: kernel/generic/include/ipc/ipcrsc.h
===================================================================
--- kernel/generic/include/ipc/ipcrsc.h	(revision 30f1a25ef3be685966ce1377e11888810d47aab9)
+++ kernel/generic/include/ipc/ipcrsc.h	(revision e6d670fd4926748dbee919b7e1014dcb33cb1748)
@@ -40,6 +40,5 @@
 #include <cap/cap.h>
 
-extern errno_t phone_alloc(task_t *, cap_handle_t *);
-extern bool phone_connect(cap_handle_t, answerbox_t *);
+extern errno_t phone_alloc(task_t *, bool, cap_handle_t *, kobject_t **);
 extern void phone_dealloc(cap_handle_t);
 
Index: kernel/generic/src/cap/cap.c
===================================================================
--- kernel/generic/src/cap/cap.c	(revision 30f1a25ef3be685966ce1377e11888810d47aab9)
+++ kernel/generic/src/cap/cap.c	(revision e6d670fd4926748dbee919b7e1014dcb33cb1748)
@@ -235,22 +235,4 @@
 }
 
-static bool cap_reclaimer(ht_link_t *link, void *arg)
-{
-	cap_t **result = (cap_t **) arg;
-	cap_t *cap = hash_table_get_inst(link, cap_t, caps_link);
-
-	if (cap->state == CAP_STATE_PUBLISHED && cap->kobject->ops->reclaim &&
-	    cap->kobject->ops->reclaim(cap->kobject)) {
-		kobject_t *kobj = cap_unpublish(cap->task, cap->handle,
-		    cap->kobject->type);
-		kobject_put(kobj);
-		cap_initialize(cap, cap->task, cap->handle);
-		*result = cap;
-		return false;
-	}
-
-	return true;
-}
-
 /** Allocate new capability
  *
@@ -263,32 +245,18 @@
 errno_t cap_alloc(task_t *task, cap_handle_t *handle)
 {
-	cap_t *cap = NULL;
-
-	/*
-	 * First of all, see if we can reclaim a capability. Note that this
-	 * feature is only temporary and capability reclamaition will eventually
-	 * be phased out.
-	 */
-	mutex_lock(&task->cap_info->lock);
-	hash_table_apply(&task->cap_info->caps, cap_reclaimer, &cap);
-
-	/*
-	 * If we don't have a capability by now, try to allocate a new one.
-	 */
+	mutex_lock(&task->cap_info->lock);
+	cap_t *cap = slab_alloc(cap_cache, FRAME_ATOMIC);
 	if (!cap) {
-		cap = slab_alloc(cap_cache, FRAME_ATOMIC);
-		if (!cap) {
-			mutex_unlock(&task->cap_info->lock);
-			return ENOMEM;
-		}
-		uintptr_t hbase;
-		if (!ra_alloc(task->cap_info->handles, 1, 1, &hbase)) {
-			slab_free(cap_cache, cap);
-			mutex_unlock(&task->cap_info->lock);
-			return ENOMEM;
-		}
-		cap_initialize(cap, task, (cap_handle_t) hbase);
-		hash_table_insert(&task->cap_info->caps, &cap->caps_link);
-	}
+		mutex_unlock(&task->cap_info->lock);
+		return ENOMEM;
+	}
+	uintptr_t hbase;
+	if (!ra_alloc(task->cap_info->handles, 1, 1, &hbase)) {
+		slab_free(cap_cache, cap);
+		mutex_unlock(&task->cap_info->lock);
+		return ENOMEM;
+	}
+	cap_initialize(cap, task, (cap_handle_t) hbase);
+	hash_table_insert(&task->cap_info->caps, &cap->caps_link);
 
 	cap->state = CAP_STATE_ALLOCATED;
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision 30f1a25ef3be685966ce1377e11888810d47aab9)
+++ kernel/generic/src/ipc/ipc.c	(revision e6d670fd4926748dbee919b7e1014dcb33cb1748)
@@ -63,6 +63,6 @@
 static void ipc_forget_call(call_t *);
 
-/** Open channel that is assigned automatically to new tasks */
-answerbox_t *ipc_phone_0 = NULL;
+/** Answerbox that new tasks are automatically connected to */
+answerbox_t *ipc_box_0 = NULL;
 
 static slab_cache_t *call_cache;
@@ -147,4 +147,5 @@
 	list_initialize(&box->answers);
 	list_initialize(&box->irq_notifs);
+	atomic_set(&box->active_calls, 0);
 	box->task = task;
 }
@@ -160,11 +161,11 @@
 bool ipc_phone_connect(phone_t *phone, answerbox_t *box)
 {
-	bool active;
+	bool connected;
 
 	mutex_lock(&phone->lock);
 	irq_spinlock_lock(&box->lock, true);
 
-	active = box->active;
-	if (active) {
+	connected = box->active && (phone->state == IPC_PHONE_CONNECTING);
+	if (connected) {
 		phone->state = IPC_PHONE_CONNECTED;
 		phone->callee = box;
@@ -176,10 +177,10 @@
 	mutex_unlock(&phone->lock);
 
-	if (!active) {
+	if (!connected) {
 		/* We still have phone->kobject's reference; drop it */
 		kobject_put(phone->kobject);
 	}
 
-	return active;
+	return connected;
 }
 
@@ -350,4 +351,9 @@
 	} else {
 		atomic_inc(&phone->active_calls);
+		if (call->callerbox)
+			atomic_inc(&call->callerbox->active_calls);
+		else
+			atomic_inc(&caller->answerbox.active_calls);
+		kobject_add_ref(phone->kobject);
 		call->sender = caller;
 		call->active = true;
@@ -439,6 +445,6 @@
 /** Disconnect phone from answerbox.
  *
- * This call leaves the phone in the HUNGUP state. The change to 'free' is done
- * lazily later.
+ * This call leaves the phone in the hung-up state. The phone is destroyed when
+ * its last active call is answered and there are no references to it.
  *
  * @param phone Phone structure to be hung up.
@@ -563,4 +569,6 @@
 		list_remove(&request->ab_link);
 		atomic_dec(&request->caller_phone->active_calls);
+		atomic_dec(&box->active_calls);
+		kobject_put(request->caller_phone->kobject);
 	} else if (!list_empty(&box->calls)) {
 		/* Count received call */
@@ -707,4 +715,6 @@
 
 	atomic_dec(&call->caller_phone->active_calls);
+	atomic_dec(&TASK->answerbox.active_calls);
+	kobject_put(call->caller_phone->kobject);
 
 	SYSIPC_OP(request_forget, call);
@@ -746,80 +756,4 @@
 }
 
-static bool phone_cap_wait_cb(cap_t *cap, void *arg)
-{
-	phone_t *phone = cap->kobject->phone;
-	bool *restart = (bool *) arg;
-
-	mutex_lock(&phone->lock);
-	if ((phone->state == IPC_PHONE_HUNGUP) &&
-	    (atomic_get(&phone->active_calls) == 0)) {
-		phone->state = IPC_PHONE_FREE;
-		phone->callee = NULL;
-	}
-
-	/*
-	 * We might have had some IPC_PHONE_CONNECTING phones at the beginning
-	 * of ipc_cleanup(). Depending on whether these were forgotten or
-	 * answered, they will eventually enter the IPC_PHONE_FREE or
-	 * IPC_PHONE_CONNECTED states, respectively.  In the latter case, the
-	 * other side may slam the open phones at any time, in which case we
-	 * will get an IPC_PHONE_SLAMMED phone.
-	 */
-	if ((phone->state == IPC_PHONE_CONNECTED) ||
-	    (phone->state == IPC_PHONE_SLAMMED)) {
-		mutex_unlock(&phone->lock);
-		ipc_phone_hangup(phone);
-		/*
-		 * Now there may be one extra active call, which needs to be
-		 * forgotten.
-		 */
-		ipc_forget_all_active_calls();
-		*restart = true;
-		return false;
-	}
-
-	/*
-	 * If the hangup succeeded, it has sent a HANGUP message, the IPC is now
-	 * in HUNGUP state, we wait for the reply to come
-	 */
-	if (phone->state != IPC_PHONE_FREE) {
-		mutex_unlock(&phone->lock);
-		return false;
-	}
-
-	mutex_unlock(&phone->lock);
-	return true;
-}
-
-/** Wait for all answers to asynchronous calls to arrive. */
-static void ipc_wait_for_all_answered_calls(void)
-{
-	call_t *call;
-	bool restart;
-
-restart:
-	/*
-	 * Go through all phones, until they are all free.
-	 * Locking is needed as there may be connection handshakes in progress.
-	 */
-	restart = false;
-	if (caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_PHONE,
-	    phone_cap_wait_cb, &restart)) {
-		/* Got into cleanup */
-		return;
-	}
-	if (restart)
-		goto restart;
-
-	call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT,
-	    SYNCH_FLAGS_NONE);
-	assert(call->flags & (IPC_CALL_ANSWERED | IPC_CALL_NOTIF));
-
-	SYSIPC_OP(answer_process, call);
-
-	kobject_put(call->kobject);
-	goto restart;
-}
-
 static bool phone_cap_cleanup_cb(cap_t *cap, void *arg)
 {
@@ -830,4 +764,26 @@
 	cap_free(cap->task, cap->handle);
 	return true;
+}
+
+/** Wait for all answers to asynchronous calls to arrive. */
+static void ipc_wait_for_all_answered_calls(void)
+{
+	while (atomic_get(&TASK->answerbox.active_calls) != 0) {
+		call_t *call = ipc_wait_for_call(&TASK->answerbox,
+		    SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE);
+		assert(call->flags & (IPC_CALL_ANSWERED | IPC_CALL_NOTIF));
+
+		SYSIPC_OP(answer_process, call);
+
+		kobject_put(call->kobject);
+
+		/*
+		 * Now there may be some new phones and new hangup calls to
+		 * immediately forget.
+		 */
+		caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_PHONE,
+		    phone_cap_cleanup_cb, NULL);
+		ipc_forget_all_active_calls();
+	}
 }
 
@@ -869,9 +825,9 @@
 	irq_spinlock_unlock(&TASK->answerbox.lock, true);
 
-	/* Disconnect all our phones ('ipc_phone_hangup') */
+	/* Hangup all phones and destroy all phone capabilities */
 	caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_PHONE,
 	    phone_cap_cleanup_cb, NULL);
 
-	/* Unsubscribe from any event notifications. */
+	/* Unsubscribe from any event notifications */
 	event_cleanup_answerbox(&TASK->answerbox);
 
@@ -899,4 +855,6 @@
 	ipc_forget_all_active_calls();
 	ipc_wait_for_all_answered_calls();
+
+	assert(atomic_get(&TASK->answerbox.active_calls) == 0);
 }
 
@@ -968,5 +926,5 @@
 			break;
 		case IPC_PHONE_HUNGUP:
-			printf("hung up by %p", phone->callee);
+			printf("hung up to %p", phone->callee);
 			break;
 		default:
@@ -1004,4 +962,7 @@
 	irq_spinlock_lock(&task->lock, true);
 	irq_spinlock_lock(&task->answerbox.lock, false);
+
+	printf("Active calls: %" PRIun "\n",
+	    atomic_get(&task->answerbox.active_calls));
 
 #ifdef __32_BITS__
Index: kernel/generic/src/ipc/ipcrsc.c
===================================================================
--- kernel/generic/src/ipc/ipcrsc.c	(revision 30f1a25ef3be685966ce1377e11888810d47aab9)
+++ kernel/generic/src/ipc/ipcrsc.c	(revision e6d670fd4926748dbee919b7e1014dcb33cb1748)
@@ -39,7 +39,8 @@
  *
  * The pattern of usage of the resources is:
- * - allocate empty phone capability slot, connect | deallocate slot
+ * - allocate a capability and phone kernel object (do not publish yet),
+ *   connect to the answerbox, and finally publish the capability
  * - disconnect connected phone (some messages might be on the fly)
- * - find phone in slot and send a message using phone
+ * - find phone capability and send a message using phone
  * - answer message to phone
  * - hangup phone (the caller has hung up)
@@ -53,5 +54,4 @@
  *   atomic on all platforms)
  *
- * - To find an empty phone capability slot, the TASK must be locked
  * - To answer a message, the answerbox must be locked
  * - The locking of phone and answerbox is done at the ipc_ level.
@@ -73,11 +73,11 @@
  * *** Connect_me_to ***
  * The caller sends IPC_M_CONNECT_ME_TO to an answerbox. The server receives
- * 'phoneid' of the connecting phone as an ARG5. If it answers with RETVAL=0,
- * the phonecall is accepted, otherwise it is refused.
+ * 'phoneid' of the connecting phone as an ARG5. If it answers with RETVAL=EOK,
+ * the phone call is accepted, otherwise it is refused.
  *
  * *** Connect_to_me ***
  * The caller sends IPC_M_CONNECT_TO_ME.
  * The server receives an automatically opened phoneid. If it accepts
- * (RETVAL=0), it can use the phoneid immediately.  Possible race condition can
+ * (RETVAL=EOK), it can use the phoneid immediately. Possible race condition can
  * arise, when the client receives messages from new connection before getting
  * response for connect_to_me message. Userspace should implement handshake
@@ -95,5 +95,5 @@
  * - The phone is disconnected. EHANGUP response code is sent to the calling
  *   task. All new calls through this phone get a EHUNGUP error code, the task
- *   is expected to send an sys_ipc_hangup after cleaning up its internal
+ *   is expected to call sys_ipc_hangup after cleaning up its internal
  *   structures.
  *
@@ -137,17 +137,4 @@
 #include <mm/slab.h>
 
-static bool phone_reclaim(kobject_t *kobj)
-{
-	bool gc = false;
-
-	mutex_lock(&kobj->phone->lock);
-	if (kobj->phone->state == IPC_PHONE_HUNGUP &&
-	    atomic_get(&kobj->phone->active_calls) == 0)
-		gc = true;
-	mutex_unlock(&kobj->phone->lock);
-
-	return gc;
-}
-
 static void phone_destroy(void *arg)
 {
@@ -157,5 +144,4 @@
 
 static kobject_ops_t phone_kobject_ops = {
-	.reclaim = phone_reclaim,
 	.destroy = phone_destroy
 };
@@ -164,11 +150,13 @@
 /** Allocate new phone in the specified task.
  *
- * @param task  Task for which to allocate a new phone.
- *
- * @param[out] out_handle  New phone capability handle.
+ * @param[in]  task     Task for which to allocate a new phone.
+ * @param[in]  publish  If true, the new capability will be published.
+ * @param[out] phandle  New phone capability handle.
+ * @param[out] kobject  New phone kobject.
  *
  * @return  An error code if a new capability cannot be allocated.
  */
-errno_t phone_alloc(task_t *task, cap_handle_t *out_handle)
+errno_t phone_alloc(task_t *task, bool publish, cap_handle_t *phandle,
+    kobject_t **kobject)
 {
 	cap_handle_t handle;
@@ -180,6 +168,6 @@
 			return ENOMEM;
 		}
-		kobject_t *kobject = malloc(sizeof(kobject_t), FRAME_ATOMIC);
-		if (!kobject) {
+		kobject_t *kobj = malloc(sizeof(kobject_t), FRAME_ATOMIC);
+		if (!kobj) {
 			cap_free(TASK, handle);
 			slab_free(phone_cache, phone);
@@ -190,11 +178,14 @@
 		phone->state = IPC_PHONE_CONNECTING;
 
-		kobject_initialize(kobject, KOBJECT_TYPE_PHONE, phone,
+		kobject_initialize(kobj, KOBJECT_TYPE_PHONE, phone,
 		    &phone_kobject_ops);
-		phone->kobject = kobject;
-
-		cap_publish(task, handle, kobject);
-
-		*out_handle = handle;
+		phone->kobject = kobj;
+
+		if (publish)
+			cap_publish(task, handle, kobj);
+
+		*phandle = handle;
+		if (kobject)
+			*kobject = kobj;
 	}
 	return rc;
@@ -214,29 +205,8 @@
 		return;
 
-	assert(kobj->phone);
-	assert(kobj->phone->state == IPC_PHONE_CONNECTING);
-
 	kobject_put(kobj);
 	cap_free(TASK, handle);
 }
 
-/** Connect phone to a given answerbox.
- *
- * @param handle  Capability handle of the phone to be connected.
- * @param box     Answerbox to which to connect the phone.
- * @return        True if the phone was connected, false otherwise.
- */
-bool phone_connect(cap_handle_t handle, answerbox_t *box)
-{
-	kobject_t *phone_obj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE);
-	if (!phone_obj)
-		return false;
-
-	assert(phone_obj->phone->state == IPC_PHONE_CONNECTING);
-
-	/* Hand over phone_obj reference to the answerbox */
-	return ipc_phone_connect(phone_obj->phone, box);
-}
-
 /** @}
  */
Index: kernel/generic/src/ipc/kbox.c
===================================================================
--- kernel/generic/src/ipc/kbox.c	(revision 30f1a25ef3be685966ce1377e11888810d47aab9)
+++ kernel/generic/src/ipc/kbox.c	(revision e6d670fd4926748dbee919b7e1014dcb33cb1748)
@@ -253,5 +253,5 @@
 	/* Allocate a new phone. */
 	cap_handle_t phone_handle;
-	errno_t rc = phone_alloc(TASK, &phone_handle);
+	errno_t rc = phone_alloc(TASK, true, &phone_handle, NULL);
 	if (rc != EOK) {
 		mutex_unlock(&task->kb.cleanup_lock);
Index: kernel/generic/src/ipc/ops/conctmeto.c
===================================================================
--- kernel/generic/src/ipc/ops/conctmeto.c	(revision 30f1a25ef3be685966ce1377e11888810d47aab9)
+++ kernel/generic/src/ipc/ops/conctmeto.c	(revision e6d670fd4926748dbee919b7e1014dcb33cb1748)
@@ -42,19 +42,21 @@
 static errno_t request_preprocess(call_t *call, phone_t *phone)
 {
+	/*
+	 * Create the new phone and capability, but don't publish them yet.
+	 * That will be done once the phone is connected.
+	 */
 	cap_handle_t phone_handle;
-	errno_t rc = phone_alloc(TASK, &phone_handle);
-
-	/* Remember the phone capability or that an error occured. */
-	call->priv = (rc == EOK) ? phone_handle : -1;
-
+	kobject_t *phone_obj;
+	errno_t rc = phone_alloc(TASK, false, &phone_handle, &phone_obj);
 	if (rc != EOK) {
+		call->priv = -1;
 		return rc;
 	}
 
-	/* Set arg5 for server */
-	kobject_t *phone_obj = kobject_get(TASK, phone_handle,
-	    KOBJECT_TYPE_PHONE);
 	/* Hand over phone_obj's reference to ARG5 */
 	IPC_SET_ARG5(call->data, (sysarg_t) phone_obj->phone);
+
+	/* Remember the handle */
+	call->priv = phone_handle;
 
 	return EOK;
@@ -65,13 +67,13 @@
 	cap_handle_t phone_handle = (cap_handle_t) call->priv;
 
-	if (phone_handle < 0) {
+	if (phone_handle < 0)
 		return EOK;
-	}
 
-	phone_dealloc(phone_handle);
 	/* Hand over reference from ARG5 to phone->kobject */
 	phone_t *phone = (phone_t *) IPC_GET_ARG5(call->data);
-	/* Drop phone_obj's reference */
+	/* Drop phone->kobject's reference */
 	kobject_put(phone->kobject);
+	cap_free(TASK, phone_handle);
+
 	return EOK;
 }
@@ -82,5 +84,11 @@
 	phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);
 
-	/* If the user accepted call, connect */
+	/*
+	 * Get an extra reference and pass it in the answer data.
+	 */
+	kobject_add_ref(phone->kobject);
+	IPC_SET_ARG5(answer->data, (sysarg_t) phone);
+
+	/* If the user accepted the call, connect */
 	if (IPC_GET_RETVAL(answer->data) == EOK) {
 		/* Hand over reference from phone to the answerbox */
@@ -96,14 +104,23 @@
 {
 	cap_handle_t phone_handle = (cap_handle_t) answer->priv;
+	phone_t *phone = (phone_t *) IPC_GET_ARG5(answer->data);
 
 	if (IPC_GET_RETVAL(answer->data)) {
 		if (phone_handle >= 0) {
 			/*
-			 * The phone was indeed allocated and now needs
-			 * to be deallocated.
+			 * Cleanup the unpublished capability and drop
+			 * phone->kobject's reference.
 			 */
-			phone_dealloc(phone_handle);
+			kobject_put(phone->kobject);
+			cap_free(TASK, phone_handle);
 		}
 	} else {
+		/*
+		 * Publish the capability. Publishing the capability this late
+		 * is important for ipc_cleanup() where we want to have a
+		 * capability for each phone that wasn't hung up by the user.
+		 */
+		cap_publish(TASK, phone_handle, phone->kobject);
+
 		IPC_SET_ARG5(answer->data, phone_handle);
 	}
Index: kernel/generic/src/ipc/ops/concttome.c
===================================================================
--- kernel/generic/src/ipc/ops/concttome.c	(revision 30f1a25ef3be685966ce1377e11888810d47aab9)
+++ kernel/generic/src/ipc/ops/concttome.c	(revision e6d670fd4926748dbee919b7e1014dcb33cb1748)
@@ -43,5 +43,7 @@
 {
 	cap_handle_t phone_handle;
-	errno_t rc = phone_alloc(TASK, &phone_handle);
+	kobject_t *phone_obj;
+	errno_t rc = phone_alloc(TASK, false, &phone_handle, &phone_obj);
+	call->priv = (sysarg_t) phone_obj;
 	IPC_SET_ARG5(call->data, (rc == EOK) ? phone_handle : -1);
 	return 0;
@@ -51,7 +53,10 @@
 {
 	cap_handle_t phone_handle = (cap_handle_t) IPC_GET_ARG5(*olddata);
+	kobject_t *phone_obj = (kobject_t *) answer->priv;
 
-	if (phone_handle >= 0)
-		phone_dealloc(phone_handle);
+	if (phone_handle >= 0) {
+		kobject_put(phone_obj);
+		cap_free(TASK, phone_handle);
+	}
 
 	return EOK;
@@ -61,4 +66,5 @@
 {
 	cap_handle_t phone_handle = (cap_handle_t) IPC_GET_ARG5(*olddata);
+	kobject_t *phone_obj = (kobject_t *) answer->priv;
 
 	if (IPC_GET_RETVAL(answer->data) != EOK) {
@@ -66,12 +72,21 @@
 		answer_cleanup(answer, olddata);
 	} else if (phone_handle >= 0) {
-		/* The connection was accepted */
-		if (phone_connect(phone_handle, &answer->sender->answerbox)) {
+		/*
+		 * The connection was accepted
+		 */
+
+		/*
+		 * We need to create another reference as the one we have now
+		 * will be consumed by ipc_phone_connect().
+		 */
+		kobject_add_ref(phone_obj);
+
+		if (ipc_phone_connect(phone_obj->phone,
+		    &answer->sender->answerbox)) {
+			/* Pass the reference to the capability */
+			cap_publish(TASK, phone_handle, phone_obj);
 			/* Set 'phone hash' as ARG5 of response */
-			kobject_t *phone_obj = kobject_get(TASK, phone_handle,
-			    KOBJECT_TYPE_PHONE);
 			IPC_SET_ARG5(answer->data,
 			    (sysarg_t) phone_obj->phone);
-			kobject_put(phone_obj);
 		} else {
 			/* The answerbox is shutting down. */
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision 30f1a25ef3be685966ce1377e11888810d47aab9)
+++ kernel/generic/src/ipc/sysipc.c	(revision e6d670fd4926748dbee919b7e1014dcb33cb1748)
@@ -724,5 +724,5 @@
 sys_errno_t sys_ipc_hangup(sysarg_t handle)
 {
-	kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE);
+	kobject_t *kobj = cap_unpublish(TASK, handle, KOBJECT_TYPE_PHONE);
 	if (!kobj)
 		return ENOENT;
@@ -730,4 +730,5 @@
 	errno_t rc = ipc_phone_hangup(kobj->phone);
 	kobject_put(kobj);
+	cap_free(TASK, handle);
 	return rc;
 }
Index: kernel/generic/src/main/kinit.c
===================================================================
--- kernel/generic/src/main/kinit.c	(revision 30f1a25ef3be685966ce1377e11888810d47aab9)
+++ kernel/generic/src/main/kinit.c	(revision e6d670fd4926748dbee919b7e1014dcb33cb1748)
@@ -265,9 +265,9 @@
 				    PERM_IO_MANAGER | PERM_IRQ_REG);
 
-				if (!ipc_phone_0) {
-					ipc_phone_0 = &programs[i].task->answerbox;
+				if (!ipc_box_0) {
+					ipc_box_0 = &programs[i].task->answerbox;
 					/*
-					 * Hold the first task so that the
-					 * ipc_phone_0 remains a valid pointer
+					 * Hold the first task so that
+					 * ipc_box_0 remains a valid pointer
 					 * even if the first task exits for
 					 * whatever reason.
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision 30f1a25ef3be685966ce1377e11888810d47aab9)
+++ kernel/generic/src/proc/task.c	(revision e6d670fd4926748dbee919b7e1014dcb33cb1748)
@@ -129,7 +129,7 @@
 	size_t tasks_left;
 
-	if (ipc_phone_0) {
-		task_t *task_0 = ipc_phone_0->task;
-		ipc_phone_0 = NULL;
+	if (ipc_box_0) {
+		task_t *task_0 = ipc_box_0->task;
+		ipc_box_0 = NULL;
 		/*
 		 * The first task is held by kinit(), we need to release it or
@@ -243,8 +243,8 @@
 #endif
 
-	if ((ipc_phone_0) &&
-	    (container_check(ipc_phone_0->task->container, task->container))) {
+	if ((ipc_box_0) &&
+	    (container_check(ipc_box_0->task->container, task->container))) {
 		cap_handle_t phone_handle;
-		errno_t rc = phone_alloc(task, &phone_handle);
+		errno_t rc = phone_alloc(task, true, &phone_handle, NULL);
 		if (rc != EOK) {
 			task->as = NULL;
@@ -256,5 +256,5 @@
 		kobject_t *phone_obj = kobject_get(task, phone_handle,
 		    KOBJECT_TYPE_PHONE);
-		(void) ipc_phone_connect(phone_obj->phone, ipc_phone_0);
+		(void) ipc_phone_connect(phone_obj->phone, ipc_box_0);
 	}
 
