aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Bugaev <bugaevc@gmail.com>2021-05-29 17:50:52 +0300
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2022-08-10 22:15:02 +0200
commitfb59c57316054d84f64d3bd35072ac92d51f9419 (patch)
tree9c91f60dfe3fed441975898e6a95fc02dceb9aab
parent008a7e92c54c2f71f282527241d18875be61ecf3 (diff)
downloadhurd-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.defs11
-rw-r--r--hurd/process_reply.defs4
-rw-r--r--hurd/process_request.defs4
-rw-r--r--proc/mgt.c137
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
diff --git a/proc/mgt.c b/proc/mgt.c
index bf82cd7f..68c19ea1 100644
--- a/proc/mgt.c
+++ b/proc/mgt.c
@@ -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,