diff options
-rw-r--r-- | proc/mgt.c | 173 |
1 files changed, 97 insertions, 76 deletions
@@ -1,5 +1,5 @@ /* Process management - Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. This file is part of the GNU Hurd. @@ -8,7 +8,7 @@ it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. -The GNU Hurd is distributed in the hope that it will be useful, +The GNU Hurd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -37,22 +37,21 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ourmsg_U.h" #include "proc_exc_S.h" #include "proc_exc_U.h" -#include "proc_excrepl_U.h" -#include "proc_excrepl_S.h" +#include <hurd/signal.h> /* Create a new id structure with the given genuine uids and gids. */ static inline struct ids * make_ids (uid_t *uids, int nuids, uid_t *gids, int ngids) { struct ids *i; - + i = malloc (sizeof (struct ids)); i->i_nuids = nuids; i->i_ngids = ngids; i->i_uids = malloc (sizeof (uid_t) * nuids); i->i_gids = malloc (sizeof (uid_t) * ngids); i->i_refcnt = 1; - + memcpy (i->i_uids, uids, sizeof (uid_t) * nuids); memcpy (i->i_gids, gids, sizeof (uid_t) * ngids); return i; @@ -87,17 +86,17 @@ S_proc_reauthenticate (struct proc *p, mach_port_t rendport) uid_t gubuf[50], aubuf[50], ggbuf[50], agbuf[50]; uid_t *gen_uids, *aux_uids, *gen_gids, *aux_gids; u_int ngen_uids, naux_uids, ngen_gids, naux_gids; - + gen_uids = gubuf; aux_uids = aubuf; gen_gids = ggbuf; aux_gids = agbuf; - + ngen_uids = naux_uids = 50; ngen_gids = naux_gids = 50; - err = auth_server_authenticate (authserver, p->p_reqport, - MACH_MSG_TYPE_MAKE_SEND, + err = auth_server_authenticate (authserver, p->p_reqport, + MACH_MSG_TYPE_MAKE_SEND, rendport, MACH_MSG_TYPE_MOVE_SEND, MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND, &gen_uids, &ngen_uids, @@ -110,7 +109,7 @@ S_proc_reauthenticate (struct proc *p, mach_port_t rendport) if (!--p->p_id->i_refcnt) free_ids (p->p_id); p->p_id = make_ids (gen_uids, ngen_uids, gen_gids, ngen_gids); - + if (gen_uids != gubuf) vm_deallocate (mach_task_self (), (u_int) gen_uids, ngen_uids * sizeof (uid_t)); @@ -136,10 +135,10 @@ S_proc_child (struct proc *parentp, if (!childp) return ESRCH; - + if (childp->p_parentset) return EBUSY; - + /* Process identification. Leave p_task and p_pid alone; all the rest comes from the new parent. */ @@ -157,14 +156,14 @@ S_proc_child (struct proc *parentp, childp->p_id = parentp->p_id; childp->p_id->i_refcnt++; - /* Process hierarchy. Remove from our current location + /* Process hierarchy. Remove from our current location and place us under our new parent. Sanity check to make sure parent is currently init. */ assert (childp->p_parent == startup_proc); if (childp->p_sib) childp->p_sib->p_prevsib = childp->p_prevsib; *childp->p_prevsib = childp->p_sib; - + childp->p_parent = parentp; childp->p_sib = parentp->p_ochild; childp->p_prevsib = &parentp->p_ochild; @@ -172,7 +171,7 @@ S_proc_child (struct proc *parentp, parentp->p_ochild->p_prevsib = &childp->p_sib; parentp->p_ochild = childp; - /* Process group structure. */ + /* Process group structure. */ if (childp->p_pgrp != parentp->p_pgrp) { leave_pgrp (childp); @@ -182,7 +181,7 @@ S_proc_child (struct proc *parentp, it for us. */ } else if (childp->p_msgport != MACH_PORT_NULL) - nowait_msg_proc_newids (childp->p_msgport, childp->p_task, + nowait_msg_proc_newids (childp->p_msgport, childp->p_task, childp->p_parent->p_pid, childp->p_pgrp->pg_pgid, !childp->p_pgrp->pg_orphcnt); childp->p_parentset = 1; @@ -199,7 +198,7 @@ S_proc_reassign (struct proc *p, if (!stubp) return ESRCH; - + if (stubp == p) return EINVAL; @@ -209,7 +208,7 @@ 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 + /* For security, we need use the request port from STUBP, and not inherit this state. */ mach_port_mod_refs (mach_task_self (), p->p_reqport, MACH_PORT_RIGHT_RECEIVE, -1); @@ -240,7 +239,7 @@ S_proc_reassign (struct proc *p, /* Destroy stubp */ stubp->p_task = 0; /* block deallocation */ process_has_exited (stubp); - + add_proc_to_hash (p); return 0; @@ -253,7 +252,7 @@ S_proc_setowner (struct proc *p, { if (! check_uid (p, owner)) return EPERM; - + p->p_owner = owner; p->p_noowner = 0; return 0; @@ -338,7 +337,7 @@ S_proc_handle_exceptions (struct proc *p, struct exc *e = malloc (sizeof (struct exc) + (statecnt * sizeof (natural_t))); mach_port_t foo; - + mach_port_request_notification (mach_task_self (), msgport, MACH_NOTIFY_NO_SENDERS, 1, msgport, MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo); @@ -348,7 +347,6 @@ S_proc_handle_exceptions (struct proc *p, mach_port_move_member (mach_task_self (), msgport, request_portset); e->excport = msgport; e->forwardport = forwardport; - e->replyport = MACH_PORT_NULL; e->flavor = flavor; e->statecnt = statecnt; bcopy (new_state, e->thread_state, statecnt * sizeof (natural_t)); @@ -362,41 +360,64 @@ S_proc_handle_exceptions (struct proc *p, kern_return_t S_proc_exception_raise (mach_port_t excport, mach_port_t reply, - mach_msg_type_name_t replyname, + mach_msg_type_name_t reply_type, mach_port_t thread, mach_port_t task, int exception, int code, int subcode) { + error_t err; + struct proc *p; struct exc *e = exc_find (excport); if (!e) return EOPNOTSUPP; - if (e->replyport != MACH_PORT_NULL) - return EBUSY; /* This is wrong, but too much trouble to fix now */ - thread_set_state (thread, e->flavor, e->thread_state, e->statecnt); - proc_exception_raise (e->forwardport, e->excport, - MACH_MSG_TYPE_MAKE_SEND_ONCE, - thread, task, exception, code, subcode); + + p = task_find (task); + if (! p) + /* Bogus RPC. */ + return EINVAL; + + /* Try to forward the message. */ + err = proc_exception_raise (e->forwardport, + reply, reply_type, MACH_SEND_NOTIFY, + thread, task, exception, code, subcode); mach_port_deallocate (mach_task_self (), thread); mach_port_deallocate (mach_task_self (), task); - return MIG_NO_REPLY; -} -/* Called by proc_handle_exception clients after they have received - the exception_raise we send in S_proc_exception_raise. Reply to - the agent that generated the exception raise. */ -kern_return_t -S_proc_exception_raise_reply (mach_port_t excport, - int replycode) -{ - struct exc *e = exc_find (excport); - if (!e) - return EOPNOTSUPP; - if (e->replyport == MACH_PORT_NULL) - return 0; - proc_exception_raise_reply (e->replyport, e->replyporttype, replycode); - return MIG_NO_REPLY; + switch (err) + { + int signo, error; + long int sigcode; + + case 0: + /* We have successfully forwarded the exception message. Now reset + the faulting thread's state to run its recovery code, which should + dequeue that message. */ + err = thread_set_state (thread, e->flavor, e->thread_state, e->statecnt); + return MIG_NO_REPLY; + + default: + /* Some unexpected error in forwarding the message. */ + /* FALLTHROUGH */ + + case MACH_SEND_INVALID_NOTIFY: + /* The port's queue is full, meaning the thread didn't receive + the exception message we forwarded last time it faulted. + Declare that signal thread hopeless and the task crashed. */ + + /* Translate the exception code into a signal number + and mark the process has dying that way. */ + _hurd_exception2signal (exception, code, subcode, + &signo, &sigcode, &error); + p->p_exiting = 1; + p->p_status = W_EXITCODE (0, signo); + + /* Nuke the task; we will get a notification message and report it + died with SIGNO. */ + task_terminate (task); + return 0; + } } /* Implement proc_getallpids as described in <hurd/proc.defs>. */ @@ -407,7 +428,7 @@ S_proc_getallpids (struct proc *p, { int nprocs; pid_t *loc; - + void count_up (struct proc *p, void *counter) { ++*(int *)counter; @@ -418,7 +439,7 @@ S_proc_getallpids (struct proc *p, } add_tasks (0); - + nprocs = 0; prociterate (count_up, &nprocs); @@ -440,12 +461,12 @@ new_proc (task_t task) { struct proc *p; mach_port_t foo; - + /* Because these have a reference count of one before starting, they can never be freed, so we're safe. */ static struct login *nulllogin; static struct ids nullids = {0, 0, 0, 0, 1}; - + if (!nulllogin) { nulllogin = malloc (sizeof (struct login) + 7); @@ -460,7 +481,7 @@ new_proc (task_t task) p = malloc (sizeof (struct proc)); mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &p->p_reqport); - mach_port_move_member (mach_task_self (), p->p_reqport, + mach_port_move_member (mach_task_self (), p->p_reqport, request_portset); p->p_pid = genpid (); @@ -470,8 +491,8 @@ new_proc (task_t task) MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo); if (foo != MACH_PORT_NULL) mach_port_deallocate (mach_task_self (), foo); - - + + switch (p->p_pid) { case 0: @@ -479,7 +500,7 @@ new_proc (task_t task) p->p_login->l_refcnt = 1; strcpy (p->p_login->l_name, "root"); break; - + case 1: p->p_login = self_proc->p_login; p->p_login->l_refcnt++; @@ -489,9 +510,9 @@ new_proc (task_t task) p->p_login = nulllogin; p->p_login->l_refcnt++; } - + p->p_owner = 0; - + if (p->p_pid == 0) { uid_t foo = 0; @@ -538,16 +559,16 @@ new_proc (task_t task) p->p_parentset = 0; p->p_noowner = 1; } - + if (p->p_pid < 2) boot_setsid (p); else p->p_pgrp = startup_proc->p_pgrp; - + p->p_msgport = MACH_PORT_NULL; - + p->p_argv = p->p_envp = p->p_status = 0; - + p->p_exec = 0; p->p_stopped = 0; p->p_waited = 0; @@ -576,26 +597,26 @@ process_has_exited (struct proc *p) alert_parent (p); prociterate ((void (*) (struct proc *, void *))check_message_dying, p); - - mach_port_mod_refs (mach_task_self (), p->p_reqport, + + mach_port_mod_refs (mach_task_self (), p->p_reqport, MACH_PORT_RIGHT_RECEIVE, -1); remove_proc_from_hash (p); - + mach_port_deallocate (mach_task_self (), p->p_task); if (!--p->p_login->l_refcnt) free (p->p_login); - + if (!--p->p_id->i_refcnt) free_ids (p->p_id); - - /* Reparent our children to init by attaching the head and tail + + /* Reparent our children to init by attaching the head and tail of our list onto init's. */ if (p->p_ochild) { struct proc *tp; /* will point to the last one */ - + /* first tell them their parent is changing */ for (tp = p->p_ochild; tp->p_sib; tp = tp->p_sib) { @@ -620,23 +641,23 @@ process_has_exited (struct proc *p) } reparent_zombies (p); - + /* Remove us from our parent's list of children. */ if (p->p_sib) p->p_sib->p_prevsib = p->p_prevsib; *p->p_prevsib = p->p_sib; - + leave_pgrp (p); - + mach_port_deallocate (mach_task_self (), p->p_msgport); - + if (p->p_waiting) - mach_port_deallocate (mach_task_self (), + mach_port_deallocate (mach_task_self (), p->p_continuation.wait_c.reply_port); if (p->p_msgportwait) mach_port_deallocate (mach_task_self (), p->p_continuation.getmsgport_c.reply_port); - + free (p); } @@ -687,18 +708,18 @@ add_tasks (task_t task) } mach_port_deallocate (mach_task_self (), psets[i]); } - vm_deallocate (mach_host_self (), (vm_address_t) psets, + vm_deallocate (mach_host_self (), (vm_address_t) psets, npsets * sizeof (mach_port_t)); return foundp; } /* Allocate a new pid. The first two times this is called it must return - 0 and 1 in order; after that it must simply return an unused pid. + 0 and 1 in order; after that it must simply return an unused pid. (Unused means it is neither the pid nor pgrp of any relevant data.) */ int genpid () { -#define WRAP_AROUND 30000 +#define WRAP_AROUND 30000 #define START_OVER 100 static int nextpid = 0; static int wrap = WRAP_AROUND; |