diff options
Diffstat (limited to 'debian/patches/0012-proc-implement-proc_make_task_namespace.patch')
-rw-r--r-- | debian/patches/0012-proc-implement-proc_make_task_namespace.patch | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/debian/patches/0012-proc-implement-proc_make_task_namespace.patch b/debian/patches/0012-proc-implement-proc_make_task_namespace.patch new file mode 100644 index 00000000..a7bd19b2 --- /dev/null +++ b/debian/patches/0012-proc-implement-proc_make_task_namespace.patch @@ -0,0 +1,224 @@ +From 5aef28222f05dec56cd1212e70766d8bf779df11 Mon Sep 17 00:00:00 2001 +From: Justus Winter <4winter@informatik.uni-hamburg.de> +Date: Tue, 11 Nov 2014 21:23:42 +0100 +Subject: [PATCH hurd 12/14] proc: implement `proc_make_task_namespace' + +* proc/proc.h (struct proc): Add field `p_task_namespace'. +* proc/mgt.c (S_proc_child): Propagate `p_task_namespace' to child. +(allocate_proc): Initialize `p_task_namespace'. +(namespace_terminate): New function. +(process_has_exited): Reparent children of dead tasks in the namespace +to the root process. Terminate all tasks if the root process dies. +Reap dead tasks. +(S_mach_notify_new_task): For newly created tasks thats parent is in a +namespace, call S_proc_child and forward the `mach_notify_new_task' +message. +(S_proc_make_task_namespace): New function. +--- + proc/mgt.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----- + proc/proc.h | 4 +++ + 2 files changed, 107 insertions(+), 9 deletions(-) + +diff --git a/proc/mgt.c b/proc/mgt.c +index 32408ae..bf400ba 100644 +--- a/proc/mgt.c ++++ b/proc/mgt.c +@@ -220,6 +220,13 @@ S_proc_child (struct proc *parentp, + childp->end_code = parentp->end_code; + } + ++ if (MACH_PORT_VALID (parentp->p_task_namespace)) ++ { ++ mach_port_mod_refs (mach_task_self (), parentp->p_task_namespace, ++ MACH_PORT_RIGHT_SEND, +1); ++ childp->p_task_namespace = parentp->p_task_namespace; ++ } ++ + return 0; + } + +@@ -577,6 +584,7 @@ allocate_proc (task_t task) + + memset (&p->p_pi + 1, 0, sizeof *p - sizeof p->p_pi); + p->p_task = task; ++ p->p_task_namespace = MACH_PORT_NULL; + p->p_msgport = MACH_PORT_NULL; + + pthread_cond_init (&p->p_wakeup, NULL); +@@ -721,6 +729,16 @@ new_proc (task_t task) + return p; + } + ++/* Used with prociterate to terminate all tasks in a task ++ namespace. */ ++static void ++namespace_terminate (struct proc *p, void *cookie) ++{ ++ mach_port_t *namespacep = cookie; ++ if (p->p_task_namespace == *namespacep) ++ task_terminate (p->p_task); ++} ++ + /* The task associated with process P has died. Drop most state, + and then record us as dead. Our parent will eventually complete the + deallocation. */ +@@ -751,13 +769,39 @@ process_has_exited (struct proc *p) + + ids_rele (p->p_id); + +- /* Reparent our children to init by attaching the head and tail +- of our list onto init's. */ ++ /* Reparent our children to init by attaching the head and tail of ++ our list onto init's. If the process is part of a task ++ namespace, reparent to the process that created the namespace ++ instead. */ + if (p->p_ochild) + { ++ struct proc *reparent_to = init_proc; + struct proc *tp; /* will point to the last one. */ + int isdead = 0; + ++ if (MACH_PORT_VALID (p->p_task_namespace)) ++ { ++ for (tp = p; ++ MACH_PORT_VALID (tp->p_parent->p_task_namespace); ++ tp = tp->p_parent) ++ { ++ /* Walk up the process hierarchy until we find the ++ creator of the task namespace. */ ++ } ++ ++ if (p == tp) ++ { ++ /* The creator of the task namespace died. Terminate ++ all tasks. */ ++ prociterate (namespace_terminate, &p->p_task_namespace); ++ ++ mach_port_deallocate (mach_task_self (), p->p_task_namespace); ++ p->p_task_namespace = MACH_PORT_NULL; ++ } ++ else ++ reparent_to = tp; ++ } ++ + /* first tell them their parent is changing */ + for (tp = p->p_ochild; tp->p_sib; tp = tp->p_sib) + { +@@ -765,7 +809,7 @@ process_has_exited (struct proc *p) + nowait_msg_proc_newids (tp->p_msgport, tp->p_task, + 1, tp->p_pgrp->pg_pgid, + !tp->p_pgrp->pg_orphcnt); +- tp->p_parent = init_proc; ++ tp->p_parent = reparent_to; + if (tp->p_dead) + isdead = 1; + } +@@ -773,17 +817,17 @@ process_has_exited (struct proc *p) + nowait_msg_proc_newids (tp->p_msgport, tp->p_task, + 1, tp->p_pgrp->pg_pgid, + !tp->p_pgrp->pg_orphcnt); +- tp->p_parent = init_proc; ++ tp->p_parent = reparent_to; + + /* And now append the lists. */ +- tp->p_sib = init_proc->p_ochild; ++ tp->p_sib = reparent_to->p_ochild; + if (tp->p_sib) + tp->p_sib->p_prevsib = &tp->p_sib; +- init_proc->p_ochild = p->p_ochild; +- p->p_ochild->p_prevsib = &init_proc->p_ochild; ++ reparent_to->p_ochild = p->p_ochild; ++ p->p_ochild->p_prevsib = &reparent_to->p_ochild; + + if (isdead) +- alert_parent (init_proc); ++ alert_parent (reparent_to); + } + + /* If an operation is in progress for this process, cause it +@@ -795,6 +839,23 @@ process_has_exited (struct proc *p) + + /* Cancel any outstanding RPCs done on behalf of the dying process. */ + ports_interrupt_rpcs (p); ++ ++ /* No one is going to wait for processes in a task namespace. */ ++ if (MACH_PORT_VALID (p->p_task_namespace)) ++ { ++ mach_port_t task; ++ mach_port_deallocate (mach_task_self (), p->p_task_namespace); ++ p->p_waited = 1; ++ ++ /* XXX: `complete_exit' will destroy p->p_task if it is valid. ++ Prevent this so that `do_mach_notify_dead_name' can ++ deallocate the right. The proper fix is not to use ++ mach_port_destroy in the first place. */ ++ task = p->p_task; ++ p->p_task = MACH_PORT_NULL; ++ complete_exit (p); ++ mach_port_deallocate (mach_task_self (), task); ++ } + } + + void +@@ -1008,9 +1069,42 @@ S_mach_notify_new_task (mach_port_t notify, + childp = new_proc (task); + } + +- /* XXX do something interesting */ ++ if (MACH_PORT_VALID (parentp->p_task_namespace)) ++ { ++ error_t err; ++ /* Tasks in a task namespace are not expected to call ++ proc_child, so we do it on their behalf. */ ++ mach_port_mod_refs (mach_task_self (), task, MACH_PORT_RIGHT_SEND, +1); ++ err = S_proc_child (parentp, task); ++ if (! err) ++ /* Relay the notification. This consumes TASK and PARENT. */ ++ return mach_notify_new_task (childp->p_task_namespace, task, parent); ++ } + + mach_port_deallocate (mach_task_self (), task); + mach_port_deallocate (mach_task_self (), parent); + return 0; + } ++ ++/* Implement proc_make_task_namespace as described in ++ <hurd/process.defs>. */ ++error_t ++S_proc_make_task_namespace (struct proc *callerp, ++ mach_port_t notify) ++{ ++ if (! callerp) ++ return EOPNOTSUPP; ++ ++ if (! MACH_PORT_VALID (notify)) ++ return EINVAL; ++ ++ if (MACH_PORT_VALID (callerp->p_task_namespace)) ++ { ++ mach_port_deallocate (mach_task_self (), notify); ++ return EBUSY; ++ } ++ ++ callerp->p_task_namespace = notify; ++ ++ return 0; ++} +diff --git a/proc/proc.h b/proc/proc.h +index 6196697..a056d18 100644 +--- a/proc/proc.h ++++ b/proc/proc.h +@@ -58,6 +58,10 @@ struct proc + /* Process group structure */ + struct pgrp *p_pgrp; + ++ /* Processes may live in a task namespace identified by the ++ notification port registered by proc_make_task_namespace. */ ++ mach_port_t p_task_namespace; /* send right */ ++ + /* Communication */ + mach_port_t p_msgport; /* send right */ + +-- +2.1.1 + |