diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2022-01-02 01:23:27 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2022-01-04 01:09:32 +0100 |
commit | a179160d41424813a2cf07ab554180804ae14fdf (patch) | |
tree | 1a9eaa1fc2e5f38c98f421488791614023aad0ce | |
parent | a8d51bf0ce26fd26e00338540857f43b8a99e126 (diff) | |
download | hurd-a179160d41424813a2cf07ab554180804ae14fdf.tar.gz hurd-a179160d41424813a2cf07ab554180804ae14fdf.tar.bz2 hurd-a179160d41424813a2cf07ab554180804ae14fdf.zip |
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.
-rw-r--r-- | libfshelp/fetch-root.c | 3 | ||||
-rw-r--r-- | libshouldbeinlibc/nullauth.c | 4 | ||||
-rw-r--r-- | utils/login.c | 28 | ||||
-rw-r--r-- | utils/nonsugid.c | 6 | ||||
-rw-r--r-- | utils/shd.c | 5 | ||||
-rw-r--r-- | utils/x.c | 4 |
6 files changed, 40 insertions, 10 deletions
diff --git a/libfshelp/fetch-root.c b/libfshelp/fetch-root.c index c1001bc3..f3ae0ee9 100644 --- a/libfshelp/fetch-root.c +++ b/libfshelp/fetch-root.c @@ -153,6 +153,9 @@ fshelp_fetch_root (struct transbox *box, void *cookie, if (i != INIT_PORT_CWDIR) mach_port_deallocate (mach_task_self (), ports[i]); + if (ourauth != MACH_PORT_NULL) + mach_port_deallocate (mach_task_self (), ourauth); + pthread_mutex_lock (box->lock); free (argz); diff --git a/libshouldbeinlibc/nullauth.c b/libshouldbeinlibc/nullauth.c index 3a98e558..8a19b05c 100644 --- a/libshouldbeinlibc/nullauth.c +++ b/libshouldbeinlibc/nullauth.c @@ -29,14 +29,16 @@ setnullauth (void) { error_t err; + auth_t ourauth = getauth (); auth_t nullauth; - err = auth_makeauth (getauth (), + err = auth_makeauth (ourauth, NULL, MACH_MSG_TYPE_COPY_SEND, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, &nullauth); + mach_port_deallocate (mach_task_self (), ourauth); if (err) return err; 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) { @@ -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); |