bool AppleSmartBatteryManagerUserClient::initWithTask(task_t owningTask, void *security_id, UInt32 type, OSDictionary * properties) { uint32_t _pid; /* 1. Only root processes may open a SmartBatteryManagerUserClient. * 2. Attempts to create exclusive UserClients will fail if an * exclusive user client is attached. * 3. Non-exclusive clients will not be able to perform transactions * while an exclusive client is attached. * 3a. Only battery firmware updaters should bother being exclusive. */ if ( kIOReturnSuccess != clientHasPrivilege(owningTask, kIOClientPrivilegeAdministrator)) { return false; } if (!super::initWithTask(owningTask, security_id, type, properties)) { return false; } fUserClientType = type; _pid = proc_selfpid(); setProperty("pid", _pid, 32); fOwningTask = owningTask; task_reference (fOwningTask); return true; }
//============================================================================== // IOHIDEventServiceUserClient::initWithTask //============================================================================== bool IOHIDEventServiceUserClient::initWithTask(task_t owningTask, void * security_id, UInt32 type) { if (!super::init()) return false; _client = owningTask; task_reference (_client); return true; }
bool RootDomainUserClient::initWithTask(task_t owningTask, void *security_id, UInt32 type, OSDictionary * properties) { if (properties) properties->setObject(kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue); if (!super::initWithTask(owningTask, security_id, type, properties)) return false; fOwningTask = owningTask; task_reference (fOwningTask); return true; }
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ bool IOHIDStackShotUserClient:: initWithTask(task_t owningTask, void * /* security_id */, UInt32 /* type */) { if (!super::init() || (IOUserClient::clientHasPrivilege(owningTask, kIOClientPrivilegeAdministrator) != kIOReturnSuccess)) return false; client = owningTask; task_reference (client); return true; }
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ bool IOHIDStackShotUserClient:: initWithTask(task_t owningTask, void * /* security_id */, UInt32 /* type */) { if (!super::init()) return false; IOReturn priv = IOUserClient::clientHasPrivilege(owningTask, kIOClientPrivilegeAdministrator); if (priv != kIOReturnSuccess) { IOLog("%s call failed %08x\n", __PRETTY_FUNCTION__, priv); return false; } client = owningTask; task_reference (client); return true; }
//============================================================================== // IOHIDEventServiceUserClient::initWithTask //============================================================================== bool IOHIDEventServiceUserClient::initWithTask(task_t owningTask, void * security_id, UInt32 type) { if (!super::init()) return false; _client = owningTask; task_reference (_client); _queue = IOHIDEventServiceQueue::withCapacity(1024); if ( !_queue ) return false; return true; }
bool IOHIDEventSystemUserClient:: initWithTask(task_t owningTask, void * /* security_id */, UInt32 /* type */) { if ( !super::init() ) { return false; } IOReturn priv = IOUserClient::clientHasPrivilege(owningTask, kIOClientPrivilegeAdministrator); if (priv != kIOReturnSuccess) { IOLog("%s: Client task not privileged to open IOHIDSystem for mapping memory (%08x)\n", __PRETTY_FUNCTION__, priv); return false; } client = owningTask; task_reference (client); return true; }
bool IOHIDLibUserClient::initWithTask(task_t owningTask, void * /* security_id */, UInt32 /* type */) { if (!super::init()) return false; if (IOUserClient::clientHasPrivilege(owningTask, kIOClientPrivilegeAdministrator) != kIOReturnSuccess) { // Preparing for extended data. Set a temporary key. setProperty(kIOHIDLibClientExtendedData, true); } fClient = owningTask; task_reference (fClient); proc_t p = (proc_t)get_bsdtask_info(fClient); fPid = proc_pid(p); fQueueMap = OSArray::withCapacity(4); if (!fQueueMap) return false; return true; }
boolean_t ipc_port_importance_delta( ipc_port_t port, mach_port_delta_t delta) { ipc_port_t next, base; task_t task = TASK_NULL; boolean_t dropped = FALSE; if (delta == 0) return FALSE; base = port; /* if port is in transit, have to search for end of chain */ if (ip_active(port) && port->ip_destination != IP_NULL && port->ip_receiver_name == MACH_PORT_NULL) { dropped = TRUE; ip_unlock(port); ipc_port_multiple_lock(); /* massive serialization */ ip_lock(base); while(ip_active(base) && base->ip_destination != IP_NULL && base->ip_receiver_name == MACH_PORT_NULL) { base = base->ip_destination; ip_lock(base); } ipc_port_multiple_unlock(); } /* unlock down to the base, adding a boost at each level */ for (;;) { port->ip_impcount += delta; if (port == base) break; /* port is in transit */ assert(port->ip_tempowner == 0); next = port->ip_destination; ip_unlock(port); port = next; } /* find the task (if any) to boost according to the base */ if (ip_active(base)) { if (base->ip_tempowner != 0) { if (base->ip_taskptr != 0) task = base->ip_imp_task; /* otherwise don't boost */ } else if (base->ip_receiver_name != MACH_PORT_NULL) { ipc_space_t space = base->ip_receiver; /* only spaces with boost-accepting tasks */ if (space->is_task != TASK_NULL && space->is_task->imp_receiver != 0) task = space->is_task; } } /* * Only the base is locked. If we have to hold or drop task * importance assertions, we'll have to drop that lock as well. */ if (task != TASK_NULL) { /* take a reference before unlocking base */ assert(task->imp_receiver != 0); task_reference(task); ip_unlock(base); dropped = TRUE; if (delta > 0) task_importance_hold_internal_assertion(task, delta); else task_importance_drop_internal_assertion(task, -delta); task_deallocate(task); } else if (dropped == TRUE) { ip_unlock(base); } return dropped; }
boolean_t ipc_port_check_circularity( ipc_port_t port, ipc_port_t dest) { ipc_port_t base; #if IMPORTANCE_INHERITANCE task_t task = TASK_NULL; task_t release_task = TASK_NULL; int assertcnt = 0; #endif /* IMPORTANCE_INHERITANCE */ assert(port != IP_NULL); assert(dest != IP_NULL); if (port == dest) return TRUE; base = dest; /* * First try a quick check that can run in parallel. * No circularity if dest is not in transit. */ ip_lock(port); if (ip_lock_try(dest)) { if (!ip_active(dest) || (dest->ip_receiver_name != MACH_PORT_NULL) || (dest->ip_destination == IP_NULL)) goto not_circular; /* dest is in transit; further checking necessary */ ip_unlock(dest); } ip_unlock(port); ipc_port_multiple_lock(); /* massive serialization */ /* * Search for the end of the chain (a port not in transit), * acquiring locks along the way. */ for (;;) { ip_lock(base); if (!ip_active(base) || (base->ip_receiver_name != MACH_PORT_NULL) || (base->ip_destination == IP_NULL)) break; base = base->ip_destination; } /* all ports in chain from dest to base, inclusive, are locked */ if (port == base) { /* circularity detected! */ ipc_port_multiple_unlock(); /* port (== base) is in limbo */ assert(ip_active(port)); assert(port->ip_receiver_name == MACH_PORT_NULL); assert(port->ip_destination == IP_NULL); while (dest != IP_NULL) { ipc_port_t next; /* dest is in transit or in limbo */ assert(ip_active(dest)); assert(dest->ip_receiver_name == MACH_PORT_NULL); next = dest->ip_destination; ip_unlock(dest); dest = next; } return TRUE; } /* * The guarantee: lock port while the entire chain is locked. * Once port is locked, we can take a reference to dest, * add port to the chain, and unlock everything. */ ip_lock(port); ipc_port_multiple_unlock(); not_circular: /* port is in limbo */ assert(ip_active(port)); assert(port->ip_receiver_name == MACH_PORT_NULL); assert(port->ip_destination == IP_NULL); ip_reference(dest); port->ip_destination = dest; #if IMPORTANCE_INHERITANCE /* must have been in limbo or still bound to a task */ assert(port->ip_tempowner != 0); if (port->ip_taskptr != 0) { /* * We delayed dropping assertions from a specific task. * Cache that info now (we'll drop assertions and the * task reference below). */ release_task = port->ip_imp_task; port->ip_imp_task = TASK_NULL; port->ip_taskptr = 0; } assertcnt = port->ip_impcount; /* take the port out of limbo w.r.t. assertions */ port->ip_tempowner = 0; #endif /* IMPORTANCE_INHERITANCE */ /* now unlock chain */ ip_unlock(port); for (;;) { #if IMPORTANCE_INHERITANCE /* every port along chain track assertions behind it */ dest->ip_impcount += assertcnt; #endif /* IMPORTANCE_INHERITANCE */ if (dest == base) break; /* port is in transit */ assert(ip_active(dest)); assert(dest->ip_receiver_name == MACH_PORT_NULL); assert(dest->ip_destination != IP_NULL); #if IMPORTANCE_INHERITANCE assert(dest->ip_tempowner == 0); #endif /* IMPORTANCE_INHERITANCE */ port = dest->ip_destination; ip_unlock(dest); dest = port; } /* base is not in transit */ assert(!ip_active(base) || (base->ip_receiver_name != MACH_PORT_NULL) || (base->ip_destination == IP_NULL)); #if IMPORTANCE_INHERITANCE /* * Find the task to boost (if any). * We will boost "through" ports that don't know * about inheritance to deliver receive rights that * do. */ if (ip_active(base) && (assertcnt > 0)) { if (base->ip_tempowner != 0) { if (base->ip_taskptr != 0) /* specified tempowner task */ task = base->ip_imp_task; /* otherwise don't boost current task */ } else if (base->ip_receiver_name != MACH_PORT_NULL) { ipc_space_t space = base->ip_receiver; /* only spaces with boost-accepting tasks */ if (space->is_task != TASK_NULL && space->is_task->imp_receiver != 0) task = space->is_task; } /* take reference before unlocking base */ if (task != TASK_NULL) { assert(task->imp_receiver != 0); task_reference(task); } } #endif /* IMPORTANCE_INHERITANCE */ ip_unlock(base); #if IMPORTANCE_INHERITANCE /* * Transfer assertions now that the ports are unlocked. * Avoid extra overhead if transferring to/from the same task. */ boolean_t transfer_assertions = (task != release_task) ? TRUE : FALSE; if (task != TASK_NULL) { if (transfer_assertions) task_importance_hold_internal_assertion(task, assertcnt); task_deallocate(task); task = TASK_NULL; } if (release_task != TASK_NULL) { if (transfer_assertions) task_importance_drop_internal_assertion(release_task, assertcnt); task_deallocate(release_task); release_task = TASK_NULL; } #endif /* IMPORTANCE_INHERITANCE */ return FALSE; }
kern_return_t task_name_for_pid( struct task_name_for_pid_args *args) { mach_port_name_t target_tport = args->target_tport; int pid = args->pid; user_addr_t task_addr = args->t; proc_t p = PROC_NULL; task_t t1; mach_port_name_t tret; void * sright; int error = 0, refheld = 0; kauth_cred_t target_cred; AUDIT_MACH_SYSCALL_ENTER(AUE_TASKNAMEFORPID); AUDIT_ARG(pid, pid); AUDIT_ARG(mach_port1, target_tport); t1 = port_name_to_task(target_tport); if (t1 == TASK_NULL) { (void) copyout((char *)&t1, task_addr, sizeof(mach_port_name_t)); AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE); return(KERN_FAILURE); } p = proc_find(pid); if (p != PROC_NULL) { AUDIT_ARG(process, p); target_cred = kauth_cred_proc_ref(p); refheld = 1; if ((p->p_stat != SZOMB) && ((current_proc() == p) || kauth_cred_issuser(kauth_cred_get()) || ((kauth_cred_getuid(target_cred) == kauth_cred_getuid(kauth_cred_get())) && ((kauth_cred_getruid(target_cred) == kauth_getruid()))))) { if (p->task != TASK_NULL) { task_reference(p->task); #if CONFIG_MACF error = mac_proc_check_get_task_name(kauth_cred_get(), p); if (error) { task_deallocate(p->task); goto noperm; } #endif sright = (void *)convert_task_name_to_port(p->task); tret = ipc_port_copyout_send(sright, get_task_ipcspace(current_task())); } else tret = MACH_PORT_NULL; AUDIT_ARG(mach_port2, tret); (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t)); task_deallocate(t1); error = KERN_SUCCESS; goto tnfpout; } } #if CONFIG_MACF noperm: #endif task_deallocate(t1); tret = MACH_PORT_NULL; (void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t)); error = KERN_FAILURE; tnfpout: if (refheld != 0) kauth_cred_unref(&target_cred); if (p != PROC_NULL) proc_rele(p); AUDIT_MACH_SYSCALL_EXIT(error); return(error); }
/* * Routine: task_for_pid * Purpose: * Get the task port for another "process", named by its * process ID on the same host as "target_task". * * Only permitted to privileged processes, or processes * with the same user ID. * * Note: if pid == 0, an error is return no matter who is calling. * * XXX This should be a BSD system call, not a Mach trap!!! */ kern_return_t task_for_pid( struct task_for_pid_args *args) { mach_port_name_t target_tport = args->target_tport; int pid = args->pid; user_addr_t task_addr = args->t; proc_t p = PROC_NULL; task_t t1 = TASK_NULL; mach_port_name_t tret = MACH_PORT_NULL; ipc_port_t tfpport; void * sright; int error = 0; AUDIT_MACH_SYSCALL_ENTER(AUE_TASKFORPID); AUDIT_ARG(pid, pid); AUDIT_ARG(mach_port1, target_tport); /* Always check if pid == 0 */ if (pid == 0) { (void ) copyout((char *)&t1, task_addr, sizeof(mach_port_name_t)); AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE); return(KERN_FAILURE); } t1 = port_name_to_task(target_tport); if (t1 == TASK_NULL) { (void) copyout((char *)&t1, task_addr, sizeof(mach_port_name_t)); AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE); return(KERN_FAILURE); } p = proc_find(pid); if (p == PROC_NULL) { error = KERN_FAILURE; goto tfpout; } #if CONFIG_AUDIT AUDIT_ARG(process, p); #endif if (!(task_for_pid_posix_check(p))) { error = KERN_FAILURE; goto tfpout; } if (p->task != TASK_NULL) { /* If we aren't root and target's task access port is set... */ if (!kauth_cred_issuser(kauth_cred_get()) && p != current_proc() && (task_get_task_access_port(p->task, &tfpport) == 0) && (tfpport != IPC_PORT_NULL)) { if (tfpport == IPC_PORT_DEAD) { error = KERN_PROTECTION_FAILURE; goto tfpout; } /* Call up to the task access server */ error = check_task_access(tfpport, proc_selfpid(), kauth_getgid(), pid); if (error != MACH_MSG_SUCCESS) { if (error == MACH_RCV_INTERRUPTED) error = KERN_ABORTED; else error = KERN_FAILURE; goto tfpout; } } #if CONFIG_MACF error = mac_proc_check_get_task(kauth_cred_get(), p); if (error) { error = KERN_FAILURE; goto tfpout; } #endif /* Grant task port access */ task_reference(p->task); extmod_statistics_incr_task_for_pid(p->task); sright = (void *) convert_task_to_port(p->task); tret = ipc_port_copyout_send( sright, get_task_ipcspace(current_task())); } error = KERN_SUCCESS; tfpout: task_deallocate(t1); AUDIT_ARG(mach_port2, tret); (void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t)); if (p != PROC_NULL) proc_rele(p); AUDIT_MACH_SYSCALL_EXIT(error); return(error); }
/* * Routine: task_for_pid * Purpose: * Get the task port for another "process", named by its * process ID on the same host as "target_task". * * Only permitted to privileged processes, or processes * with the same user ID. * * XXX This should be a BSD system call, not a Mach trap!!! */ kern_return_t task_for_pid( struct task_for_pid_args *args) { mach_port_name_t target_tport = args->target_tport; int pid = args->pid; user_addr_t task_addr = args->t; struct uthread *uthread; proc_t p = PROC_NULL; task_t t1 = TASK_NULL; mach_port_name_t tret = MACH_PORT_NULL; ipc_port_t tfpport; void * sright; int error = 0; AUDIT_MACH_SYSCALL_ENTER(AUE_TASKFORPID); AUDIT_ARG(pid, pid); AUDIT_ARG(mach_port1, target_tport); #if defined(SECURE_KERNEL) if (0 == pid) { (void ) copyout((char *)&t1, task_addr, sizeof(mach_port_name_t)); AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE); return(KERN_FAILURE); } #endif t1 = port_name_to_task(target_tport); if (t1 == TASK_NULL) { (void) copyout((char *)&t1, task_addr, sizeof(mach_port_name_t)); AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE); return(KERN_FAILURE); } /* * Delayed binding of thread credential to process credential, if we * are not running with an explicitly set thread credential. */ uthread = get_bsdthread_info(current_thread()); kauth_cred_uthread_update(uthread, current_proc()); p = proc_find(pid); AUDIT_ARG(process, p); if (!(task_for_pid_posix_check(p))) { error = KERN_FAILURE; goto tfpout; } if (p->task != TASK_NULL) { /* If we aren't root and target's task access port is set... */ if (!kauth_cred_issuser(kauth_cred_get()) && p != current_proc() && (task_get_task_access_port(p->task, &tfpport) == 0) && (tfpport != IPC_PORT_NULL)) { if (tfpport == IPC_PORT_DEAD) { error = KERN_PROTECTION_FAILURE; goto tfpout; } /* Call up to the task access server */ error = check_task_access(tfpport, proc_selfpid(), kauth_getgid(), pid); if (error != MACH_MSG_SUCCESS) { if (error == MACH_RCV_INTERRUPTED) error = KERN_ABORTED; else error = KERN_FAILURE; goto tfpout; } } #if CONFIG_MACF error = mac_proc_check_get_task(kauth_cred_get(), p); if (error) { error = KERN_FAILURE; goto tfpout; } #endif /* Grant task port access */ task_reference(p->task); sright = (void *) convert_task_to_port(p->task); tret = ipc_port_copyout_send( sright, get_task_ipcspace(current_task())); } error = KERN_SUCCESS; tfpout: task_deallocate(t1); AUDIT_ARG(mach_port2, tret); (void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t)); if (p != PROC_NULL) proc_rele(p); AUDIT_MACH_SYSCALL_EXIT(error); return(error); }
bool com_VFSFilter0::start( __in IOService *provider ) { //__asm__ volatile( "int $0x3" ); VNodeMap::Init(); if( kIOReturnSuccess != VFSHookInit() ){ DBG_PRINT_ERROR( ( "VFSHookInit() failed\n" ) ); goto __exit_on_error; } if( ! QvrVnodeHooksHashTable::CreateStaticTableWithSize( 8, true ) ){ DBG_PRINT_ERROR( ( "QvrVnodeHooksHashTable::CreateStaticTableWithSize() failed\n" ) ); goto __exit_on_error; } // // gSuperUserContext must have a valid thread and process pointer // TO DO redesign this! Indefinit holding a thread or task object is a bad behaviour. // thread_reference( current_thread() ); task_reference( current_task() ); gSuperUserContext = vfs_context_create(NULL); // vfs_context_kernel() // // create an object for the vnodes KAuth callback and register the callback, // the callback might be called immediatelly just after registration! // gVnodeGate = QvrIOKitKAuthVnodeGate::withCallbackRegistration( this ); assert( NULL != gVnodeGate ); if( NULL == gVnodeGate ){ DBG_PRINT_ERROR( ( "QvrIOKitKAuthVnodeGate::withDefaultSettings() failed\n" ) ); goto __exit_on_error; } Instance = this; // // register with IOKit to allow the class matching // registerService(); return true; __exit_on_error: // // all cleanup will be done in stop() and free() // this->release(); return false; }