commit-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[hurd] 02/06: proc: Hierarchical proc servers.


From: Samuel Thibault
Subject: [hurd] 02/06: proc: Hierarchical proc servers.
Date: Sat, 10 Jun 2017 00:38:17 +0000

This is an automated email from the git hooks/post-receive script.

sthibault pushed a commit to branch upstream
in repository hurd.

commit 34a94ce86b1bada9c0768f631540735d44f41100
Author: Justus Winter <address@hidden>
Date:   Thu Mar 9 23:55:12 2017 +0100

    proc: Hierarchical proc servers.
    
    Previously, a Subhurd's tasks were shown as weird processes in the
    Motherhurd.  This change connects the proc server in the Motherhurd
    with the proc server in the Subhurd, embedding the Subhurd's process
    hierarchy.  Subhurd's processes can now be inspected and debugged like
    any other process.
    
    * NEWS: Update.
    * boot/boot.c (mach_msg_forward): New function.
    (boot_demuxer): Forward messages arriving on the new task notification
    port from the proc server, and forward them to the proc server inside
    the Subhurd via the notification port.
    * proc/info.c (S_proc_task2proc): Relay request for processes in a task
    namespace to the Subhurd's proc server.
    (S_proc_pid2proc): Likewise.
    (S_proc_getprocargs): Likewise.
    (S_proc_getprocenv): Likewise.
    (S_proc_getprocinfo): Likewise.  Translate PIDs.
    (S_proc_getloginid): Likewise.
    (S_proc_getloginpids): Likewise.
    * proc/mgt.c (namespace_is_subprocess): New function.
    (namespace_translate_pids): Likewise.
    * proc/msg.c (S_proc_getmsgport): Relay request for processes in a task
    namespace to the Subhurd's proc server.
    * proc/pgrp.c (S_proc_getsid): Likewise.  Translate PIDs.
    (S_proc_getsessionpids): Likewise.
    (S_proc_getsessionpgids): Likewise.
    (S_proc_getpgrppids): Likewise.
    * proc/proc.h (namespace_is_subprocess): New prototype.
    (namespace_translate_pids): Likewise.
---
 NEWS        |   6 ++
 boot/boot.c |  54 +++++++++++++++
 proc/info.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 proc/mgt.c  |  56 ++++++++++++++++
 proc/msg.c  |  26 +++++++-
 proc/pgrp.c | 100 ++++++++++++++++++++++++++++
 proc/proc.h |   2 +
 7 files changed, 458 insertions(+), 2 deletions(-)

diff --git a/NEWS b/NEWS
index 05e04d5..1b500be 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,9 @@
+Version X (2017-06-XX)
+
+Subhurd's processes are now properly embedded in the Motherhurds
+process hierarchy.  They can be inspected and debugged just like any
+other process.
+
 Version 0.9 (2016-12-18)
 
 The 'boot' program can now be run as unprivileged user, allowing any
diff --git a/boot/boot.c b/boot/boot.c
index 950aedb..13a19d2 100644
--- a/boot/boot.c
+++ b/boot/boot.c
@@ -196,12 +196,66 @@ mig_reply_setup (
 #undef OutP
 }
 
+error_t
+mach_msg_forward (mach_msg_header_t *inp,
+                  mach_port_t destination, mach_msg_type_name_t 
destination_type)
+{
+  /* Put the reply port back at the correct position, insert new
+     destination.  */
+  inp->msgh_local_port = inp->msgh_remote_port;
+  inp->msgh_remote_port = destination;
+  inp->msgh_bits =
+    MACH_MSGH_BITS (destination_type, MACH_MSGH_BITS_REMOTE (inp->msgh_bits))
+    | MACH_MSGH_BITS_OTHER (inp->msgh_bits);
+
+  /* A word about resources carried in complex messages.
+
+     "In a received message, msgt_deallocate is TRUE in type
+     descriptors for out-of-line memory".  Therefore, "[the
+     out-of-line memory] is implicitly deallocated from the sender
+     [when we resend the message], as if by vm_deallocate".
+
+     Similarly, rights in messages will be either
+     MACH_MSG_TYPE_PORT_SEND, MACH_MSG_TYPE_PORT_SEND_ONCE, or
+     MACH_MSG_TYPE_PORT_RECEIVE.  These types are aliases for,
+     respectively, MACH_MSG_TYPE_MOVE_SEND,
+     MACH_MSG_TYPE_MOVE_SEND_ONCE, and MACH_MSG_TYPE_MOVE_RECEIVE.
+     Therefore, the rights are moved when we resend the message.  */
+
+  return mach_msg (inp, MACH_SEND_MSG, inp->msgh_size,
+                   0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+}
+
 int
 boot_demuxer (mach_msg_header_t *inp,
              mach_msg_header_t *outp)
 {
+  error_t err;
   mig_routine_t routine;
   mig_reply_setup (inp, outp);
+
+  if (inp->msgh_local_port == task_notification_port
+      && MACH_PORT_VALID (new_task_notification)
+      && 24000 <= inp->msgh_id && inp->msgh_id < 24100)
+    {
+      /* This is a message of the Process subsystem.  We relay this to
+         allow the "outer" proc servers to communicate with the "inner"
+         one.  */
+      mig_reply_header_t *reply = (mig_reply_header_t *) outp;
+
+      if (MACH_PORT_VALID (new_task_notification))
+        err = mach_msg_forward (inp, new_task_notification, 
MACH_MSG_TYPE_COPY_SEND);
+      else
+        err = EOPNOTSUPP;
+
+      if (err)
+        reply->RetCode = err;
+      else
+        reply->RetCode = MIG_NO_REPLY;
+
+      return TRUE;
+    }
+
   if ((routine = io_server_routine (inp)) ||
       (routine = device_server_routine (inp)) ||
       (routine = notify_server_routine (inp)) ||
diff --git a/proc/info.c b/proc/info.c
index 9732140..79a4c37 100644
--- a/proc/info.c
+++ b/proc/info.c
@@ -109,6 +109,28 @@ S_proc_task2proc (struct proc *callerp,
   if (!p)
     return ESRCH;
 
+  if (namespace_is_subprocess (p))
+    {
+      /* Relay it to the Subhurd's proc server (if any).  */
+      error_t err;
+
+      /* Release global lock while talking to the other proc server.  */
+      pthread_mutex_unlock (&global_lock);
+
+      err = proc_task2proc (p->p_task_namespace, t, outproc);
+
+      pthread_mutex_lock (&global_lock);
+
+      if (! err)
+       {
+         *outproc_type = MACH_MSG_TYPE_MOVE_SEND;
+         mach_port_deallocate (mach_task_self (), t);
+         return 0;
+       }
+
+      /* Fallback.  */
+    }
+
   *outproc = ports_get_right (p);
   *outproc_type = MACH_MSG_TYPE_MAKE_SEND;
   mach_port_deallocate (mach_task_self (), t);
@@ -151,6 +173,27 @@ S_proc_pid2proc (struct proc *callerp,
   if (! check_owner (callerp, p))
     return EPERM;
 
+  if (namespace_is_subprocess (p))
+    {
+      /* Relay it to the Subhurd's proc server (if any).  */
+      error_t err;
+
+      /* Release global lock while talking to the other proc server.  */
+      pthread_mutex_unlock (&global_lock);
+
+      err = proc_task2proc (p->p_task_namespace, p->p_task, outproc);
+
+      pthread_mutex_lock (&global_lock);
+
+      if (! err)
+       {
+         *outproc_type = MACH_MSG_TYPE_MOVE_SEND;
+         return 0;
+       }
+
+      /* Fallback.  */
+    }
+
   *outproc = ports_get_right (p);
   *outproc_type = MACH_MSG_TYPE_MAKE_SEND;
   return 0;
@@ -345,6 +388,27 @@ S_proc_getprocargs (struct proc *callerp,
   if (!p)
     return ESRCH;
 
+  if (namespace_is_subprocess (p))
+    {
+      /* Relay it to the Subhurd's proc server (if any).  */
+      error_t err;
+      pid_t pid_sub;
+
+      /* Release global lock while talking to the other proc server.  */
+      pthread_mutex_unlock (&global_lock);
+
+      err = proc_task2pid (p->p_task_namespace, p->p_task, &pid_sub);
+      if (! err)
+       err = proc_getprocargs (p->p_task_namespace, pid_sub, buf, buflen);
+
+      pthread_mutex_lock (&global_lock);
+
+      if (! err)
+       return 0;
+
+      /* Fallback.  */
+    }
+
   return get_string_array (p->p_task, p->p_argv, (vm_address_t *) buf, buflen);
 }
 
@@ -362,6 +426,27 @@ S_proc_getprocenv (struct proc *callerp,
   if (!p)
     return ESRCH;
 
+  if (namespace_is_subprocess (p))
+    {
+      /* Relay it to the Subhurd's proc server (if any).  */
+      error_t err;
+      pid_t pid_sub;
+
+      /* Release global lock while talking to the other proc server.  */
+      pthread_mutex_unlock (&global_lock);
+
+      err = proc_task2pid (p->p_task_namespace, p->p_task, &pid_sub);
+      if (! err)
+       err = proc_getprocenv (p->p_task_namespace, pid_sub, buf, buflen);
+
+      pthread_mutex_lock (&global_lock);
+
+      if (! err)
+       return 0;
+
+      /* Fallback.  */
+    }
+
   return get_string_array (p->p_task, p->p_envp, (vm_address_t *)buf, buflen);
 }
 
@@ -398,6 +483,82 @@ S_proc_getprocinfo (struct proc *callerp,
   if (!p)
     return ESRCH;
 
+  if (namespace_is_subprocess (p))
+    {
+      /* Relay it to the Subhurd's proc server (if any).  */
+      error_t err;
+      pid_t pid_sub;
+
+      /* Release global lock while talking to the other proc server.  */
+      pthread_mutex_unlock (&global_lock);
+
+      err = proc_task2pid (p->p_task_namespace, p->p_task, &pid_sub);
+      if (! err)
+       err = proc_getprocinfo (p->p_task_namespace, pid_sub, flags,
+                               piarray, piarraylen, waits, waits_len);
+
+      if (! err && *piarray && *piarraylen * sizeof (int) >= sizeof *pi)
+       {
+         /* Fixup the PIDs to refer to this Hurd's processes.  */
+         task_t t_ppid = MACH_PORT_NULL;
+         task_t t_pgrp = MACH_PORT_NULL;
+         task_t t_session = MACH_PORT_NULL;
+         task_t t_logincollection = MACH_PORT_NULL;
+
+         pi = (struct procinfo *) *piarray;
+
+         /* We handle errors by checking each returned task.  */
+         if (pi->ppid != pid_sub)
+           proc_pid2task (p->p_task_namespace, pi->ppid, &t_ppid);
+         proc_pid2task (p->p_task_namespace, pi->pgrp, &t_pgrp);
+         proc_pid2task (p->p_task_namespace, pi->session, &t_session);
+         proc_pid2task (p->p_task_namespace, pi->logincollection,
+                        &t_logincollection);
+
+         /* Reacquire the global lock for the hash table lookups.  */
+         pthread_mutex_lock (&global_lock);
+
+         if (MACH_PORT_VALID (t_ppid))
+           {
+             struct proc *q = task_find (t_ppid);
+             pi->ppid = q ? q->p_pid : (pid_t) -1;
+             mach_port_deallocate (mach_task_self (), t_ppid);
+           }
+         else
+           {
+             /* Either the pid2task lookup failed, or this process is
+                a root of a process hierarchy in the Subhurd.  Either
+                way, we attach it to the creator of the task
+                namespace.  */
+             pi->ppid = namespace_find_root (p)->p_pid;
+           }
+         if (MACH_PORT_VALID (t_pgrp))
+           {
+             struct proc *q = task_find (t_pgrp);
+             pi->pgrp = q ? q->p_pid : (pid_t) -1;
+             mach_port_deallocate (mach_task_self (), t_pgrp);
+           }
+         if (MACH_PORT_VALID (t_session))
+           {
+             struct proc *q = task_find (t_session);
+             pi->session = q ? q->p_pid : (pid_t) -1;
+             mach_port_deallocate (mach_task_self (), t_session);
+           }
+         if (MACH_PORT_VALID (t_logincollection))
+           {
+             struct proc *q = task_find (t_logincollection);
+             pi->logincollection = q ? q->p_pid : (pid_t) -1;
+             mach_port_deallocate (mach_task_self (), t_logincollection);
+           }
+
+         return 0;
+       }
+
+      pthread_mutex_lock (&global_lock);
+      err = 0;
+      /* Fallback.  */
+    }
+
   task = p->p_task;
 
   check_msgport_death (p);
@@ -644,13 +805,37 @@ S_proc_getloginid (struct proc *callerp,
                   pid_t *leader)
 {
   struct proc *proc = pid_find (pid);
-  struct proc *p;
+  struct proc *p = proc;
 
   /* No need to check CALLERP here; we don't use it. */
 
   if (!proc)
     return ESRCH;
 
+  if (namespace_is_subprocess (p))
+    {
+      /* Relay it to the Subhurd's proc server (if any).  */
+      error_t err;
+      pid_t pid_sub;
+
+      /* Release global lock while talking to the other proc server.  */
+      pthread_mutex_unlock (&global_lock);
+
+      err = proc_task2pid (p->p_task_namespace, p->p_task, &pid_sub);
+      if (! err)
+       err = proc_getloginid (p->p_task_namespace, pid_sub, leader);
+      if (! err)
+       /* Acquires global_lock.  */
+       err = namespace_translate_pids (p->p_task_namespace, leader, 1);
+      else
+       pthread_mutex_lock (&global_lock);
+
+      if (! err)
+       return 0;
+
+      /* Fallback.  */
+    }
+
   for (p = proc; !p->p_loginleader; p = p->p_parent)
     assert (p);
 
@@ -674,6 +859,35 @@ S_proc_getloginpids (struct proc *callerp,
 
   /* No need to check CALLERP here; we don't use it. */
 
+  if (!l)
+    return ESRCH;
+
+  if (namespace_is_subprocess (l))
+    {
+      /* Relay it to the Subhurd's proc server (if any).  */
+      error_t err;
+      pid_t pid_sub;
+      pid_t leader_sub;
+      task_t leader_task;
+
+      /* Release global lock while talking to the other proc server.  */
+      pthread_mutex_unlock (&global_lock);
+
+      err = proc_task2pid (l->p_task_namespace, l->p_task, &pid_sub);
+      if (! err)
+       err = proc_getloginpids (l->p_task_namespace, pid_sub, pids, npids);
+      if (! err)
+       /* Acquires global_lock.  */
+       err = namespace_translate_pids (l->p_task_namespace, *pids, *npids);
+      else
+       pthread_mutex_lock (&global_lock);
+
+      if (! err)
+       return 0;
+
+      /* Fallback.  */
+    }
+
   if (!l || !l->p_loginleader)
     return ESRCH;
 
diff --git a/proc/mgt.c b/proc/mgt.c
index 87a7c96..a9015cc 100644
--- a/proc/mgt.c
+++ b/proc/mgt.c
@@ -732,7 +732,61 @@ new_proc (task_t task)
     complete_proc (p, genpid ());
   return p;
 }
+
 
+
+/* Task namespace support.  */
+
+/* Check if a given process is part of a task namespace but is not the
+   root.  The root is managed by us, while all other tasks are managed
+   by the root itself.  */
+int
+namespace_is_subprocess (struct proc *p)
+{
+  return (p
+          && MACH_PORT_VALID (p->p_task_namespace)
+          && p->p_parent
+          && MACH_PORT_VALID (p->p_parent->p_task_namespace));
+}
+
+/* Translate PIDs valid in NAMESPACE into PIDs valid in our own
+   process space.
+
+   Conditions: global_lock is unlocked before calling, and is locked
+   afterwards.  */
+error_t
+namespace_translate_pids (mach_port_t namespace, pid_t *pids, size_t pids_len)
+{
+  size_t i;
+  task_t *tasks;
+
+  tasks = calloc (pids_len, sizeof *tasks);
+  if (tasks == NULL)
+    {
+      pthread_mutex_lock (&global_lock);
+      return ENOMEM;
+    }
+
+  for (i = 0; i < pids_len; i++)
+    /* We handle errors by checking each returned task.  */
+    proc_pid2task (namespace, pids[i], &tasks[i]);
+
+  pthread_mutex_lock (&global_lock);
+
+  for (i = 0; i < pids_len; i++)
+    if (MACH_PORT_VALID (tasks[i]))
+      {
+        struct proc *p = task_find_nocreate (tasks[i]);
+        mach_port_deallocate (mach_task_self (), tasks[i]);
+        pids[i] = p ? p->p_pid : (pid_t) -1;
+      }
+    else
+      pids[i] = (pid_t) -1;
+
+  free (tasks);
+  return 0;
+}
+
 /* Find the creator of the task namespace that P is in.  */
 struct proc *
 namespace_find_root (struct proc *p)
@@ -759,6 +813,8 @@ namespace_terminate (struct proc *p, void *cookie)
     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. */
diff --git a/proc/msg.c b/proc/msg.c
index e145f6e..8efc993 100644
--- a/proc/msg.c
+++ b/proc/msg.c
@@ -137,7 +137,31 @@ S_proc_getmsgport (struct proc *callerp,
 
   p = pid_find_allow_zombie (pid);
 
-restart:  
+  if (namespace_is_subprocess (p))
+    {
+      /* Relay it to the Subhurd's proc server (if any).  */
+      error_t err;
+      pid_t pid_sub;
+
+      /* Release global lock while talking to the other proc server.  */
+      pthread_mutex_unlock (&global_lock);
+
+      err = proc_task2pid (p->p_task_namespace, p->p_task, &pid_sub);
+      if (! err)
+        err = proc_getmsgport (p->p_task_namespace, pid_sub, msgport);
+
+      pthread_mutex_lock (&global_lock);
+
+      if (! err)
+       {
+         *msgport_type = MACH_MSG_TYPE_MOVE_SEND;
+         return 0;
+       }
+
+      /* Fallback.  */
+    }
+
+ restart:
   while (p && p->p_deadmsg && !p->p_dead)
     {
       callerp->p_msgportwait = 1;
diff --git a/proc/pgrp.c b/proc/pgrp.c
index d7c562f..9db1dba 100644
--- a/proc/pgrp.c
+++ b/proc/pgrp.c
@@ -147,6 +147,30 @@ S_proc_getsid (struct proc *callerp,
 
   /* No need to check CALLERP; we don't use it. */
 
+  if (namespace_is_subprocess (p))
+    {
+      /* Relay it to the Subhurd's proc server (if any).  */
+      error_t err;
+      pid_t pid_sub;
+
+      /* Release global lock while talking to the other proc server.  */
+      pthread_mutex_unlock (&global_lock);
+
+      err = proc_task2pid (p->p_task_namespace, p->p_task, &pid_sub);
+      if (! err)
+        err = proc_getsid (p->p_task_namespace, pid_sub, sid);
+      if (! err)
+       /* Acquires global_lock.  */
+       err = namespace_translate_pids (p->p_task_namespace, sid, 1);
+      else
+       pthread_mutex_lock (&global_lock);
+
+      if (! err)
+       return 0;
+
+      /* Fallback.  */
+    }
+
   *sid = p->p_pgrp->pg_session->s_sid;
   return 0;
 }
@@ -167,6 +191,31 @@ S_proc_getsessionpids (struct proc *callerp,
 
   /* No need to check CALLERP; we don't use it. */
 
+  p = pid_find (sid);
+  if (namespace_is_subprocess (p))
+    {
+      /* Relay it to the Subhurd's proc server (if any).  */
+      error_t err;
+      pid_t pid_sub;
+
+      /* Release global lock while talking to the other proc server.  */
+      pthread_mutex_unlock (&global_lock);
+
+      err = proc_task2pid (p->p_task_namespace, p->p_task, &pid_sub);
+      if (! err)
+        err = proc_getsessionpids (p->p_task_namespace, pid_sub, pids, npidsp);
+      if (! err)
+       /* Acquires global_lock.  */
+       err = namespace_translate_pids (p->p_task_namespace, *pids, *npidsp);
+      else
+       pthread_mutex_lock (&global_lock);
+
+      if (! err)
+       return 0;
+
+      /* Fallback.  */
+    }
+
   s = session_find (sid);
   if (!s)
     return ESRCH;
@@ -206,6 +255,7 @@ S_proc_getsessionpgids (struct proc *callerp,
                        size_t *npgidsp)
 {
   int count;
+  struct proc *p;
   struct pgrp *pg;
   struct session *s;
   pid_t *pp = *pgids;
@@ -213,6 +263,31 @@ S_proc_getsessionpgids (struct proc *callerp,
 
   /* No need to check CALLERP; we don't use it. */
 
+  p = pid_find (sid);
+  if (namespace_is_subprocess (p))
+    {
+      /* Relay it to the Subhurd's proc server (if any).  */
+      error_t err;
+      pid_t pid_sub;
+
+      /* Release global lock while talking to the other proc server.  */
+      pthread_mutex_unlock (&global_lock);
+
+      err = proc_task2pid (p->p_task_namespace, p->p_task, &pid_sub);
+      if (! err)
+        err = proc_getsessionpgids (p->p_task_namespace, pid_sub, pgids, 
npgidsp);
+      if (! err)
+       /* Acquires global_lock.  */
+       err = namespace_translate_pids (p->p_task_namespace, *pgids, *npgidsp);
+      else
+       pthread_mutex_lock (&global_lock);
+
+      if (! err)
+       return 0;
+
+      /* Fallback.  */
+    }
+
   s = session_find (sid);
   if (!s)
     return ESRCH;
@@ -254,6 +329,31 @@ S_proc_getpgrppids (struct proc *callerp,
 
   /* No need to check CALLERP; we don't use it. */
 
+  p = pid_find (pgid);
+  if (namespace_is_subprocess (p))
+    {
+      /* Relay it to the Subhurd's proc server (if any).  */
+      error_t err;
+      pid_t pid_sub;
+
+      /* Release global lock while talking to the other proc server.  */
+      pthread_mutex_unlock (&global_lock);
+
+      err = proc_task2pid (p->p_task_namespace, p->p_task, &pid_sub);
+      if (! err)
+        err = proc_getpgrppids (p->p_task_namespace, pid_sub, pids, npidsp);
+      if (! err)
+       /* Acquires global_lock.  */
+       err = namespace_translate_pids (p->p_task_namespace, *pids, *npidsp);
+      else
+       pthread_mutex_lock (&global_lock);
+
+      if (! err)
+       return 0;
+
+      /* Fallback.  */
+    }
+
   if (pgid == 0)
     pg = callerp->p_pgrp;
   else
diff --git a/proc/proc.h b/proc/proc.h
index c069614..333e884 100644
--- a/proc/proc.h
+++ b/proc/proc.h
@@ -201,6 +201,8 @@ void leave_pgrp (struct proc *);
 void join_pgrp (struct proc *);
 void boot_setsid (struct proc *);
 
+int namespace_is_subprocess (struct proc *p);
+error_t namespace_translate_pids (mach_port_t namespace, pid_t *pids, size_t 
pids_len);
 struct proc *namespace_find_root (struct proc *);
 void process_has_exited (struct proc *);
 void alert_parent (struct proc *);

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-hurd/hurd.git



reply via email to

[Prev in Thread] Current Thread [Next in Thread]