summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael I. Bushnell <mib@gnu.org>1996-03-29 14:38:23 +0000
committerMichael I. Bushnell <mib@gnu.org>1996-03-29 14:38:23 +0000
commit07a9e1c2c2eaff10eee4e1e8ca5cdbf4b429ad54 (patch)
treebd10d12c7b993e3c44fc76f4ae2ad869fff14f63
parent3538ecac80377f828c6bba504e468201ea7ea55b (diff)
(S_proc_reassign): Use new ports_transfer_right call instead of
claim/install sequence; the latter has leaves the port out of any hash table for a time, which produces a race with incoming messages.
-rw-r--r--proc/mgt.c47
1 files changed, 41 insertions, 6 deletions
diff --git a/proc/mgt.c b/proc/mgt.c
index 135f448e..5478b9af 100644
--- a/proc/mgt.c
+++ b/proc/mgt.c
@@ -34,7 +34,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "proc.h"
#include "process_S.h"
-#include "ourmsg_U.h"
+#include "mutated_ourmsg_U.h"
#include "proc_exc_S.h"
#include "proc_exc_U.h"
#include <hurd/signal.h>
@@ -87,6 +87,9 @@ S_proc_reauthenticate (struct proc *p, mach_port_t rendport)
uid_t *gen_uids, *aux_uids, *gen_gids, *aux_gids;
u_int ngen_uids, naux_uids, ngen_gids, naux_gids;
+ if (!p)
+ return EOPNOTSUPP;
+
gen_uids = gubuf;
aux_uids = aubuf;
gen_gids = ggbuf;
@@ -95,6 +98,7 @@ S_proc_reauthenticate (struct proc *p, mach_port_t rendport)
ngen_uids = naux_uids = 50;
ngen_gids = naux_gids = 50;
+
err = auth_server_authenticate (authserver, ports_get_right (p),
MACH_MSG_TYPE_MAKE_SEND,
rendport, MACH_MSG_TYPE_MOVE_SEND,
@@ -133,6 +137,9 @@ S_proc_child (struct proc *parentp,
{
struct proc *childp = task_find (childt);
+ if (!parentp)
+ return EOPNOTSUPP;
+
if (!childp)
return ESRCH;
@@ -196,6 +203,9 @@ S_proc_reassign (struct proc *p,
struct proc *stubp = task_find (newt);
mach_port_t foo;
+ if (!p)
+ return EOPNOTSUPP;
+
if (!stubp)
return ESRCH;
@@ -208,14 +218,13 @@ S_proc_reassign (struct proc *p,
mach_port_deallocate (mach_task_self (), p->p_task);
p->p_task = newt;
- /* For security, we need use the request port from STUBP, and
- not inherit this state. */
- ports_reallocate_from_external (p, ports_claim_right (stubp));
+ /* For security, we need use the request port from STUBP */
+ ports_transfer_right (p, stubp);
/* Redirect the task-death notification to the new receive right. */
mach_port_request_notification (mach_task_self (), p->p_task,
MACH_NOTIFY_DEAD_NAME, 1,
- ports_get_right (p),
+ p->p_pi.port_right,
MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo);
if (foo)
mach_port_deallocate (mach_task_self (), foo);
@@ -236,6 +245,8 @@ S_proc_reassign (struct proc *p,
/* Destroy stubp */
stubp->p_task = 0; /* block deallocation */
process_has_exited (stubp);
+ stubp->p_waited = 1; /* fake out complete_exit */
+ complete_exit (stubp);
add_proc_to_hash (p);
@@ -247,6 +258,9 @@ kern_return_t
S_proc_setowner (struct proc *p,
uid_t owner)
{
+ if (!p)
+ return EOPNOTSUPP;
+
if (! check_uid (p, owner))
return EPERM;
@@ -262,6 +276,8 @@ S_proc_getpids (struct proc *p,
pid_t *ppid,
int *orphaned)
{
+ if (!p)
+ return EOPNOTSUPP;
*pid = p->p_pid;
*ppid = p->p_parent->p_pid;
*orphaned = !p->p_pgrp->pg_orphcnt;
@@ -274,6 +290,8 @@ S_proc_set_arg_locations (struct proc *p,
vm_address_t argv,
vm_address_t envp)
{
+ if (!p)
+ return EOPNOTSUPP;
p->p_argv = argv;
p->p_envp = envp;
return 0;
@@ -299,6 +317,9 @@ S_proc_dostop (struct proc *p,
unsigned int nthreads = 2, i;
error_t err;
+ if (!p)
+ return EOPNOTSUPP;
+
err = task_suspend (p->p_task);
if (err)
return err;
@@ -342,6 +363,8 @@ S_proc_handle_exceptions (struct proc *p,
struct exc *e;
error_t err;
+ /* No need to check P here; we don't use it. */
+
err = ports_import_port (exc_class, proc_bucket, msgport,
(sizeof (struct exc)
+ (statecnt * sizeof (natural_t))), &e);
@@ -445,6 +468,8 @@ S_proc_getallpids (struct proc *p,
*(*(pid_t **)loc)++ = p->p_pid;
}
+ /* No need to check P here; we don't use it. */
+
add_tasks (0);
nprocs = 0;
@@ -601,8 +626,18 @@ new_proc (task_t task)
void
process_has_exited (struct proc *p)
{
+ /* We have already died; this can happen since both proc_reassign
+ and dead-name notifications could result in two calls to this
+ routine for the same process. */
+ if (p->p_dead)
+ return;
+
alert_parent (p);
+ if (p->p_msgport)
+ mach_port_deallocate (mach_task_self (), p->p_msgport);
+ p->p_msgport = MACH_PORT_NULL;
+
prociterate ((void (*) (struct proc *, void *))check_message_dying, p);
/* Nuke external send rights and the (possible) associated reference */
@@ -672,7 +707,7 @@ complete_exit (struct proc *p)
other references that ever show up are those for RPC args, which
will shortly vanish (because we are p_dead, those routines do
nothing). */
- ports_port_deref (p);
+ ports_port_deref (p);
}
/* Get the list of all tasks from the kernel and start adding them.