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 | |
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 ()
-rw-r--r-- | exec/exec.c | 7 | ||||
-rw-r--r-- | hurd/process.defs | 20 | ||||
-rw-r--r-- | hurd/process_reply.defs | 3 | ||||
-rw-r--r-- | hurd/process_request.defs | 12 | ||||
-rw-r--r-- | libfshelp/start-translator-long.c | 16 | ||||
-rw-r--r-- | libshouldbeinlibc/exec-reauth.c | 32 | ||||
-rw-r--r-- | proc/mgt.c | 136 |
7 files changed, 167 insertions, 59 deletions
diff --git a/exec/exec.c b/exec/exec.c index 43760321..27d8abdf 100644 --- a/exec/exec.c +++ b/exec/exec.c @@ -1400,6 +1400,13 @@ do_exec (file_t file, if (e.error) goto out; + e.error = proc_complete_reauthentication (newproc); + if (e.error) + { + mach_port_deallocate (mach_task_self (), newproc); + goto out; + } + assert_backtrace (ports_replaced[INIT_PORT_PROC]); mach_port_deallocate (mach_task_self (), boot->portarray[INIT_PORT_PROC]); diff --git a/hurd/process.defs b/hurd/process.defs index 416ec30f..cb17e631 100644 --- a/hurd/process.defs +++ b/hurd/process.defs @@ -86,12 +86,13 @@ routine proc_register_version ( a new process, just create a new task and use proc_task2proc. */ /* Change the current authentication of the process. The user should - follow this call with a call to auth_user_authenticate. The - new_port passed back through the auth server will be - MACH_PORT_NULL. */ + follow this call with a call to auth_user_authenticate, and then a + call to proc_complete_reauthentication on the port passed back + through the auth server, which becomes the new port for this process. + The old process port is destroyed. */ simpleroutine proc_reauthenticate ( process: process_t; - rendezvous2: mach_port_send_t); + rendezvous: mach_port_send_t); /* Declare that a task is a child of the caller. The task's state will then inherit from the caller. This call can be made only once @@ -452,9 +453,16 @@ routine proc_waitid ( /* 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. */ + auth_user_authenticate, and then a call to proc_complete_reauthentication + on the port passed back through the auth server, which becomes the new + port for this process. The old process port is destroyed. */ simpleroutine proc_reauthenticate_reassign ( old_process: process_t; rendezvous: mach_port_send_t; new_task: task_t); + +/* Complete reauthentication started with proc_reauthenticate or + proc_reauthenticate_reassign. The process port must be the port + that the user has received from auth_user_authenticate call. */ +simpleroutine proc_complete_reauthentication ( + process: process_t); diff --git a/hurd/process_reply.defs b/hurd/process_reply.defs index 4775c7c6..f0952ff9 100644 --- a/hurd/process_reply.defs +++ b/hurd/process_reply.defs @@ -203,4 +203,5 @@ skip; /* proc_get_entry */ skip; /* proc_waitid */ -skip; /* proc_reauthenticate_reassign */
\ No newline at end of file +skip; /* proc_reauthenticate_reassign */ +skip; /* proc_complete_reauthentication */ diff --git a/hurd/process_request.defs b/hurd/process_request.defs index 295a05bb..3401a2cb 100644 --- a/hurd/process_request.defs +++ b/hurd/process_request.defs @@ -86,13 +86,14 @@ simpleroutine proc_register_version_request ( a new process, just create a new task and use proc_task2proc. */ /* Change the current authentication of the process. The user should - follow this call with a call to auth_user_authenticate. The - new_port passed back through the auth server will be - MACH_PORT_NULL. */ + follow this call with a call to auth_user_authenticate, and then a + call to proc_complete_reauthentication on the port passed back + through the auth server, which becomes the new port for this process. + The old process port is destroyed. */ simpleroutine proc_reauthenticate_request ( process: process_t; ureplyport reply: reply_port_t; - rendezvous2: mach_port_send_t); + rendezvous: mach_port_send_t); /* Declare that a task is a child of the caller. The task's state will then inherit from the caller. This call can be made only once @@ -420,4 +421,5 @@ skip; /* proc_get_entry */ skip; /* proc_waitid */ -skip; /* proc_reauthenticate_reassign */
\ No newline at end of file +skip; /* proc_reauthenticate_reassign */ +skip; /* proc_complete_reauthentication */ diff --git a/libfshelp/start-translator-long.c b/libfshelp/start-translator-long.c index 1bbf310a..e870767f 100644 --- a/libfshelp/start-translator-long.c +++ b/libfshelp/start-translator-long.c @@ -300,10 +300,20 @@ fshelp_start_translator_long (fshelp_open_fn_t underlying_open_fn, mach_port_mod_refs (mach_task_self (), rend, MACH_PORT_RIGHT_RECEIVE, -1); - } - if (err) - goto lose_task; + if (err) + goto lose_task; + + err = proc_complete_reauthentication (newport); + if (err) + { + mach_port_deallocate (mach_task_self (), newport); + goto lose_task; + } + + mach_port_deallocate (mach_task_self (), ports[INIT_PORT_PROC]); + ports[INIT_PORT_PROC] = newport; + } saveport = ports[INIT_PORT_BOOTSTRAP]; ports[INIT_PORT_BOOTSTRAP] = bootstrap; diff --git a/libshouldbeinlibc/exec-reauth.c b/libshouldbeinlibc/exec-reauth.c index cd217e02..71e41b8b 100644 --- a/libshouldbeinlibc/exec-reauth.c +++ b/libshouldbeinlibc/exec-reauth.c @@ -60,22 +60,24 @@ exec_reauth (auth_t auth, int secure, int must_reauth, err = auth_user_authenticate (auth, ref, MACH_MSG_TYPE_MAKE_SEND, &newport); mach_port_mod_refs (mach_task_self (), ref, MACH_PORT_RIGHT_RECEIVE, -1); + /* If they gave us nothing, make sure not to proceed. */ + if (!err && newport == MACH_PORT_NULL) + err = KERN_INVALID_ARGUMENT; if (err) - { - if (must_reauth) - return err; - /* Nothing Happens. */ - } - else - { - if (isproc) - mach_port_deallocate (mach_task_self (), newport); - else - { - mach_port_deallocate (mach_task_self (), *port); - *port = newport; - } - } + return must_reauth ? err : 0; + + if (isproc) + { + err = proc_complete_reauthentication (newport); + if (err) + { + mach_port_deallocate (mach_task_self (), newport); + return must_reauth ? err : 0; + } + } + + mach_port_deallocate (mach_task_self (), *port); + *port = newport; } return 0; } @@ -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, |