From 31858894c49d469c1942f8ce2622d74de107f785 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Tue, 4 Feb 2014 06:22:19 -0700 Subject: [PATCH] When the closefrom limit is greater than any of the preserved fds, the pfds list will be non-empty but lastfd will be -1 triggering an ecalloc(0) assertion. Instead, test for lastfd being -1 and make sure we always update it, even if dup() fails. Also restore initial value of lowfd after we are done relocating. Fixes bug #633 --- src/preserve_fds.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/preserve_fds.c b/src/preserve_fds.c index d5c1fce7d..587fb88c3 100644 --- a/src/preserve_fds.c +++ b/src/preserve_fds.c @@ -111,12 +111,15 @@ closefrom_except(int startfd, struct preserved_fd_list *pfds) if (pfd->highfd < startfd) continue; fd = dup(pfd->highfd); - if (fd < pfd->highfd) { - if (fd == -1) { - if (errno == EBADF) - TAILQ_REMOVE(pfds, pfd, entries); + if (fd == -1) { + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, + "dup %d", pfd->highfd); + if (errno == EBADF) { + TAILQ_REMOVE(pfds, pfd, entries); continue; } + /* NOTE: still need to adjust lastfd below with unchanged lowfd. */ + } else if (fd < pfd->highfd) { pfd->lowfd = fd; fd = pfd->highfd; if (fd == debug_fd) @@ -124,13 +127,14 @@ closefrom_except(int startfd, struct preserved_fd_list *pfds) sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, "dup %d -> %d", pfd->highfd, pfd->lowfd); } - (void) close(fd); + if (fd != -1) + (void) close(fd); if (pfd->lowfd > lastfd) lastfd = pfd->lowfd; /* highest (relocated) preserved fd */ } - if (TAILQ_EMPTY(pfds)) { + if (lastfd == -1) { /* No fds to preserve. */ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, "closefrom(%d)", startfd); @@ -146,7 +150,6 @@ closefrom_except(int startfd, struct preserved_fd_list *pfds) /* * Close any unpreserved fds [startfd,lastfd] - * NOTE: this could relocate the debug fd, breaking the debug subsystem. */ for (fd = startfd; fd <= lastfd; fd++) { if (!FD_ISSET(fd, fdsp)) { @@ -189,6 +192,7 @@ closefrom_except(int startfd, struct preserved_fd_list *pfds) if (pfd->lowfd == debug_fd) debug_fd = sudo_debug_fd_set(pfd->highfd); (void) close(pfd->lowfd); + pfd->lowfd = pfd->highfd; } } debug_return; -- 2.40.0