Example #1
0
kern_return_t
mach_port_set_attributes(
	ipc_space_t		space,
	mach_port_name_t	name,
	int			flavor,
        mach_port_info_t	info,
        mach_msg_type_number_t	count)
{
	ipc_port_t port;
	kern_return_t kr;
        
	if (space == IS_NULL)
		return KERN_INVALID_TASK;

        switch (flavor) {
                
        case MACH_PORT_LIMITS_INFO: {
                mach_port_limits_t *mplp = (mach_port_limits_t *)info;
                
                if (count < MACH_PORT_LIMITS_INFO_COUNT)
                        return KERN_FAILURE;
                
                if (mplp->mpl_qlimit > MACH_PORT_QLIMIT_MAX)
                        return KERN_INVALID_VALUE;

		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 */

                ipc_mqueue_set_qlimit(&port->ip_messages, mplp->mpl_qlimit);
                ip_unlock(port);
                break;
        }
	case MACH_PORT_DNREQUESTS_SIZE: {
                if (count < MACH_PORT_DNREQUESTS_SIZE_COUNT)
                        return KERN_FAILURE;

		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 */
		
		kr = ipc_port_dngrow(port, *(int *)info);
		if (kr != KERN_SUCCESS)
			return kr;
		break;
	}
        default:
		return KERN_INVALID_ARGUMENT;
                /*NOTREACHED*/
        }
	return KERN_SUCCESS;
}
Example #2
0
kern_return_t
ipc_right_dnrequest(
	ipc_space_t	space,
	mach_port_t	name,
	boolean_t	immediate,
	ipc_port_t	notify,
	ipc_port_t	*previousp)
{
	ipc_port_t previous;

	for (;;) {
		ipc_entry_t entry;
		ipc_entry_bits_t bits;
		kern_return_t kr;

		kr = ipc_right_lookup_write(space, name, &entry);
		if (kr != KERN_SUCCESS)
			return kr;
		/* space is write-locked and active */

		bits = entry->ie_bits;
		if (bits & MACH_PORT_TYPE_PORT_RIGHTS) {
			ipc_port_t port;
			ipc_port_request_index_t request;

			port = (ipc_port_t) entry->ie_object;
			assert(port != IP_NULL);

			if (!ipc_right_check(space, port, name, entry)) {
				/* port is locked and active */

				if (notify == IP_NULL) {
					previous = ipc_right_dncancel_macro(
						space, port, name, entry);

					ip_unlock(port);
					is_write_unlock(space);
					break;
				}

				/*
				 *	If a registered soright exists,
				 *	want to atomically switch with it.
				 *	If ipc_port_dncancel finds us a
				 *	soright, then the following
				 *	ipc_port_dnrequest will reuse
				 *	that slot, so we are guaranteed
				 *	not to unlock and retry.
				 */

				previous = ipc_right_dncancel_macro(space,
							port, name, entry);

				kr = ipc_port_dnrequest(port, name, notify,
							&request);
				if (kr != KERN_SUCCESS) {
					assert(previous == IP_NULL);
					is_write_unlock(space);

					kr = ipc_port_dngrow(port);
					/* port is unlocked */
					if (kr != KERN_SUCCESS)
						return kr;

					continue;
				}

				assert(request != 0);
				ip_unlock(port);

				entry->ie_request = request;
				is_write_unlock(space);
				break;
			}

			bits = entry->ie_bits;
			assert(bits & MACH_PORT_TYPE_DEAD_NAME);
		}

		if ((bits & MACH_PORT_TYPE_DEAD_NAME) &&
		    immediate && (notify != IP_NULL)) {
			mach_port_urefs_t urefs = IE_BITS_UREFS(bits);

			assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
			assert(urefs > 0);

			if (MACH_PORT_UREFS_OVERFLOW(urefs, 1)) {
				is_write_unlock(space);
				return KERN_UREFS_OVERFLOW;
			}

			entry->ie_bits = bits + 1; /* increment urefs */
			is_write_unlock(space);

			ipc_notify_dead_name(notify, name);
			previous = IP_NULL;
			break;
		}

		is_write_unlock(space);
		if (bits & MACH_PORT_TYPE_PORT_OR_DEAD)
			return KERN_INVALID_ARGUMENT;
		else
			return KERN_INVALID_RIGHT;
	}

	*previousp = previous;
	return KERN_SUCCESS;
}