diff options
author | Sergey Bugaev <bugaevc@gmail.com> | 2021-06-09 15:41:58 +0300 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2022-08-10 22:17:08 +0200 |
commit | 5710aaa670a14cbbe4da0e8fe64314a55f14a015 (patch) | |
tree | 5a76113134f56b3e481c8019684fc1300d9e5d3f /proc | |
parent | b6c6e41a0d94740f4ecce9afdafa0c17348ce4c0 (diff) | |
download | hurd-5710aaa670a14cbbe4da0e8fe64314a55f14a015.tar.gz hurd-5710aaa670a14cbbe4da0e8fe64314a55f14a015.tar.bz2 hurd-5710aaa670a14cbbe4da0e8fe64314a55f14a015.zip |
Make proc_reauthenticate () recreate proc port
And add proc_complete_reauthentication ()
Diffstat (limited to 'proc')
-rw-r--r-- | proc/mgt.c | 136 |
1 files changed, 107 insertions, 29 deletions
@@ -44,6 +44,9 @@ #include "task_notify_S.h" #include <hurd/signal.h> +extern mach_msg_return_t +mach_msg_receive (mach_msg_header_t *msg); + /* Create a new id structure with the given genuine uids. */ static inline struct ids * make_ids (const uid_t *eff_uids, size_t n_eff_uids, @@ -94,6 +97,8 @@ kern_return_t S_proc_reauthenticate (struct proc *p, mach_port_t rendport) { error_t err; + mach_port_t new_proc_port, prev; + mach_msg_header_t msg; struct ids *new_ids; uid_t gubuf[50], aubuf[50], ggbuf[50], agbuf[50]; uid_t *gen_uids, *aux_uids, *gen_gids, *aux_gids; @@ -112,38 +117,78 @@ S_proc_reauthenticate (struct proc *p, mach_port_t rendport) ngen_gids = sizeof (ggbuf) / sizeof (uid_t); naux_gids = sizeof (agbuf) / sizeof (uid_t); + new_proc_port = mach_reply_port (); + /* Ask to be told if the new port dies. We receive the notification + on the same port, and as it's not a proc_complete_reauthentication () + call, consider it an error. */ + err = mach_port_request_notification (mach_task_self (), new_proc_port, + MACH_NOTIFY_NO_SENDERS, 1, + new_proc_port, + MACH_MSG_TYPE_MAKE_SEND_ONCE, + &prev); + assert_perror_backtrace (err); + assert_backtrace (prev == MACH_PORT_NULL); + /* Release the global lock while blocking on the auth server and client. */ pthread_mutex_unlock (&global_lock); + do err = auth_server_authenticate (authserver, - rendport, MACH_MSG_TYPE_COPY_SEND, - MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND, - &gen_uids, &ngen_uids, - &aux_uids, &naux_uids, - &gen_gids, &ngen_gids, - &aux_gids, &naux_gids); + rendport, 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); + + /* Wait for a proc_complete_reauthentication () call + on the new port before proceeding. */ + if (!err) + { + msg.msgh_size = sizeof (mach_msg_header_t); + msg.msgh_local_port = new_proc_port; + err = mach_msg_receive (&msg); + } + pthread_mutex_lock (&global_lock); if (err) - return err; + goto out; + + /* Check if what we have received was indeed a + proc_complete_reauthentication () call. */ + if (msg.msgh_id != 24064) + err = EINVAL; + mach_msg_destroy (&msg); + if (err) + goto out; if (p->p_dead) - /* The process died while we had the lock released. - Its p_id field is no longer valid and we shouldn't touch it. */ - err = EAGAIN; - else { - new_ids = make_ids (gen_uids, ngen_uids, aux_uids, naux_uids); - if (!new_ids) - err = errno; - else - { - ids_rele (p->p_id); - p->p_id = new_ids; - } + /* The process died while we had the lock released. + Its p_id field is no longer valid and we shouldn't touch it. */ + err = EAGAIN; + goto out; + } + + new_ids = make_ids (gen_uids, ngen_uids, aux_uids, naux_uids); + if (!new_ids) + { + err = errno; + goto out; } + /* From here on, nothing can go wrong. */ + + mach_port_deallocate (mach_task_self (), rendport); + + ids_rele (p->p_id); + p->p_id = new_ids; + + ports_reallocate_from_external (p, new_proc_port); + + out: if (gen_uids != gubuf) munmap (gen_uids, ngen_uids * sizeof (uid_t)); if (aux_uids != aubuf) @@ -153,8 +198,9 @@ S_proc_reauthenticate (struct proc *p, mach_port_t rendport) if (aux_gids != agbuf) munmap (aux_gids, naux_gids * sizeof (uid_t)); - if (!err) - mach_port_deallocate (mach_task_self (), rendport); + if (err) + mach_port_mod_refs (mach_task_self (), new_proc_port, + MACH_PORT_RIGHT_RECEIVE, -1); return err; } @@ -300,7 +346,8 @@ S_proc_reauthenticate_reassign (struct proc *p, task_t new_task) { error_t err; - mach_port_t new_proc_port; + mach_port_t new_proc_port, prev; + mach_msg_header_t msg; struct proc *stubp; struct ids *new_ids; uid_t gubuf[50], aubuf[50], ggbuf[50], agbuf[50]; @@ -331,12 +378,23 @@ S_proc_reauthenticate_reassign (struct proc *p, naux_gids = sizeof (agbuf) / sizeof (uid_t); new_proc_port = mach_reply_port (); + /* Ask to be told if the new port dies. We receive the notification + on the same port, and as it's not a proc_complete_reauthentication () + call, consider it an error. */ + err = mach_port_request_notification (mach_task_self (), new_proc_port, + MACH_NOTIFY_NO_SENDERS, 1, + new_proc_port, + MACH_MSG_TYPE_MAKE_SEND_ONCE, + &prev); + assert_perror_backtrace (err); + assert_backtrace (prev == MACH_PORT_NULL); /* 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, @@ -347,17 +405,30 @@ S_proc_reauthenticate_reassign (struct proc *p, &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); + while (err == EINTR); - if (err) + /* Wait for a proc_complete_reauthentication () call + on the new port before proceeding. */ + if (!err) { - mach_port_mod_refs (mach_task_self (), new_proc_port, - MACH_PORT_RIGHT_RECEIVE, -1); - ports_port_deref (stubp); - return err; + msg.msgh_size = sizeof (mach_msg_header_t); + msg.msgh_local_port = new_proc_port; + err = mach_msg_receive (&msg); } + pthread_mutex_lock (&global_lock); + + if (err) + goto out; + + /* Check if what we have received was indeed a + proc_complete_reauthentication () call. */ + if (msg.msgh_id != 24064) + err = EINVAL; + mach_msg_destroy (&msg); + if (err) + goto out; + /* 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) @@ -438,6 +509,13 @@ S_proc_setowner (struct proc *p, return EOPNOTSUPP; } +kern_return_t +S_proc_complete_reauthentication (struct proc *p) +{ + /* Regular calls of this routine always fail. */ + return EOPNOTSUPP; +} + /* Implement proc_getpids as described in <hurd/process.defs>. */ kern_return_t S_proc_getpids (struct proc *p, |