From a179160d41424813a2cf07ab554180804ae14fdf Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 2 Jan 2022 01:23:27 +0100 Subject: 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. --- utils/login.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'utils/login.c') 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 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); -- cgit v1.2.3