[pacman-dev] [PATCH 1/2] pacman: fix possible buffer overflow

morganamilo morganamilo at gmail.com
Sat Sep 22 20:16:44 UTC 2018


in the function query_fileowner, if the user enters a string longer
than PATH_MAX then rpath will buffer overflow when lrealpath tries to
strcat everything together.

Even if we made sure filename was never longer than PATH_MAX this would
not help because lrealpath may concatenate filename with the current
directory among other things.

So simply let lrealpath calculate the size needed and allocate it for
us.

This also fixes the compiler warning;
query.c: In function ‘query_fileowner’:
query.c:192:4: warning: ‘strncpy’ specified bound 4096 equals destination size [-Wstringop-truncation]
    strncpy(rpath, filename, PATH_MAX);

The warning could have also been Fixed by using PATH_MAX -1 and explicitly
terminating the string. However this would not fix the buffer overflow.

Signed-off-by: morganamilo <morganamilo at gmail.com>

diff --git a/src/pacman/query.c b/src/pacman/query.c
index 00c39638..a1197cea 100644
--- a/src/pacman/query.c
+++ b/src/pacman/query.c
@@ -155,10 +155,10 @@ static int query_fileowner(alpm_list_t *targets)
 
 	for(t = targets; t; t = alpm_list_next(t)) {
 		char *filename = NULL;
-		char rpath[PATH_MAX], *rel_path;
+		char *rpath = NULL, *rpathsave, *rel_path;
 		struct stat buf;
 		alpm_list_t *i;
-		size_t len;
+		size_t len, rlen;
 		unsigned int found = 0;
 		int is_dir = 0, is_missing = 0;
 
@@ -187,9 +187,15 @@ static int query_fileowner(alpm_list_t *targets)
 			}
 		}
 
-		if(!lrealpath(filename, rpath)) {
+		if(!(rpath = lrealpath(filename, NULL))) {
 			/* Can't canonicalize path, try to proceed anyway */
-			strncpy(rpath, filename, PATH_MAX);
+			rpath = strdup(filename);
+		}
+
+		rlen = strlen(rpath);
+		if(rlen + 1 >= PATH_MAX) {
+				pm_printf(ALPM_LOG_ERROR, _("path too long: %s/\n"), rpath);
+				goto targcleanup;
 		}
 
 		if(strncmp(rpath, root, rootlen) != 0) {
@@ -201,11 +207,14 @@ static int query_fileowner(alpm_list_t *targets)
 		rel_path = rpath + rootlen;
 
 		if((is_missing && is_dir) || (!is_missing && (is_dir = S_ISDIR(buf.st_mode)))) {
-			size_t rlen = strlen(rpath);
 			if(rlen + 2 >= PATH_MAX) {
 					pm_printf(ALPM_LOG_ERROR, _("path too long: %s/\n"), rpath);
 					goto targcleanup;
 			}
+			if ((rpathsave = realloc(rpath, rlen + 2)) == NULL) {
+				goto targcleanup;
+			}
+			rpath = rpathsave;
 			strcat(rpath + rlen, "/");
 		}
 
-- 
2.19.0


More information about the pacman-dev mailing list