Skip to content

Commit

Permalink
xnu-2050.24.15
Browse files Browse the repository at this point in the history
  • Loading branch information
Darwin authored and das committed Jun 4, 2017
1 parent 74d6983 commit 2b43307
Show file tree
Hide file tree
Showing 56 changed files with 1,074 additions and 266 deletions.
24 changes: 21 additions & 3 deletions bsd/hfs/hfs_vnops.c
Original file line number Diff line number Diff line change
Expand Up @@ -5630,11 +5630,29 @@ hfs_vgetrsrc(struct hfsmount *hfsmp, struct vnode *vp, struct vnode **rvpp,
* do a lookup on /tmp/b, you'd acquire an entirely different record's resource
* fork.
*
* As a result, we use the fileid, which should be invariant for the lifetime
* of the cnode (possibly barring calls to exchangedata).
* As a result, we use the fileid, which should be invariant for the lifetime
* of the cnode (possibly barring calls to exchangedata).
*
* Addendum: We can't do the above for HFS standard since we aren't guaranteed to
* have thread records for files. They were only required for directories. So
* we need to do the lookup with the catalog name. This is OK since hardlinks were
* never allowed on HFS standard.
*/

error = cat_idlookup (hfsmp, cp->c_attr.ca_fileid, 0, 1, NULL, NULL, &rsrcfork);
if (hfsmp->hfs_flags & HFS_STANDARD) {
/*
* HFS standard only:
*
* Get the resource fork for this item via catalog lookup
* since HFS standard was case-insensitive only. We don't want the
* descriptor; just the fork data here.
*/
error = cat_lookup (hfsmp, descptr, 1, (struct cat_desc*)NULL,
(struct cat_attr*)NULL, &rsrcfork, NULL);
}
else {
error = cat_idlookup (hfsmp, cp->c_fileid, 0, 1, NULL, NULL, &rsrcfork);
}

hfs_systemfile_unlock(hfsmp, lockflags);
if (error) {
Expand Down
18 changes: 18 additions & 0 deletions bsd/kern/kern_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,24 @@ filt_proc(struct knote *kn, long hint)
*/
event = (u_int)hint & NOTE_PCTRLMASK;

/*
* termination lifecycle events can happen while a debugger
* has reparented a process, in which case notifications
* should be quashed except to the tracing parent. When
* the debugger reaps the child (either via wait4(2) or
* process exit), the child will be reparented to the original
* parent and these knotes re-fired.
*/
if (event & NOTE_EXIT) {
if ((kn->kn_ptr.p_proc->p_oppid != 0)
&& (kn->kn_kq->kq_p->p_pid != kn->kn_ptr.p_proc->p_ppid)) {
/*
* This knote is not for the current ptrace(2) parent, ignore.
*/
return 0;
}
}

/*
* if the user is interested in this event, record it.
*/
Expand Down
106 changes: 63 additions & 43 deletions bsd/kern/kern_exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ void vfork_exit(proc_t p, int rv);
void vproc_exit(proc_t p);
__private_extern__ void munge_user64_rusage(struct rusage *a_rusage_p, struct user64_rusage *a_user_rusage_p);
__private_extern__ void munge_user32_rusage(struct rusage *a_rusage_p, struct user32_rusage *a_user_rusage_p);
static int reap_child_locked(proc_t parent, proc_t child, int deadparent, int locked, int droplock);
static int reap_child_locked(proc_t parent, proc_t child, int deadparent, int reparentedtoinit, int locked, int droplock);

/*
* Things which should have prototypes in headers, but don't
Expand Down Expand Up @@ -652,6 +652,7 @@ proc_exit(proc_t p)
/* wait till parentrefs are dropped and grant no more */
proc_childdrainstart(p);
while ((q = p->p_children.lh_first) != NULL) {
int reparentedtoinit = (q->p_listflag & P_LIST_DEADPARENT) ? 1 : 0;
q->p_listflag |= P_LIST_DEADPARENT;
if (q->p_stat == SZOMB) {
if (p != q->p_pptr)
Expand All @@ -670,7 +671,7 @@ proc_exit(proc_t p)
* and the proc struct cannot be used for wakeups as well.
* It is safe to use q here as this is system reap
*/
(void)reap_child_locked(p, q, 1, 1, 0);
(void)reap_child_locked(p, q, 1, reparentedtoinit, 1, 0);
} else {
proc_reparentlocked(q, initproc, 0, 1);
/*
Expand Down Expand Up @@ -794,10 +795,6 @@ proc_exit(proc_t p)
set_bsdtask_info(task, NULL);

knote_hint = NOTE_EXIT | (p->p_xstat & 0xffff);
if (p->p_oppid != 0) {
knote_hint |= NOTE_EXIT_REPARENTED;
}

proc_knote(p, knote_hint);

/* mark the thread as the one that is doing proc_exit
Expand Down Expand Up @@ -836,7 +833,7 @@ proc_exit(proc_t p)
p->p_listflag |= P_LIST_DEADPARENT;
proc_list_unlock();
}
if ((p->p_listflag & P_LIST_DEADPARENT) == 0) {
if ((p->p_listflag & P_LIST_DEADPARENT) == 0 || p->p_oppid) {
if (pp != initproc) {
proc_lock(pp);
pp->si_pid = p->p_pid;
Expand Down Expand Up @@ -899,7 +896,7 @@ proc_exit(proc_t p)
* and the proc struct cannot be used for wakeups as well.
* It is safe to use p here as this is system reap
*/
(void)reap_child_locked(pp, p, 1, 1, 1);
(void)reap_child_locked(pp, p, 1, 0, 1, 1);
/* list lock dropped by reap_child_locked */
}
if (uth->uu_lowpri_window) {
Expand Down Expand Up @@ -934,7 +931,7 @@ proc_exit(proc_t p)
* 1 Process was reaped
*/
static int
reap_child_locked(proc_t parent, proc_t child, int deadparent, int locked, int droplock)
reap_child_locked(proc_t parent, proc_t child, int deadparent, int reparentedtoinit, int locked, int droplock)
{
proc_t trace_parent = PROC_NULL; /* Traced parent process, if tracing */

Expand All @@ -949,41 +946,62 @@ reap_child_locked(proc_t parent, proc_t child, int deadparent, int locked, int d
* ptraced can simply be reaped, refer to radar 5677288
* p_oppid -> ptraced
* trace_parent == initproc -> away from launchd
* P_LIST_DEADPARENT -> came to launchd by reparenting
* reparentedtoinit -> came to launchd by reparenting
*/
if (child->p_oppid && (trace_parent = proc_find(child->p_oppid))
&& !((trace_parent == initproc) && (child->p_lflag & P_LIST_DEADPARENT))) {
if (child->p_oppid) {
int knote_hint;
pid_t oppid;

proc_lock(child);
oppid = child->p_oppid;
child->p_oppid = 0;
knote_hint = NOTE_EXIT | (child->p_xstat & 0xffff);
proc_unlock(child);
if (trace_parent != initproc) {
/*
* proc internal fileds and p_ucred usage safe
* here as child is dead and is not reaped or
* reparented yet
*/
proc_lock(trace_parent);
trace_parent->si_pid = child->p_pid;
trace_parent->si_status = child->p_xstat;
trace_parent->si_code = CLD_CONTINUED;
trace_parent->si_uid = kauth_cred_getruid(child->p_ucred);
proc_unlock(trace_parent);
}
proc_reparentlocked(child, trace_parent, 1, 0);
psignal(trace_parent, SIGCHLD);
proc_list_lock();
wakeup((caddr_t)trace_parent);
child->p_listflag &= ~P_LIST_WAITING;
wakeup(&child->p_stat);
proc_list_unlock();
proc_rele(trace_parent);
if ((locked == 1) && (droplock == 0))

if ((trace_parent = proc_find(oppid))
&& !((trace_parent == initproc) && reparentedtoinit)) {

if (trace_parent != initproc) {
/*
* proc internal fileds and p_ucred usage safe
* here as child is dead and is not reaped or
* reparented yet
*/
proc_lock(trace_parent);
trace_parent->si_pid = child->p_pid;
trace_parent->si_status = child->p_xstat;
trace_parent->si_code = CLD_CONTINUED;
trace_parent->si_uid = kauth_cred_getruid(child->p_ucred);
proc_unlock(trace_parent);
}
proc_reparentlocked(child, trace_parent, 1, 0);

/* resend knote to original parent (and others) after reparenting */
proc_knote(child, knote_hint);

psignal(trace_parent, SIGCHLD);
proc_list_lock();
return (0);
}

if (trace_parent != PROC_NULL) {
proc_rele(trace_parent);
wakeup((caddr_t)trace_parent);
child->p_listflag &= ~P_LIST_WAITING;
wakeup(&child->p_stat);
proc_list_unlock();
proc_rele(trace_parent);
if ((locked == 1) && (droplock == 0))
proc_list_lock();
return (0);
}

/*
* If we can't reparent (e.g. the original parent exited while child was being debugged, or
* original parent is the same as the debugger currently exiting), we still need to satisfy
* the knote lifecycle for other observers on the system. While the debugger was attached,
* the NOTE_EXIT would not have been broadcast during initial child termination.
*/
proc_knote(child, knote_hint);

if (trace_parent != PROC_NULL) {
proc_rele(trace_parent);
}
}

proc_knote(child, NOTE_REAP);
Expand Down Expand Up @@ -1148,6 +1166,8 @@ wait4_nocancel(proc_t q, struct wait4_nocancel_args *uap, int32_t *retval)


if (p->p_stat == SZOMB) {
int reparentedtoinit = (p->p_listflag & P_LIST_DEADPARENT) ? 1 : 0;

proc_list_unlock();
#if CONFIG_MACF
if ((error = mac_proc_check_wait(q, p)) != 0)
Expand Down Expand Up @@ -1208,7 +1228,7 @@ wait4_nocancel(proc_t q, struct wait4_nocancel_args *uap, int32_t *retval)
}

/* Clean up */
(void)reap_child_locked(q, p, 0, 0, 0);
(void)reap_child_locked(q, p, 0, reparentedtoinit, 0, 0);

return (0);
}
Expand Down Expand Up @@ -1410,7 +1430,7 @@ waitid_nocancel(proc_t q, struct waitid_nocancel_args *uap,

/* Prevent other process for waiting for this event? */
if (!(uap->options & WNOWAIT)) {
(void) reap_child_locked(q, p, 0, 0, 0);
(void) reap_child_locked(q, p, 0, 0, 0, 0);
return (0);
}
goto out;
Expand Down Expand Up @@ -1789,7 +1809,7 @@ vproc_exit(proc_t p)
* and the proc struct cannot be used for wakeups as well.
* It is safe to use q here as this is system reap
*/
(void)reap_child_locked(p, q, 1, 1, 0);
(void)reap_child_locked(p, q, 1, 0, 1, 0);
} else {
proc_reparentlocked(q, initproc, 0, 1);
/*
Expand Down Expand Up @@ -1967,7 +1987,7 @@ vproc_exit(proc_t p)
* and the proc struct cannot be used for wakeups as well.
* It is safe to use p here as this is system reap
*/
(void)reap_child_locked(pp, p, 0, 1, 1);
(void)reap_child_locked(pp, p, 0, 0, 1, 1);
/* list lock dropped by reap_child_locked */
}
proc_rele(pp);
Expand Down
7 changes: 7 additions & 0 deletions bsd/kern/kern_fork.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ extern void dtrace_lazy_dofs_duplicate(proc_t, proc_t);
#include <kern/kalloc.h>
#include <kern/mach_param.h>
#include <kern/task.h>
#include <kern/thread.h>
#include <kern/thread_call.h>
#include <kern/zalloc.h>

Expand Down Expand Up @@ -812,6 +813,12 @@ fork_create_child(task_t parent_task, proc_t child_proc, int inherit_memory, int
task_deallocate(child_task);
child_task = NULL;
}

/*
* Tag thread as being the first thread in its task.
*/
thread_set_tag(child_thread, THREAD_TAG_MAINTHREAD);

bad:
thread_yield_internal(1);

Expand Down
2 changes: 1 addition & 1 deletion bsd/kern/policy_check.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ static struct mac_policy_ops policy_ops = {
CHECK_SET_VOID_HOOK(thread_label_init)
CHECK_SET_VOID_HOOK(thread_label_destroy)
.mpo_reserved18 = common_void_hook,
.mpo_reserved19 = common_void_hook,
CHECK_SET_VOID_HOOK(vnode_notify_open)
.mpo_reserved20 = common_void_hook,
.mpo_reserved21 = common_void_hook,
.mpo_reserved22 = common_void_hook,
Expand Down
Loading

0 comments on commit 2b43307

Please sign in to comment.