From patchwork Sun Mar 1 17:29:47 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 5390 Received: (qmail 77854 invoked by alias); 2 Mar 2015 08:40:29 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 77709 invoked by uid 89); 2 Mar 2015 08:40:28 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL, BAYES_00, DATE_IN_PAST_12_24, SPF_HELO_PASS, T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Message-Id: In-Reply-To: References: From: Florian Weimer Date: Sun, 1 Mar 2015 18:29:47 +0100 Subject: [PATCH 03/25] nscd restart: Use malloc instead of extend_alloca To: libc-alpha@sourceware.org This introduces a separate function, read_cmdline, which reads the contents of /proc/self/cmdline into a heap-allocated buffer. --- nscd/connections.c | 99 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 38 deletions(-) diff --git a/nscd/connections.c b/nscd/connections.c index 985eab6..e85f296 100644 --- a/nscd/connections.c +++ b/nscd/connections.c @@ -1382,64 +1382,83 @@ request from '%s' [%ld] not handled due to missing permission"), } } - -/* Restart the process. */ -static void -restart (void) +static char * +read_cmdline (size_t *size) { - /* First determine the parameters. We do not use the parameters - passed to main() since in case nscd is started by running the - dynamic linker this will not work. Yes, this is not the usual - case but nscd is part of glibc and we occasionally do this. */ - size_t buflen = 1024; - char *buf = alloca (buflen); - size_t readlen = 0; int fd = open ("/proc/self/cmdline", O_RDONLY); - if (fd == -1) + if (fd < 0) + return NULL; + size_t current = 0; + size_t limit = 1024; + char *buffer = malloc (limit); + if (buffer == NULL) { - dbg_log (_("\ -cannot open /proc/self/cmdline: %s; disabling paranoia mode"), - strerror (errno)); - - paranoia = 0; - return; + close (fd); + errno = ENOMEM; + return NULL; } - while (1) { - ssize_t n = TEMP_FAILURE_RETRY (read (fd, buf + readlen, - buflen - readlen)); - if (n == -1) + if (current == limit) { - dbg_log (_("\ -cannot read /proc/self/cmdline: %s; disabling paranoia mode"), - strerror (errno)); + char *newptr; + if (2 * limit < limit + || (newptr = realloc (buffer, 2 * limit)) == NULL) + { + free (buffer); + close (fd); + errno = ENOMEM; + return NULL; + } + buffer = newptr; + limit *= 2; + } + ssize_t n = TEMP_FAILURE_RETRY (read (fd, buffer + current, + limit - current)); + if (n == -1) + { + int e = errno; + free (buffer); close (fd); - paranoia = 0; - return; + errno = e; + return NULL; } - - readlen += n; - - if (readlen < buflen) + if (n == 0) break; - - /* We might have to extend the buffer. */ - size_t old_buflen = buflen; - char *newp = extend_alloca (buf, buflen, 2 * buflen); - buf = memmove (newp, buf, old_buflen); + current += n; } close (fd); + *size = current; + return buffer; +} + + +/* Restart the process. */ +static void +restart (void) +{ + /* First determine the parameters. We do not use the parameters + passed to main() because then nscd would would use the system + libc after restarting even if it was started by a non-system + dynamic linker during glibc testing. */ + size_t readlen; + char *cmdline = read_cmdline (&readlen); + if (cmdline == NULL) + { + dbg_log (_("\ +cannot open /proc/self/cmdline: %m; disabling paranoia mode")); + paranoia = 0; + return; + } /* Parse the command line. Worst case scenario: every two characters form one parameter (one character plus NUL). */ char **argv = alloca ((readlen / 2 + 1) * sizeof (argv[0])); int argc = 0; - char *cp = buf; - while (cp < buf + readlen) + for (char *cp = cmdline; cp < cmdline + readlen;) { argv[argc++] = cp; cp = (char *) rawmemchr (cp, '\0') + 1; @@ -1456,6 +1475,7 @@ cannot change to old UID: %s; disabling paranoia mode"), strerror (errno)); paranoia = 0; + free (cmdline); return; } @@ -1467,6 +1487,7 @@ cannot change to old GID: %s; disabling paranoia mode"), ignore_value (setuid (server_uid)); paranoia = 0; + free (cmdline); return; } } @@ -1484,6 +1505,7 @@ cannot change to old working directory: %s; disabling paranoia mode"), ignore_value (setgid (server_gid)); } paranoia = 0; + free (cmdline); return; } @@ -1532,6 +1554,7 @@ cannot change to old working directory: %s; disabling paranoia mode"), dbg_log (_("cannot change current working directory to \"/\": %s"), strerror (errno)); paranoia = 0; + free (cmdline); /* Reenable the databases. */ time_t now = time (NULL);