]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix use-after-free in glob when expanding ~user (bug 25414)
authorAndreas Schwab <schwab@suse.de>
Wed, 19 Feb 2020 16:21:46 +0000 (17:21 +0100)
committerTulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
Fri, 20 Mar 2020 20:49:04 +0000 (17:49 -0300)
The value of `end_name' points into the value of `dirname', thus don't
deallocate the latter before the last use of the former.

(cherry picked from commit ddc650e9b3dc916eab417ce9f79e67337b05035c with
 changes from commit d711a00f93fa964f41a53839228598fbf1a6b482)

NEWS
posix/glob.c

diff --git a/NEWS b/NEWS
index cb62587dbb6caaf3213482ddbc0d28b8b069cb1e..b18a0f3d290da93149b3f7b697aafe2452fd9e2f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -394,6 +394,9 @@ Security related changes:
 * A use-after-free vulnerability in clntudp_call in the Sun RPC system has been
   fixed (CVE-2017-12133).
 
+* A use-after-free vulnerability in the glob function when expanding ~user has
+  been fixed (CVE-2020-1752).
+
 The following bugs are resolved with this release:
 
   [984] network: Respond to changed resolv.conf in gethostbyname
@@ -621,6 +624,7 @@ The following bugs are resolved with this release:
   [21839] localedata: Fix LC_MONETARY for ta_LK
   [21844] localedata: Fix Latin characters and Months Sequence.
   [21848] localedata: Fix mai_NP Title Name
+  [25414] 'glob' use-after-free bug (CVE-2020-1752)
 
 \f
 Version 2.25
index b2273ea7bce40552f3d45d74214868dec8cf232d..0c6eeb36378b06781a3dbbf2be8bf430c2dbb8fb 100644 (file)
@@ -947,26 +947,32 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
                size_t home_len = strlen (p->pw_dir);
                size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
 
-               if (__glibc_unlikely (malloc_dirname))
-                 free (dirname);
-               malloc_dirname = 0;
+               char *d, *newp;
+               bool use_alloca = glob_use_alloca (alloca_used,
+                                                  home_len + rest_len + 1);
 
-               if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
-                 dirname = alloca_account (home_len + rest_len + 1,
-                                           alloca_used);
+               if (use_alloca)
+                 newp = alloca_account (home_len + rest_len + 1, alloca_used);
                else
                  {
-                   dirname = malloc (home_len + rest_len + 1);
-                   if (dirname == NULL)
+                   newp = malloc (home_len + rest_len + 1);
+                   if (newp == NULL)
                      {
                        free (malloc_pwtmpbuf);
                        retval = GLOB_NOSPACE;
                        goto out;
                      }
-                   malloc_dirname = 1;
                  }
-               *((char *) mempcpy (mempcpy (dirname, p->pw_dir, home_len),
-                                   end_name, rest_len)) = '\0';
+
+               d = mempcpy (newp, p->pw_dir, home_len);
+               if (end_name != NULL)
+                 d = mempcpy (d, end_name, rest_len);
+               *d = '\0';
+
+               if (__glibc_unlikely (malloc_dirname))
+                 free (dirname);
+               dirname = newp;
+               malloc_dirname = !use_alloca;
 
                dirlen = home_len + rest_len;
                dirname_modified = 1;