diff options
author | Sergey Bugaev <bugaevc@gmail.com> | 2021-05-29 17:50:52 +0300 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2022-08-10 22:15:02 +0200 |
commit | fb59c57316054d84f64d3bd35072ac92d51f9419 (patch) | |
tree | 9c91f60dfe3fed441975898e6a95fc02dceb9aab | |
parent | 008a7e92c54c2f71f282527241d18875be61ecf3 (diff) | |
download | hurd-fb59c57316054d84f64d3bd35072ac92d51f9419.tar.gz hurd-fb59c57316054d84f64d3bd35072ac92d51f9419.tar.bz2 hurd-fb59c57316054d84f64d3bd35072ac92d51f9419.zip |
proc: Add proc_reauthenticate_reassign ()
This is a new RPC to atomically change the UIDs of a process, recreate its
process port, and reassign a different task to it.
-rw-r--r-- | hurd/process.defs | 11 | ||||
-rw-r--r-- | hurd/process_reply.defs | 4 | ||||
-rw-r--r-- | hurd/process_request.defs | 4 | ||||
-rw-r--r-- | proc/mgt.c | 137 |
4 files changed, 153 insertions, 3 deletions
diff --git a/hurd/process.defs b/hurd/process.defs index 3b091290..83bf6561 100644 --- a/hurd/process.defs +++ b/hurd/process.defs @@ -1,5 +1,5 @@ /* Definitions for process server interface - Copyright (C) 1992,93,94,95,96,97,2001,13,14 Free Software Foundation + Copyright (C) 1992,93,94,95,96,97,2001,13,14,21 Free Software Foundation This file is part of the GNU Hurd. @@ -451,3 +451,12 @@ routine proc_waitid ( out sigcode: int; out rusage: rusage_t; out pid_status: pid_t); + +/* Change the current authentication of the process and assign a different + task to it, atomically. The user should follow this call with a call to + auth_user_authenticate. The new_port passed back through the auth server + will be the new proc port. The old proc port is destroyed. */ +simpleroutine proc_reauthenticate_reassign ( + old_process: process_t; + rendezvous: mach_port_send_t; + new_task: task_t); diff --git a/hurd/process_reply.defs b/hurd/process_reply.defs index 4a79024c..e37db425 100644 --- a/hurd/process_reply.defs +++ b/hurd/process_reply.defs @@ -1,5 +1,5 @@ /* Reply half of wait - Copyright (C) 1991,93,94,96,2001,13 Free Software Foundation, Inc. + Copyright (C) 1991,93,94,96,2001,13,21 Free Software Foundation, Inc. This file is part of the GNU Hurd. @@ -202,3 +202,5 @@ skip; /* proc_set_entry */ skip; /* proc_get_entry */ skip; /* proc_waitid */ + +skip; /* proc_reauthenticate_reassign */
\ No newline at end of file diff --git a/hurd/process_request.defs b/hurd/process_request.defs index f200bf15..882e8366 100644 --- a/hurd/process_request.defs +++ b/hurd/process_request.defs @@ -1,6 +1,6 @@ /* Definitions for process server interface (request-only version) - Copyright (C) 1992, 93, 94, 95, 96, 98, 2013 Free Software Foundation, Inc. + Copyright (C) 1992, 93, 94, 95, 96, 98, 2013, 21 Free Software Foundation, Inc. This file is part of the GNU Hurd. @@ -425,3 +425,5 @@ skip; /* proc_set_entry */ skip; /* proc_get_entry */ skip; /* proc_waitid */ + +skip; /* proc_reauthenticate_reassign */
\ No newline at end of file @@ -295,6 +295,143 @@ S_proc_reassign (struct proc *p, return 0; } +/* Implement proc_reauthenticate_reassign + as described in <hurd/process.defs>. */ +kern_return_t +S_proc_reauthenticate_reassign (struct proc *p, + mach_port_t rendezvous, + task_t new_task) +{ + error_t err; + mach_port_t new_proc_port; + struct proc *stubp; + struct ids *new_ids; + uid_t gubuf[50], aubuf[50], ggbuf[50], agbuf[50]; + uid_t *gen_uids, *aux_uids, *gen_gids, *aux_gids; + size_t ngen_uids, naux_uids, ngen_gids, naux_gids; + + if (!p) + return EOPNOTSUPP; + + if (!MACH_PORT_VALID (rendezvous)) + return EINVAL; + + stubp = task_find (new_task); + if (!stubp) + return ESRCH; + if (stubp == p) + return EINVAL; + ports_port_ref (stubp); + + gen_uids = gubuf; + aux_uids = aubuf; + gen_gids = ggbuf; + aux_gids = agbuf; + + ngen_uids = sizeof (gubuf) / sizeof (uid_t); + naux_uids = sizeof (aubuf) / sizeof (uid_t); + ngen_gids = sizeof (ggbuf) / sizeof (uid_t); + naux_gids = sizeof (agbuf) / sizeof (uid_t); + + new_proc_port = mach_reply_port (); + + /* Communicate with the auth server before doing + *any changes* to these two processes. */ + + /* Release the lock while talking to the auth server. */ + pthread_mutex_unlock (&global_lock); + do + err = auth_server_authenticate (authserver, + rendezvous, + MACH_MSG_TYPE_COPY_SEND, + new_proc_port, + MACH_MSG_TYPE_MAKE_SEND, + &gen_uids, &ngen_uids, + &aux_uids, &naux_uids, + &gen_gids, &ngen_gids, + &aux_gids, &naux_gids); + while (err == EINTR && !p->p_dead && !stubp->p_dead); + pthread_mutex_lock (&global_lock); + + if (err) + { + mach_port_mod_refs (mach_task_self (), new_proc_port, + MACH_PORT_RIGHT_RECEIVE, -1); + ports_port_deref (stubp); + return err; + } + + /* If any task has died, or the process referring to the new task + has itself been reassigned in the meantime, abort. */ + if (p->p_dead || stubp->p_dead || stubp->p_task != new_task) + { + err = EAGAIN; + goto out; + } + + /* Copy in the new ids. */ + new_ids = make_ids (gen_uids, ngen_uids, aux_uids, naux_uids); + if (!new_ids) + { + err = errno; + goto out; + } + ids_rele (p->p_id); + p->p_id = new_ids; + + /* From here on, nothing can go wrong. */ + + mach_port_deallocate (mach_task_self (), new_task); + mach_port_deallocate (mach_task_self (), rendezvous); + + remove_proc_from_hash (p); + + task_terminate (p->p_task); + mach_port_deallocate (mach_task_self (), p->p_task); + + p->p_task = stubp->p_task; + stubp->p_task = MACH_PORT_NULL; + ports_destroy_right (stubp); + ports_reallocate_from_external (p, new_proc_port); + + if (MACH_PORT_VALID (p->p_msgport)) + { + mach_port_deallocate (mach_task_self (), p->p_msgport); + p->p_msgport = MACH_PORT_NULL; + p->p_deadmsg = 1; + } + + /* These two are image dependent. */ + p->p_argv = stubp->p_argv; + p->p_envp = stubp->p_envp; + + /* Destroy stubp. */ + process_has_exited (stubp); + stubp->p_waited = 1; /* fake out complete_exit */ + complete_exit (stubp); + + add_proc_to_hash (p); + err = 0; + + out: + if (gen_uids != gubuf) + munmap (gen_uids, ngen_uids * sizeof (uid_t)); + if (aux_uids != aubuf) + munmap (aux_uids, naux_uids * sizeof (uid_t)); + if (gen_gids != ggbuf) + munmap (gen_gids, ngen_gids * sizeof (uid_t)); + if (aux_gids != agbuf) + munmap (aux_gids, naux_gids * sizeof (uid_t)); + + if (err) + mach_port_mod_refs (mach_task_self (), new_proc_port, + MACH_PORT_RIGHT_RECEIVE, -1); + + ports_port_deref (stubp); + + return err; +} + /* Implement proc_setowner as described in <hurd/process.defs>. */ kern_return_t S_proc_setowner (struct proc *p, |