NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

bin/56358: I suspect bozo may have a core dump



>Number:         56358
>Category:       bin
>Synopsis:       I suspect bozo may have a core dump
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Aug 12 08:50:00 +0000 2021
>Originator:     parrott
>Release:        -CURRENT
>Organization:
individual
>Environment:
9.2, I downloaded httpd from HEAD
>Description:
In dir-index-bozo.c, there is a lack of error checking for the call to scandir.  If, for some reason, scandir returns -1, I believe what we would have is an out of bounds dereference of *de (that wording may not be right).

I couldn't prove this on my system, because the malloc in scandir doesn't just fail, the whole process gets killed, but perhaps other systems would be affected differently.
>How-To-Repeat:

>Fix:
Index: dir-index-bozo.c
===================================================================
RCS file: /cvsroot/src/libexec/httpd/dir-index-bozo.c,v
retrieving revision 1.34
diff -u -p -r1.34 dir-index-bozo.c
--- dir-index-bozo.c	15 Oct 2020 02:19:23 -0000	1.34
+++ dir-index-bozo.c	12 Aug 2021 08:29:38 -0000
@@ -56,7 +56,7 @@ bozo_dir_index(bozo_httpreq_t *request, 
 	bozohttpd_t *httpd = request->hr_httpd;
 	struct stat sb;
 	struct dirent **de, **deo;
-	DIR *dp;
+	//DIR *dp;
 	char buf[MAXPATHLEN];
 	char *file = NULL, *printname = NULL, *p;
 	int k, j, fd;
@@ -74,9 +74,19 @@ bozo_dir_index(bozo_httpreq_t *request, 
 		dirpath = file;
 	}
 	debug((httpd, DEBUG_FAT, "bozo_dir_index: dirpath '%s'", dirpath));
+
+	/*
+	 * Scrap opendir.  It seems to me, that it would make sense, that,
+	 * formerly, readdir was used in the loop below, but we can scandir
+	 * here (before any output is generated) and run through the results
+	 * in the loop.  Otherwise, I don't see the purpose of opendir.
+	 *
+	 * Later:  Use the select parameter to eliminate unwanted entries.
+	 */
 	if (stat(dirpath, &sb) < 0 ||
-	    (dp = opendir(dirpath)) == NULL) {
-		if (errno == EPERM)
+	    //(dp = opendir(dirpath)) == NULL) {
+	    (j = k = scandir(dirpath, &de, NULL, alphasort)) < 0) {
+		if (errno == EACCES)
 			bozo_http_error(httpd, 403, request,
 					"no permission to open directory");
 		else if (errno == ENOENT)
@@ -96,7 +106,7 @@ bozo_dir_index(bozo_httpreq_t *request, 
 	bozo_flush(httpd, stdout);
 
 	if (request->hr_method == HTTP_HEAD) {
-		closedir(dp);
+		//closedir(dp);
 		goto done;
 	}
 
@@ -113,7 +123,7 @@ bozo_dir_index(bozo_httpreq_t *request, 
 		if (strcmp(printname, httpd->index_html) == 0)
 			strcpy(printname, "/");	/* is ``slashdir'' */
 		else
-			*p = '\0';		/* strip unwanted ``index_html'' */
+			*p = '\0';	/* strip unwanted ``index_html'' */
 	}
 	if ((p = bozo_escape_html(httpd, printname)) != NULL) {
 		free(printname);
@@ -140,8 +150,7 @@ bozo_dir_index(bozo_httpreq_t *request, 
 		"<tr><th>Name<th>Last modified<th align=right>Size\r\n"
 		"<tbody>\r\n");
 
-	for (j = k = scandir(dirpath, &de, NULL, alphasort), deo = de;
-	    j--; de++) {
+	for (deo = de; j--; de++) {
 		int nostat = 0;
 		char *name = (*de)->d_name;
 		char *urlname, *htmlname;
@@ -186,7 +195,8 @@ bozo_dir_index(bozo_httpreq_t *request, 
 		else {
 			unsigned long long len;
 
-			strftime(buf, sizeof buf, "%d-%b-%Y %R", gmtime(&sb.st_mtime));
+			strftime(buf, sizeof buf, "%d-%b-%Y %R",
+			    gmtime(&sb.st_mtime));
 			bozo_printf(httpd, "<td>%s", buf);
 
 			len = ((unsigned long long)sb.st_size + 1023) / 1024;
@@ -195,16 +205,19 @@ bozo_dir_index(bozo_httpreq_t *request, 
 		bozo_printf(httpd, "\r\n");
 	}
 
-	closedir(dp);
+	//closedir(dp);
 	while (k--)
         	free(deo[k]);
 	free(deo);
+
 	bozo_printf(httpd, "</table>\r\n");
+
 	if (httpd->dir_readme != NULL) {
 		if (httpd->dir_readme[0] == '/')
 			snprintf(buf, sizeof buf, "%s", httpd->dir_readme);
 		else
-			snprintf(buf, sizeof buf, "%s/%s", dirpath, httpd->dir_readme);
+			snprintf(buf, sizeof buf, "%s/%s", dirpath,
+			    httpd->dir_readme);
 		fd = open(buf, O_RDONLY);
 		if (fd != -1) {
 			bozo_flush(httpd, stdout);



Home | Main Index | Thread Index | Old Index