/*
- * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
*
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
*
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* @OSF_COPYRIGHT@
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
+/*
+ * NOTICE: This file was modified by McAfee Research in 2004 to introduce
+ * support for mandatory and extensible security protections. This notice
+ * is included in support of clause 2.2 (b) of the Apple Public License,
+ * Version 2.0.
+ * Copyright (c) 2005-2006 SPARTA, Inc.
+ */
/*
*/
/*
#include <ipc/ipc_pset.h>
#include <ipc/ipc_right.h>
#include <ipc/ipc_kmsg.h>
+#include <ipc/ipc_labelh.h>
#include <kern/misc_protos.h>
+#include <security/mac_mach_internal.h>
+
+#include <mach/security_server.h>
/*
* Forward declarations
* Routine: mach_port_names_helper
* Purpose:
* A helper function for mach_port_names.
+ *
+ * Conditions:
+ * Space containing entry is [at least] read-locked.
*/
void
{
ipc_entry_bits_t bits;
ipc_port_request_index_t request;
- mach_port_type_t type;
+ mach_port_type_t type = 0;
ipc_entry_num_t actual;
+ ipc_port_t port;
bits = entry->ie_bits;
request = entry->ie_request;
- if (bits & MACH_PORT_TYPE_SEND_RIGHTS) {
- ipc_port_t port;
- boolean_t died;
+ port = (ipc_port_t) entry->ie_object;
- port = (ipc_port_t) entry->ie_object;
- assert(port != IP_NULL);
+ if (bits & MACH_PORT_TYPE_RECEIVE) {
+ assert(IP_VALID(port));
- /*
- * The timestamp serializes mach_port_names
- * with ipc_port_destroy. If the port died,
- * but after mach_port_names started, pretend
- * that it isn't dead.
- */
+ if (request != IE_REQ_NONE) {
+ ip_lock(port);
+ assert(ip_active(port));
+ type |= ipc_port_request_type(port, name, request);
+ ip_unlock(port);
+ }
- ip_lock(port);
- died = (!ip_active(port) &&
- IP_TIMESTAMP_ORDER(port->ip_timestamp, timestamp));
- ip_unlock(port);
+ } else if (bits & MACH_PORT_TYPE_SEND_RIGHTS) {
+ mach_port_type_t reqtype;
- if (died) {
- /* pretend this is a dead-name entry */
+ assert(IP_VALID(port));
+ ip_lock(port);
+ reqtype = (request != IE_REQ_NONE) ?
+ ipc_port_request_type(port, name, request) : 0;
+
+ /*
+ * If the port is alive, or was alive when the mach_port_names
+ * started, then return that fact. Otherwise, pretend we found
+ * a dead name entry.
+ */
+ if (ip_active(port) || IP_TIMESTAMP_ORDER(timestamp, port->ip_timestamp)) {
+ type |= reqtype;
+ } else {
bits &= ~(IE_BITS_TYPE_MASK);
bits |= MACH_PORT_TYPE_DEAD_NAME;
- if (request != 0)
+ /* account for additional reference for dead-name notification */
+ if (reqtype != 0)
bits++;
- request = 0;
}
+ ip_unlock(port);
}
- type = IE_BITS_TYPE(bits);
- if (request != 0)
- type |= MACH_PORT_TYPE_DNREQUEST;
+ type |= IE_BITS_TYPE(bits);
actual = *actualp;
names[actual] = name;
mach_port_type_t **typesp,
mach_msg_type_number_t *typesCnt)
{
- ipc_tree_entry_t tentry;
ipc_entry_t table;
ipc_entry_num_t tsize;
mach_port_index_t index;
vm_size_t size_needed;
is_read_lock(space);
- if (!space->is_active) {
+ if (!is_active(space)) {
is_read_unlock(space);
if (size != 0) {
kmem_free(ipc_kernel_map, addr1, size);
}
/* upper bound on number of names in the space */
-
- bound = space->is_table_size + space->is_tree_total;
+ bound = space->is_table_size;
size_needed = round_page(bound * sizeof(mach_port_name_t));
if (size_needed <= size)
}
}
- for (tentry = ipc_splay_traverse_start(&space->is_tree);
- tentry != ITE_NULL;
- tentry = ipc_splay_traverse_next(&space->is_tree, FALSE)) {
- ipc_entry_t entry = &tentry->ite_entry;
- mach_port_name_t name = tentry->ite_name;
-
- assert(IE_BITS_TYPE(tentry->ite_bits) != MACH_PORT_TYPE_NONE);
- mach_port_names_helper(timestamp, entry, name, names,
- types, &actual);
- }
- ipc_splay_traverse_finish(&space->is_tree);
is_read_unlock(space);
if (actual == 0) {
kr = ipc_right_lookup_write(space, name, &entry);
if (kr != KERN_SUCCESS)
return kr;
- /* space is write-locked and active */
+ /* space is write-locked and active */
kr = ipc_right_info(space, name, entry, typep, &urefs);
- if (kr == KERN_SUCCESS)
- is_write_unlock(space);
/* space is unlocked */
+
+#if 1
+ /* JMM - workaround rdar://problem/9121297 (CF being too picky on these bits). */
+ *typep &= ~(MACH_PORT_TYPE_SPREQUEST | MACH_PORT_TYPE_SPREQUEST_DELAYED);
+#endif
+
return kr;
}
* KERN_INVALID_VALUE The nname isn't a legal name.
* KERN_NAME_EXISTS The nname already denotes a right.
* KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
+ *
+ * This interface is obsolete and always returns
+ * KERN_NOT_SUPPORTED.
*/
kern_return_t
mach_port_rename(
- ipc_space_t space,
- mach_port_name_t oname,
- mach_port_name_t nname)
+ __unused ipc_space_t space,
+ __unused mach_port_name_t oname,
+ __unused mach_port_name_t nname)
{
- if (space == IS_NULL)
- return KERN_INVALID_TASK;
-
- if (!MACH_PORT_VALID(oname))
- return KERN_INVALID_NAME;
-
- if (!MACH_PORT_VALID(nname))
- return KERN_INVALID_VALUE;
-
- return ipc_object_rename(space, oname, nname);
+ return KERN_NOT_SUPPORTED;
}
+
/*
* Routine: mach_port_allocate_name [kernel call]
* Purpose:
if (qosp->name) {
if (!MACH_PORT_VALID (*namep))
return (KERN_INVALID_VALUE);
- if (is_fast_space (space))
- return (KERN_FAILURE);
}
if (qosp->prealloc) {
return KERN_RESOURCE_SHORTAGE;
} else {
mach_msg_size_t size = qosp->len + MAX_TRAILER_SIZE;
+
if (right != MACH_PORT_RIGHT_RECEIVE)
return (KERN_INVALID_VALUE);
- kmsg = (ipc_kmsg_t)ipc_kmsg_alloc(size);
+
+ kmsg = (ipc_kmsg_t)ipc_kmsg_prealloc(size);
if (kmsg == IKM_NULL)
return (KERN_RESOURCE_SHORTAGE);
}
return kr;
/* space is write-locked and active */
- kr = ipc_right_destroy(space, name, entry);
- is_write_unlock(space);
+ kr = ipc_right_destroy(space, name, entry); /* unlocks space */
return kr;
}
kr = ipc_right_lookup_write(space, name, &entry);
if (kr != KERN_SUCCESS)
return kr;
+
/* space is write-locked and active */
+ kr = ipc_right_info(space, name, entry, &type, &urefs);
+ /* space is unlocked */
- kr = ipc_right_info(space, name, entry, &type, &urefs); /* unlocks */
if (kr != KERN_SUCCESS)
- return kr; /* space is unlocked */
- is_write_unlock(space);
+ return kr;
if (type & MACH_PORT_TYPE(right))
switch (right) {
return KERN_SUCCESS;
}
+/*
+ * Routine: mach_port_get_context [kernel call]
+ * Purpose:
+ * Returns a receive right's context pointer.
+ * Conditions:
+ * Nothing locked.
+ * Returns:
+ * KERN_SUCCESS Set context pointer.
+ * KERN_INVALID_TASK The space is null.
+ * KERN_INVALID_TASK The space is dead.
+ * KERN_INVALID_NAME The name doesn't denote a right.
+ * KERN_INVALID_RIGHT Name doesn't denote receive rights.
+ */
+
+kern_return_t
+mach_port_get_context(
+ ipc_space_t space,
+ mach_port_name_t name,
+ mach_vm_address_t *context)
+{
+ ipc_port_t port;
+ kern_return_t kr;
+
+ if (space == IS_NULL)
+ return KERN_INVALID_TASK;
+
+ if (!MACH_PORT_VALID(name))
+ return KERN_INVALID_RIGHT;
+
+ kr = ipc_port_translate_receive(space, name, &port);
+ if (kr != KERN_SUCCESS)
+ return kr;
+
+ /* port is locked and active */
+ *context = port->ip_context;
+
+ ip_unlock(port);
+ return KERN_SUCCESS;
+}
+
+
+/*
+ * Routine: mach_port_set_context [kernel call]
+ * Purpose:
+ * Changes a receive right's context pointer.
+ * Conditions:
+ * Nothing locked.
+ * Returns:
+ * KERN_SUCCESS Set context pointer.
+ * KERN_INVALID_TASK The space is null.
+ * KERN_INVALID_TASK The space is dead.
+ * KERN_INVALID_NAME The name doesn't denote a right.
+ * KERN_INVALID_RIGHT Name doesn't denote receive rights.
+ */
+
+kern_return_t
+mach_port_set_context(
+ ipc_space_t space,
+ mach_port_name_t name,
+ mach_vm_address_t context)
+{
+ ipc_port_t port;
+ kern_return_t kr;
+
+ if (space == IS_NULL)
+ return KERN_INVALID_TASK;
+
+ if (!MACH_PORT_VALID(name))
+ return KERN_INVALID_RIGHT;
+
+ kr = ipc_port_translate_receive(space, name, &port);
+ if (kr != KERN_SUCCESS)
+ return kr;
+
+ /* port is locked and active */
+ port->ip_context = context;
+
+ ip_unlock(port);
+ return KERN_SUCCESS;
+}
+
+
/*
* Routine: mach_port_gst_helper
+ * Conditions:
+ * portspace is locked for both the recieve right and pset
+ * under observation.
* Purpose:
* A helper function for mach_port_get_set_status.
*/
mach_port_name_t name;
assert(port != IP_NULL);
-
- ip_lock(port);
+ /*
+ * The space lock is held by the calling function,
+ * hence it is OK to read name without the port lock.
+ */
assert(ip_active(port));
-
name = port->ip_receiver_name;
assert(name != MACH_PORT_NULL);
- ip_unlock(port);
-
if (ipc_pset_member(pset, port)) {
ipc_entry_num_t actual = *actualp;
size = PAGE_SIZE; /* initial guess */
for (;;) {
- ipc_tree_entry_t tentry;
ipc_entry_t entry, table;
ipc_entry_num_t tsize;
mach_port_index_t index;
/* the port set must be active */
names = (mach_port_name_t *) addr;
- maxnames = size / sizeof(mach_port_name_t);
+ maxnames = (ipc_entry_num_t)(size / sizeof(mach_port_name_t));
actual = 0;
table = space->is_table;
for (index = 0; index < tsize; index++) {
ipc_entry_t ientry = &table[index];
+ ipc_port_t port = (ipc_port_t) ientry->ie_object;
- if (ientry->ie_bits & MACH_PORT_TYPE_RECEIVE) {
- ipc_port_t port =
- (ipc_port_t) ientry->ie_object;
-
+ if (ientry->ie_bits & MACH_PORT_TYPE_RECEIVE &&
+ port->ip_pset_count > 0) {
mach_port_gst_helper(pset, port,
maxnames, names, &actual);
}
}
- for (tentry = ipc_splay_traverse_start(&space->is_tree);
- tentry != ITE_NULL;
- tentry = ipc_splay_traverse_next(&space->is_tree,FALSE)) {
- ipc_entry_bits_t bits = tentry->ite_bits;
-
- assert(IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE);
-
- if (bits & MACH_PORT_TYPE_RECEIVE) {
- ipc_port_t port = (ipc_port_t) tentry->ite_object;
-
- mach_port_gst_helper(pset, port, maxnames,
- names, &actual);
- }
- }
- ipc_splay_traverse_finish(&space->is_tree);
is_read_unlock(space);
if (actual <= maxnames)
ipc_port_t port;
ipc_pset_t nset;
kern_return_t kr;
+ wait_queue_link_t wql;
+ queue_head_t links_data;
+ queue_t links = &links_data;
if (space == IS_NULL)
return KERN_INVALID_TASK;
if (after == MACH_PORT_DEAD)
return KERN_INVALID_RIGHT;
+ else if (after == MACH_PORT_NULL)
+ wql = WAIT_QUEUE_LINK_NULL;
+ else
+ wql = wait_queue_link_allocate();
+
+ queue_init(links);
kr = ipc_right_lookup_read(space, member, &entry);
if (kr != KERN_SUCCESS)
- return kr;
+ goto done;
/* space is read-locked and active */
if ((entry->ie_bits & MACH_PORT_TYPE_RECEIVE) == 0) {
is_read_unlock(space);
- return KERN_INVALID_RIGHT;
+ kr = KERN_INVALID_RIGHT;
+ goto done;
}
port = (ipc_port_t) entry->ie_object;
entry = ipc_entry_lookup(space, after);
if (entry == IE_NULL) {
is_read_unlock(space);
- return KERN_INVALID_NAME;
+ kr = KERN_INVALID_NAME;
+ goto done;
}
if ((entry->ie_bits & MACH_PORT_TYPE_PORT_SET) == 0) {
is_read_unlock(space);
- return KERN_INVALID_RIGHT;
+ kr = KERN_INVALID_RIGHT;
+ goto done;
}
nset = (ipc_pset_t) entry->ie_object;
assert(nset != IPS_NULL);
}
ip_lock(port);
- ipc_pset_remove_from_all(port);
+ ipc_pset_remove_from_all(port, links);
if (nset != IPS_NULL) {
ips_lock(nset);
- kr = ipc_pset_add(nset, port);
+ kr = ipc_pset_add(nset, port, wql);
ips_unlock(nset);
}
ip_unlock(port);
is_read_unlock(space);
+
+ done:
+ if (kr != KERN_SUCCESS && wql != WAIT_QUEUE_LINK_NULL)
+ wait_queue_link_free(wql);
+ while(!queue_empty(links)) {
+ wql = (wait_queue_link_t) dequeue(links);
+ wait_queue_link_free(wql);
+ }
+
return kr;
}
break;
}
+ case MACH_NOTIFY_SEND_POSSIBLE:
+
+ if (!MACH_PORT_VALID(name)) {
+ return KERN_INVALID_ARGUMENT;
+ }
+
+ kr = ipc_right_request_alloc(space, name, sync != 0,
+ TRUE, notify, previousp);
+ if (kr != KERN_SUCCESS)
+ return kr;
+ break;
+
case MACH_NOTIFY_DEAD_NAME:
if (!MACH_PORT_VALID(name)) {
return KERN_INVALID_ARGUMENT;
}
- kr = ipc_right_dnrequest(space, name, sync != 0,
- notify, previousp);
+ kr = ipc_right_request_alloc(space, name, sync != 0,
+ FALSE, notify, previousp);
if (kr != KERN_SUCCESS)
return kr;
break;
return kr;
/* port is locked and active */
- table = port->ip_dnrequests;
+ table = port->ip_requests;
if (table == IPR_NULL)
*(int *)info = 0;
else
return kr;
/* port is locked and active */
- kr = ipc_port_dngrow(port, *(int *)info);
+ kr = ipc_port_request_grow(port, *(int *)info);
if (kr != KERN_SUCCESS)
return kr;
break;
ipc_object_t obj;
ipc_object_t psobj;
kern_return_t kr;
+ wait_queue_link_t wql;
if (space == IS_NULL)
return KERN_INVALID_TASK;
if (!MACH_PORT_VALID(name) || !MACH_PORT_VALID(psname))
return KERN_INVALID_RIGHT;
+ wql = wait_queue_link_allocate();
+
kr = ipc_object_translate_two(space,
name, MACH_PORT_RIGHT_RECEIVE, &obj,
psname, MACH_PORT_RIGHT_PORT_SET, &psobj);
if (kr != KERN_SUCCESS)
- return kr;
+ goto done;
/* obj and psobj are locked (and were locked in that order) */
assert(psobj != IO_NULL);
assert(obj != IO_NULL);
- kr = ipc_pset_add((ipc_pset_t)psobj, (ipc_port_t)obj);
+ kr = ipc_pset_add((ipc_pset_t)psobj, (ipc_port_t)obj, wql);
io_unlock(psobj);
io_unlock(obj);
+
+ done:
+ if (kr != KERN_SUCCESS)
+ wait_queue_link_free(wql);
+
return kr;
}
ipc_object_t psobj;
ipc_object_t obj;
kern_return_t kr;
+ wait_queue_link_t wql = WAIT_QUEUE_LINK_NULL;
if (space == IS_NULL)
return KERN_INVALID_TASK;
assert(psobj != IO_NULL);
assert(obj != IO_NULL);
- kr = ipc_pset_remove((ipc_pset_t)psobj, (ipc_port_t)obj);
+ kr = ipc_pset_remove((ipc_pset_t)psobj, (ipc_port_t)obj, &wql);
io_unlock(psobj);
io_unlock(obj);
+
+ if (wql != WAIT_QUEUE_LINK_NULL)
+ wait_queue_link_free(wql);
+
return kr;
}
kern_return_t kr;
is_write_lock(space);
+
+ if (!is_active(space)) {
+ is_write_unlock(space);
+ return KERN_INVALID_TASK;
+ }
+
kr = ipc_entry_grow_table(space, table_entries);
if (kr == KERN_SUCCESS)
is_write_unlock(space);
return kr;
}
+/*
+ * Get a (new) label handle representing the given port's port label.
+ */
+#if CONFIG_MACF_MACH
+kern_return_t
+mach_get_label(
+ ipc_space_t space,
+ mach_port_name_t name,
+ mach_port_name_t *outlabel)
+{
+ ipc_entry_t entry;
+ ipc_port_t port;
+ struct label outl;
+ kern_return_t kr;
+ int dead;
+
+ if (!MACH_PORT_VALID(name))
+ return KERN_INVALID_NAME;
+
+ /* Lookup the port name in the task's space. */
+ kr = ipc_right_lookup_write(space, name, &entry);
+ if (kr != KERN_SUCCESS)
+ return kr;
+
+ port = (ipc_port_t) entry->ie_object;
+ dead = ipc_right_check(space, port, name, entry);
+ if (dead) {
+ is_write_unlock(space);
+ ip_release(port);
+ return KERN_INVALID_RIGHT;
+ }
+ /* port is now locked */
+
+ is_write_unlock(space);
+ /* Make sure we are not dealing with a label handle. */
+ if (ip_kotype(port) == IKOT_LABELH) {
+ /* already is a label handle! */
+ ip_unlock(port);
+ return KERN_INVALID_ARGUMENT;
+ }
+
+ /* Copy the port label and stash it in a new label handle. */
+ mac_port_label_init(&outl);
+ mac_port_label_copy(&port->ip_label, &outl);
+ kr = labelh_new_user(space, &outl, outlabel);
+ ip_unlock(port);
+
+ return KERN_SUCCESS;
+}
+#else
+kern_return_t
+mach_get_label(
+ __unused ipc_space_t space,
+ __unused mach_port_name_t name,
+ __unused mach_port_name_t *outlabel)
+{
+ return KERN_INVALID_ARGUMENT;
+}
+#endif
+
+/*
+ * also works on label handles
+ */
+#if CONFIG_MACF_MACH
+kern_return_t
+mach_get_label_text(
+ ipc_space_t space,
+ mach_port_name_t name,
+ labelstr_t policies,
+ labelstr_t outlabel)
+{
+ ipc_entry_t entry;
+ ipc_port_t port;
+ kern_return_t kr;
+ struct label *l;
+ int dead;
+
+ if (space == IS_NULL || space->is_task == NULL)
+ return KERN_INVALID_TASK;
+
+ if (!MACH_PORT_VALID(name))
+ return KERN_INVALID_NAME;
+
+ kr = ipc_right_lookup_write(space, name, &entry);
+ if (kr != KERN_SUCCESS)
+ return kr;
+
+ port = (ipc_port_t)entry->ie_object;
+ dead = ipc_right_check(space, port, name, entry);
+ if (dead) {
+ is_write_unlock(space);
+ ip_release(port);
+ return KERN_INVALID_RIGHT;
+ }
+ /* object (port) is now locked */
+
+ is_write_unlock (space);
+ l = io_getlabel(entry->ie_object);
+
+ mac_port_label_externalize(l, policies, outlabel, 512, 0);
+
+ io_unlocklabel(entry->ie_object);
+ io_unlock(entry->ie_object);
+ return KERN_SUCCESS;
+}
+#else
+kern_return_t
+mach_get_label_text(
+ __unused ipc_space_t space,
+ __unused mach_port_name_t name,
+ __unused labelstr_t policies,
+ __unused labelstr_t outlabel)
+{
+ return KERN_INVALID_ARGUMENT;
+}
+#endif
+
+
+#if CONFIG_MACF_MACH
+kern_return_t
+mach_set_port_label(
+ ipc_space_t space,
+ mach_port_name_t name,
+ labelstr_t labelstr)
+{
+ ipc_entry_t entry;
+ kern_return_t kr;
+ struct label inl;
+ ipc_port_t port;
+ int rc;
+
+ if (space == IS_NULL || space->is_task == NULL)
+ return KERN_INVALID_TASK;
+
+ if (!MACH_PORT_VALID(name))
+ return KERN_INVALID_NAME;
+
+ mac_port_label_init(&inl);
+ rc = mac_port_label_internalize(&inl, labelstr);
+ if (rc)
+ return KERN_INVALID_ARGUMENT;
+
+ kr = ipc_right_lookup_write(space, name, &entry);
+ if (kr != KERN_SUCCESS)
+ return kr;
+
+ if (io_otype(entMACry->ie_object) != IOT_PORT) {
+ is_write_unlock(space);
+ return KERN_INVALID_RIGHT;
+ }
+
+ port = (ipc_port_t) entry->ie_object;
+ ip_lock(port);
+
+ tasklabel_lock(space->is_task);
+ rc = mac_port_check_label_update(&space->is_task->maclabel,
+ &port->ip_label, &inl);
+ tasklabel_unlock(space->is_task);
+ if (rc)
+ kr = KERN_NO_ACCESS;
+ else
+ mac_port_label_copy(&inl, &port->ip_label);
+
+ ip_unlock(port);
+ is_write_unlock(space);
+ return kr;
+}
+#else
+kern_return_t
+mach_set_port_label(
+ ipc_space_t space __unused,
+ mach_port_name_t name __unused,
+ labelstr_t labelstr __unused)
+{
+ return KERN_INVALID_ARGUMENT;
+}
+#endif