/*
- * Copyright (c) 1998-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 1998-2012 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <IOKit/IOLib.h>
#include <IOKit/IOStatisticsPrivate.h>
#include <IOKit/IOTimeStamp.h>
+#include <IOKit/system.h>
#include <libkern/OSDebug.h>
#include <sys/proc.h>
#include <sys/kauth.h>
#define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
#define SCALAR32(x) ((uint32_t )x)
-#define ARG32(x) ((void *)SCALAR32(x))
+#define ARG32(x) ((void *)(uintptr_t)SCALAR32(x))
#define REF64(x) ((io_user_reference_t)((UInt64)(x)))
#define REF32(x) ((int)(x))
void * reference, vm_size_t referenceSize,
bool clientIs64 )
{
+ if( !super::init())
+ return( false );
+
newSet = OSArray::withCapacity( 1 );
if( !newSet)
return( false );
pingMsg->notifyHeader.type = type;
bcopy( reference, pingMsg->notifyHeader.reference, referenceSize );
- return( super::init() );
+ return( true );
}
void IOServiceUserNotification::free( void )
super::free();
- if( _pingMsg && _msgSize)
- IOFree( _pingMsg, _msgSize);
+ if( _pingMsg && _msgSize) {
+ if (_pingMsg->msgHdr.msgh_remote_port) {
+ iokit_release_port_send(_pingMsg->msgHdr.msgh_remote_port);
+ }
+ IOFree(_pingMsg, _msgSize);
+ }
if( _lastEntry)
_lastEntry->release();
else
pingMsg->msgHdr.msgh_local_port = NULL;
- kr = mach_msg_send_from_kernel_proper( &pingMsg->msgHdr,
- pingMsg->msgHdr.msgh_size);
+ kr = mach_msg_send_from_kernel_with_options( &pingMsg->msgHdr,
+ pingMsg->msgHdr.msgh_size,
+ (MACH_SEND_MSG | MACH_SEND_ALWAYS | MACH_SEND_IMPORTANCE),
+ 0);
if( port)
iokit_release_port( port );
void * reference, vm_size_t referenceSize, vm_size_t extraSize,
bool client64 )
{
+ if( !super::init())
+ return( false );
if (referenceSize > sizeof(OSAsyncReference64))
return( false );
pingMsg->notifyHeader.type = type;
bcopy( reference, pingMsg->notifyHeader.reference, referenceSize );
- return( super::init() );
+ return( true );
}
void IOServiceMessageUserNotification::free( void )
super::free();
- if( _pingMsg && _msgSize)
+ if( _pingMsg && _msgSize) {
+ if (_pingMsg->msgHdr.msgh_remote_port) {
+ iokit_release_port_send(_pingMsg->msgHdr.msgh_remote_port);
+ }
IOFree( _pingMsg, _msgSize);
+ }
}
IOReturn IOServiceMessageUserNotification::_handler( void * target, void * ref,
if (kIOMessageCopyClientID == messageType)
{
- *((void **) messageArgument) = IOCopyLogNameForPID(owningPID);
- return (kIOReturnSuccess);
+ *((void **) messageArgument) = OSNumber::withNumber(owningPID, 32);
+ return (kIOReturnSuccess);
}
data->messageType = messageType;
pingMsg->ports[0].name = providerPort;
thisPort = iokit_port_for_object( this, IKOT_IOKIT_OBJECT );
pingMsg->msgHdr.msgh_local_port = thisPort;
- kr = mach_msg_send_from_kernel_proper( &pingMsg->msgHdr,
- pingMsg->msgHdr.msgh_size);
+ kr = mach_msg_send_from_kernel_with_options( &pingMsg->msgHdr,
+ pingMsg->msgHdr.msgh_size,
+ (MACH_SEND_MSG | MACH_SEND_ALWAYS | MACH_SEND_IMPORTANCE),
+ 0);
if( thisPort)
iokit_release_port( thisPort );
if( providerPort)
asyncRef[kIOAsyncCalloutRefconIndex] = refcon;
}
+void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef,
+ mach_port_t wakePort,
+ mach_vm_address_t callback, io_user_reference_t refcon, task_t task)
+{
+ setAsyncReference64(asyncRef, wakePort, callback, refcon);
+ if (vm_map_is_64bit(get_task_map(task))) {
+ asyncRef[kIOAsyncReservedIndex] |= kIOUCAsync64Flag;
+ }
+}
+
static OSDictionary * CopyConsoleUser(UInt32 uid)
{
OSArray * array;
sizeof(kIOClientPrivilegeForeground)))
{
/* is graphics access denied for current task? */
- if (proc_get_task_selfgpuacc_deny() != 0)
+ if (proc_get_effective_task_policy(current_task(), TASK_POLICY_GPU_DENY) != 0)
return (kIOReturnNotPrivileged);
else
return (kIOReturnSuccess);
bool IOUserClient::reserve()
{
- if(!reserved) {
- reserved = IONew(ExpansionData, 1);
- if (!reserved) {
- return false;
- }
+ if(!reserved) {
+ reserved = IONew(ExpansionData, 1);
+ if (!reserved) {
+ return false;
}
-
- IOStatisticsRegisterCounter();
-
- return true;
+ }
+ setTerminateDefer(NULL, true);
+ IOStatisticsRegisterCounter();
+
+ return true;
}
void IOUserClient::free()
mach_port_name_t name;
name = IOMachPort::makeSendRightForTask( task, obj, IKOT_IOKIT_OBJECT );
- assert( name );
*(mach_port_name_t *)clientObj = name;
return kIOReturnSuccess;
return (sendAsyncResult64(reference64, result, args64, numArgs));
}
+IOReturn IOUserClient::sendAsyncResult64WithOptions(OSAsyncReference64 reference,
+ IOReturn result, io_user_reference_t args[], UInt32 numArgs, IOOptionBits options)
+{
+ return _sendAsyncResult64(reference, result, args, numArgs, options);
+}
+
IOReturn IOUserClient::sendAsyncResult64(OSAsyncReference64 reference,
IOReturn result, io_user_reference_t args[], UInt32 numArgs)
+{
+ return _sendAsyncResult64(reference, result, args, numArgs, 0);
+}
+
+IOReturn IOUserClient::_sendAsyncResult64(OSAsyncReference64 reference,
+ IOReturn result, io_user_reference_t args[], UInt32 numArgs, IOOptionBits options)
{
struct ReplyMsg
{
replyMsg.m.msg32.args[idx] = REF32(args[idx]);
}
- kr = mach_msg_send_from_kernel_proper( &replyMsg.msgHdr,
- replyMsg.msgHdr.msgh_size);
- if( KERN_SUCCESS != kr)
+ if ((options & kIOUserNotifyOptionCanDrop) != 0) {
+ kr = mach_msg_send_from_kernel_with_options( &replyMsg.msgHdr,
+ replyMsg.msgHdr.msgh_size, MACH_SEND_TIMEOUT, MACH_MSG_TIMEOUT_NONE);
+ } else {
+ /* Fail on full queue. */
+ kr = mach_msg_send_from_kernel_proper( &replyMsg.msgHdr,
+ replyMsg.msgHdr.msgh_size);
+ }
+ if ((KERN_SUCCESS != kr) && (MACH_SEND_TIMED_OUT != kr))
IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__, kr );
return kr;
}
return( kr );
}
+
+/* Routine io_service_get_matching_service */
+kern_return_t is_io_service_get_matching_service(
+ mach_port_t master_port,
+ io_string_t matching,
+ io_service_t *service )
+{
+ kern_return_t kr;
+ OSObject * obj;
+ OSDictionary * dict;
+
+ if( master_port != master_device_port)
+ return( kIOReturnNotPrivileged);
+
+ obj = OSUnserializeXML( matching );
+
+ if( (dict = OSDynamicCast( OSDictionary, obj))) {
+ *service = IOService::copyMatchingService( dict );
+ kr = *service ? kIOReturnSuccess : kIOReturnNotFound;
+ } else
+ kr = kIOReturnBadArgument;
+
+ if( obj)
+ obj->release();
+
+ return( kr );
+}
+
+/* Routine io_service_get_matching_services_ool */
+kern_return_t is_io_service_get_matching_service_ool(
+ mach_port_t master_port,
+ io_buf_ptr_t matching,
+ mach_msg_type_number_t matchingCnt,
+ kern_return_t *result,
+ io_object_t *service )
+{
+ kern_return_t kr;
+ vm_offset_t data;
+ vm_map_offset_t map_data;
+
+ kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
+ data = CAST_DOWN(vm_offset_t, map_data);
+
+ if( KERN_SUCCESS == kr) {
+ // must return success after vm_map_copyout() succeeds
+ *result = is_io_service_get_matching_service( master_port,
+ (char *) data, service );
+ vm_deallocate( kernel_map, data, matchingCnt );
+ }
+
+ return( kr );
+}
+
+
static kern_return_t internal_io_service_add_notification(
mach_port_t master_port,
io_name_t notification_type,
if( userNotify && !userNotify->init( port, userMsgType,
reference, referenceSize, client64)) {
+ iokit_release_port_send(port);
userNotify->release();
userNotify = 0;
}
reference, referenceSize,
kIOUserNotifyMaxMessageSize,
client64 )) {
+ iokit_release_port_send(port);
userNotify->release();
userNotify = 0;
}
{
CHECK( IOService, _service, service );
- return( service->acknowledgeNotification( (IONotificationRef) notify_ref,
+ return( service->acknowledgeNotification( (IONotificationRef)(uintptr_t) notify_ref,
(IOOptionBits) response ));
}
CHECK( IORegistryEntry, registry_entry, entry );
+ if( propertiesCnt > sizeof(io_struct_inband_t) * 1024)
+ return( kIOReturnMessageTooLarge);
+
err = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) properties );
data = CAST_DOWN(vm_offset_t, map_data);
if( KERN_SUCCESS == err) {
// must return success after vm_map_copyout() succeeds
- obj = OSUnserializeXML( (const char *) data );
+ obj = OSUnserializeXML( (const char *) data, propertiesCnt );
vm_deallocate( kernel_map, data, propertiesCnt );
if (!obj)
vm_offset_t data;
vm_map_offset_t map_data;
+ if( propertiesCnt > sizeof(io_struct_inband_t))
+ return( kIOReturnMessageTooLarge);
+
err = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) properties );
res = err;
data = CAST_DOWN(vm_offset_t, map_data);
if (KERN_SUCCESS == err)
{
// must return success after vm_map_copyout() succeeds
- obj = OSUnserializeXML( (const char *) data );
+ obj = OSUnserializeXML( (const char *) data, propertiesCnt );
vm_deallocate( kernel_map, data, propertiesCnt );
propertiesDict = OSDynamicCast(OSDictionary, obj);
if (!propertiesDict)
client->setProperty(kIOUserClientCreatorKey, creatorName);
creatorName->release();
}
+ client->setTerminateDefer(service, false);
}
}
while (false);
mach_port_name_t name __unused =
IOMachPort::makeSendRightForTask(
into_task, map, IKOT_IOKIT_OBJECT );
- assert( name );
} else {
// keep it with the user client
case 4:
err = (object->*func)( ARG32(input[0]), ARG32(input[1]), (void *) input[2],
ARG32(input[3]),
- inputStruct, (void *)inputStructCount );
+ inputStruct, (void *)(uintptr_t)inputStructCount );
break;
case 3:
err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
- inputStruct, (void *)inputStructCount,
+ inputStruct, (void *)(uintptr_t)inputStructCount,
0 );
break;
case 2:
err = (object->*func)( ARG32(input[0]), ARG32(input[1]),
- inputStruct, (void *)inputStructCount,
+ inputStruct, (void *)(uintptr_t)inputStructCount,
0, 0 );
break;
case 1:
err = (object->*func)( ARG32(input[0]),
- inputStruct, (void *)inputStructCount,
+ inputStruct, (void *)(uintptr_t)inputStructCount,
0, 0, 0 );
break;
case 0:
- err = (object->*func)( inputStruct, (void *)inputStructCount,
+ err = (object->*func)( inputStruct, (void *)(uintptr_t)inputStructCount,
0, 0, 0, 0 );
break;
err = (object->*func)( reference,
ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
ARG32(input[3]),
- inputStruct, (void *)inputStructCount );
+ inputStruct, (void *)(uintptr_t)inputStructCount );
break;
case 3:
err = (object->*func)( reference,
ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
- inputStruct, (void *)inputStructCount,
+ inputStruct, (void *)(uintptr_t)inputStructCount,
0 );
break;
case 2:
err = (object->*func)( reference,
ARG32(input[0]), ARG32(input[1]),
- inputStruct, (void *)inputStructCount,
+ inputStruct, (void *)(uintptr_t)inputStructCount,
0, 0 );
break;
case 1:
err = (object->*func)( reference,
ARG32(input[0]),
- inputStruct, (void *)inputStructCount,
+ inputStruct, (void *)(uintptr_t)inputStructCount,
0, 0, 0 );
break;
case 0:
err = (object->*func)( reference,
- inputStruct, (void *)inputStructCount,
+ inputStruct, (void *)(uintptr_t)inputStructCount,
0, 0, 0, 0 );
break;
if( method->count1) {
if( method->count0) {
err = (object->*func)( input, output,
- (void *)inputCount, outputCount, 0, 0 );
+ (void *)(uintptr_t)inputCount, outputCount, 0, 0 );
} else {
err = (object->*func)( output, outputCount, 0, 0, 0, 0 );
}
} else {
- err = (object->*func)( input, (void *)inputCount, 0, 0, 0, 0 );
+ err = (object->*func)( input, (void *)(uintptr_t)inputCount, 0, 0, 0, 0 );
}
}
while( false);
if( method->count0) {
err = (object->*func)( reference,
input, output,
- (void *)inputCount, outputCount, 0, 0 );
+ (void *)(uintptr_t)inputCount, outputCount, 0, 0 );
} else {
err = (object->*func)( reference,
output, outputCount, 0, 0, 0, 0 );
}
} else {
err = (object->*func)( reference,
- input, (void *)inputCount, 0, 0, 0, 0 );
- }
- }
- while( false);
-
- return( err);
-}
-
-/* Routine io_make_matching */
-kern_return_t is_io_make_matching(
- mach_port_t master_port,
- uint32_t type,
- uint32_t options,
- io_struct_inband_t input,
- mach_msg_type_number_t inputCount,
- io_string_t matching )
-{
- OSSerialize * s;
- IOReturn err = kIOReturnSuccess;
- OSDictionary * dict;
-
- if( master_port != master_device_port)
- return( kIOReturnNotPrivileged);
-
- switch( type) {
-
- case kIOServiceMatching:
- dict = IOService::serviceMatching( gIOServiceKey );
- break;
-
- case kIOBSDNameMatching:
- dict = IOBSDNameMatching( (const char *) input );
- break;
-
- case kIOOFPathMatching:
- dict = IOOFPathMatching( (const char *) input,
- matching, sizeof( io_string_t));
- break;
-
- default:
- dict = 0;
- }
-
- if( !dict)
- return( kIOReturnUnsupported);
-
- do {
- s = OSSerialize::withCapacity(4096);
- if( !s) {
- err = kIOReturnNoMemory;
- continue;
- }
- s->clearText();
- if( !dict->serialize( s )) {
- err = kIOReturnUnsupported;
- continue;
+ input, (void *)(uintptr_t)inputCount, 0, 0, 0, 0 );
}
-
- if( s->getLength() > sizeof( io_string_t)) {
- err = kIOReturnNoMemory;
- continue;
- } else
- strlcpy(matching, s->text(), sizeof(io_string_t));
}
while( false);
- if( s)
- s->release();
- if( dict)
- dict->release();
-
return( err);
}
if (inData) {
vm_map_offset_t map_data;
+ if( inDataCount > sizeof(io_struct_inband_t) * 1024)
+ return( kIOReturnMessageTooLarge);
+
kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t)inData);
data = CAST_DOWN(vm_offset_t, map_data);
// must return success after vm_map_copyout() succeeds
if( inDataCount ) {
- obj = (OSObject *)OSUnserializeXML((const char *)data);
+ obj = (OSObject *)OSUnserializeXML((const char *)data, inDataCount);
vm_deallocate( kernel_map, data, inDataCount );
if( !obj) {
*result = kIOReturnNoMemory;
array = OSDynamicCast(OSArray, obj);
if (array) {
- if ( !gIOCatalogue->resetAndAddDrivers(array,
+ if ( !gIOCatalogue->resetAndAddDrivers(array,
flag == kIOCatalogResetDrivers) ) {
kr = kIOReturnError;
if (kIOUCForegroundOnly & method->flags)
{
/* is graphics access denied for current task? */
- if (proc_get_task_selfgpuacc_deny() != 0)
+ if (proc_get_effective_task_policy(current_task(), TASK_POLICY_GPU_DENY) != 0)
return (kIOReturnNotPermitted);
}
if (kIOUCForegroundOnly & method->flags)
{
/* is graphics access denied for current task? */
- if (proc_get_task_selfgpuacc_deny() != 0)
+ if (proc_get_effective_task_policy(current_task(), TASK_POLICY_GPU_DENY) != 0)
return (kIOReturnNotPermitted);
}