+
+ /*
+ * 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);
+}
+
+/*
+ * Routine: task_name_for_pid
+ * Purpose:
+ * Get the task name 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_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;
+ struct uthread *uthread;
+ 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);
+ }
+
+
+ /*
+ * 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 (p != PROC_NULL) {
+ 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())) &&
+ ((target_cred->cr_ruid == kauth_cred_get()->cr_ruid))))) {
+