[patch] Fix BZ #18660 -- overflow in getusershell

Paul Pluzhnikov ppluzhnikov@gmail.com
Tue Aug 18 23:54:00 GMT 2015


On Mon, Aug 17, 2015 at 3:59 AM, Joseph Myers <joseph@codesourcery.com> wrote:
> Since you're increasing an allocation size, don't you also need to adjust
> the check a few lines earlier for whether the allocation size calculation
> would overflow?

Thanks. Revised patch attached.

2015-08-15  Paul Pluzhnikov  <ppluzhnikov@google.com>
            Tobias Stoeckmann <tobias@stoeckmann.org>

        [BZ #18660]
        * misc/getusershell.c (initshells): Fix possible overflow.

-- 
Paul Pluzhnikov
-------------- next part --------------
diff --git a/misc/getusershell.c b/misc/getusershell.c
index fc2c43b..a5d861e 100644
--- a/misc/getusershell.c
+++ b/misc/getusershell.c
@@ -31,6 +31,7 @@
 static char sccsid[] = "@(#)getusershell.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 
+#include <assert.h>
 #include <sys/param.h>
 #include <sys/file.h>
 #include <sys/stat.h>
@@ -99,6 +100,7 @@ initshells (void)
 	FILE *fp;
 	struct stat64 statb;
 	size_t flen;
+	off64_t max_shells;
 
 	free(shells);
 	shells = NULL;
@@ -114,12 +116,13 @@ initshells (void)
 		okshells[1] = _PATH_CSHELL;
 		return (char **) okshells;
 	}
-	if (statb.st_size > ~(size_t)0 / sizeof (char *) * 3)
+	max_shells = (statb.st_size / 3) + 2;
+	if (max_shells > ~(size_t)0 / sizeof (char *))
 		goto init_okshells;
 	flen = statb.st_size + 3;
 	if ((strings = malloc(flen)) == NULL)
 		goto init_okshells;
-	shells = malloc(statb.st_size / 3 * sizeof (char *));
+	shells = malloc(max_shells * sizeof (char *));
 	if (shells == NULL) {
 		free(strings);
 		strings = NULL;
@@ -130,13 +133,16 @@ initshells (void)
 	while (fgets_unlocked(cp, flen - (cp - strings), fp) != NULL) {
 		while (*cp != '#' && *cp != '/' && *cp != '\0')
 			cp++;
-		if (*cp == '#' || *cp == '\0' || cp[1] == '\0')
+		/* Reject non-absolute paths, or anything too short.  */
+		if (cp[0] != '/' || cp[1] == '\0' || isspace(cp[1]))
 			continue;
 		*sp++ = cp;
 		while (!isspace(*cp) && *cp != '#' && *cp != '\0')
 			cp++;
+		assert (cp < strings + flen);
 		*cp++ = '\0';
 	}
+	assert (sp < shells + max_shells);
 	*sp = NULL;
 	(void)fclose(fp);
 	return (shells);


More information about the Libc-alpha mailing list