summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2022-01-02 01:23:27 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2022-01-04 01:09:32 +0100
commita179160d41424813a2cf07ab554180804ae14fdf (patch)
tree1a9eaa1fc2e5f38c98f421488791614023aad0ce /utils
parenta8d51bf0ce26fd26e00338540857f43b8a99e126 (diff)
Fix leaking auth ports
We need to be extremely careful with auth ports since leaking them into subprocesses may expose a root-auth port to non-root processes. Notably, get_nonsugid_ids was caching it, thus preventing glibc's exec implementation from dropping it. Login is also reimplementing hurdexec but without all the cloexec logic. This commit fixes various auth leaks.
Diffstat (limited to 'utils')
-rw-r--r--utils/login.c28
-rw-r--r--utils/nonsugid.c6
-rw-r--r--utils/shd.c5
-rw-r--r--utils/x.c4
4 files changed, 34 insertions, 9 deletions
diff --git a/utils/login.c b/utils/login.c
index 44bce2fd..eb0ed845 100644
--- a/utils/login.c
+++ b/utils/login.c
@@ -415,6 +415,9 @@ main(int argc, char *argv[])
mach_port_t auth; /* The new shell's authentication. */
mach_port_t proc_server = getproc ();
pid_t pid = getpid (), sid;
+ mach_port_t *please_dealloc, *pdp;
+ struct hurd_userlink ulink_ports[INIT_PORT_MAX];
+ mach_port_t port;
/* These three functions are to do child-authenticated lookups. See
<hurd/lookup.h> for an explanation. */
@@ -684,16 +687,30 @@ main(int argc, char *argv[])
else
proc_setowner (proc_server, 0, 1); /* Clear the owner. */
+ /* XXX: we should be sharing the implementation with glibc's hurdexec */
+ please_dealloc = alloca ((3 + INIT_PORT_MAX + 1) * sizeof(mach_port_t));
+ pdp = please_dealloc;
+
/* Now start constructing the exec arguments. */
memset (ints, 0, sizeof (*ints) * INIT_INT_MAX);
arg = envz_get (args, args_len, "UMASK");
ints[INIT_UMASK] = arg && *arg ? strtoul (arg, 0, 8) : umask (0);
for (i = 0; i < 3; i++)
- fds[i] = getdport (i);
+ {
+ fds[i] = getdport (i);
+ *pdp++ = fds[i];
+ }
for (i = 0; i < INIT_PORT_MAX; i++)
+ {
ports[i] = MACH_PORT_NULL;
+
+ port = _hurd_port_get (&_hurd_ports[i], &ulink_ports[i]);
+ if (port != MACH_PORT_NULL)
+ *pdp++ = port;
+ }
+
ports[INIT_PORT_PROC] = getproc ();
ports[INIT_PORT_CTTYID] = getcttyid ();
ports[INIT_PORT_CRDIR] = getcrdir (); /* May be replaced below. */
@@ -850,7 +867,10 @@ main(int argc, char *argv[])
{
mach_port_t motd_node = child_lookup (arg, 0, O_RDONLY);
if (motd_node != MACH_PORT_NULL)
- cat (motd_node, arg);
+ {
+ cat (motd_node, arg);
+ mach_port_deallocate (mach_task_self (), motd_node);
+ }
}
else
mach_port_deallocate (mach_task_self (), hush_node);
@@ -890,7 +910,7 @@ main(int argc, char *argv[])
fds, MACH_MSG_TYPE_COPY_SEND, 3,
ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
ints, INIT_INT_MAX,
- 0, 0, 0, 0);
+ please_dealloc, pdp-please_dealloc, 0, 0);
/* Fallback in case the file server hasn't been restarted. */
if (err == MIG_BAD_ID)
#endif
@@ -899,7 +919,7 @@ main(int argc, char *argv[])
fds, MACH_MSG_TYPE_COPY_SEND, 3,
ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
ints, INIT_INT_MAX,
- 0, 0, 0, 0);
+ please_dealloc, pdp-please_dealloc, 0, 0);
if (err)
error(5, err, "%s", shell);
diff --git a/utils/nonsugid.c b/utils/nonsugid.c
index 71cd3d71..15b1f777 100644
--- a/utils/nonsugid.c
+++ b/utils/nonsugid.c
@@ -32,15 +32,14 @@ get_nonsugid_ids (struct idvec *uids, struct idvec *gids)
if (uids->num == 0 && gids->num == 0)
{
error_t err = 0;
- static auth_t auth = MACH_PORT_NULL;
+ auth_t auth;
struct idvec *p_eff_uids = make_idvec ();
struct idvec *p_eff_gids = make_idvec ();
if (!p_eff_uids || !p_eff_gids)
err = ENOMEM;
- if (auth == MACH_PORT_NULL)
- auth = getauth ();
+ auth = getauth ();
if (! err)
err = idvec_merge_auth (p_eff_uids, uids, p_eff_gids, gids, auth);
@@ -55,6 +54,7 @@ get_nonsugid_ids (struct idvec *uids, struct idvec *gids)
if (! err)
err = idvec_merge (gids, p_eff_gids);
}
+ mach_port_deallocate (mach_task_self (), auth);
return err;
}
diff --git a/utils/shd.c b/utils/shd.c
index e978061c..d2075075 100644
--- a/utils/shd.c
+++ b/utils/shd.c
@@ -231,6 +231,7 @@ main (int argc, char *argv[])
{
char *linebuf = NULL;
size_t linebufsize = 0;
+ auth_t ourauth;
proc = getproc ();
assert_backtrace (proc);
@@ -252,8 +253,10 @@ main (int argc, char *argv[])
#endif
/* Kludge to give boot a port to the auth server. */
- exec_init (getdport (0), getauth (),
+ ourauth = getauth ();
+ exec_init (getdport (0), ourauth,
MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND);
+ mach_port_deallocate (mach_task_self (), ourauth);
if ((fcntl (0, F_GETFL) & O_READ) == 0)
{
diff --git a/utils/x.c b/utils/x.c
index 90671fc9..1303544d 100644
--- a/utils/x.c
+++ b/utils/x.c
@@ -237,13 +237,15 @@ main(int argc, char *argv[])
memset (remove, 0, sizeof remove);
+ auth_t ourauth = getauth ();
err =
- auth_makeauth (getauth (), 0, MACH_MSG_TYPE_COPY_SEND, 0,
+ auth_makeauth (ourauth, 0, MACH_MSG_TYPE_COPY_SEND, 0,
&auth.euids->ids, &auth.euids->num,
&auth.auids->ids, &auth.auids->num,
&auth.egids->ids, &auth.egids->num,
&auth.agids->ids, &auth.agids->num,
&auth);
+ mach_port_deallocate (mach_task_self (), ourauth);
if (err)
error (3, err, "Authentication failure", 0);