aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--exec/exec.c7
-rw-r--r--hurd/process.defs20
-rw-r--r--hurd/process_reply.defs3
-rw-r--r--hurd/process_request.defs12
-rw-r--r--libfshelp/start-translator-long.c16
-rw-r--r--libshouldbeinlibc/exec-reauth.c32
-rw-r--r--proc/mgt.c136
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;
}
diff --git a/proc/mgt.c b/proc/mgt.c
index 036ddb28..29ef05f9 100644
--- a/proc/mgt.c
+++ b/proc/mgt.c
@@ -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,