aboutsummaryrefslogtreecommitdiff
path: root/proc
diff options
context:
space:
mode:
Diffstat (limited to 'proc')
-rw-r--r--proc/info.c216
-rw-r--r--proc/mgt.c56
-rw-r--r--proc/msg.c26
-rw-r--r--proc/pgrp.c100
-rw-r--r--proc/proc.h2
5 files changed, 398 insertions, 2 deletions
diff --git a/proc/info.c b/proc/info.c
index 97321408..79a4c37f 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 87a7c96b..a9015ccc 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 e145f6e6..8efc993e 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 d7c562fa..9db1dba6 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 c0696149..333e8840 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 *);