summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/glibc/glibc
diff options
context:
space:
mode:
authorPgowda <pgowda.cve@gmail.com>2022-01-24 05:10:42 -0800
committerRichard Purdie <richard.purdie@linuxfoundation.org>2022-01-26 06:27:00 +0000
commit359fcb9ed29c73a39b96aded1a501815727dfd95 (patch)
tree3d5b8e9664ffd48239a8665d89c9e63899b6bdd1 /meta/recipes-core/glibc/glibc
parent21e5b78d9a1cd24c9488ac0ad0a2410c30bcb5da (diff)
downloadpoky-359fcb9ed29c73a39b96aded1a501815727dfd95.tar.gz
glibc : Fix CVE-2021-3998
Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commit;h=062ff490c1467059f6cd64bb9c3d85f6cc6cf97a] Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commit;h=f7a79879c0b2bef0dadd6caaaeeb0d26423e04e5] (From OE-Core rev: 20cc83dd8d323d7ea86b3625f4e8da94c160def9) Signed-off-by: pgowda <pgowda.cve@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-core/glibc/glibc')
-rw-r--r--meta/recipes-core/glibc/glibc/0001-CVE-2021-3998.patch282
-rw-r--r--meta/recipes-core/glibc/glibc/0002-CVE-2021-3998.patch138
2 files changed, 420 insertions, 0 deletions
diff --git a/meta/recipes-core/glibc/glibc/0001-CVE-2021-3998.patch b/meta/recipes-core/glibc/glibc/0001-CVE-2021-3998.patch
new file mode 100644
index 0000000000..c6bd5916e3
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/0001-CVE-2021-3998.patch
@@ -0,0 +1,282 @@
1From fb7bff12e81c677a6622f724edd4d4987dd9d971 Mon Sep 17 00:00:00 2001
2From: Siddhesh Poyarekar <siddhesh@sourceware.org>
3Date: Tue, 18 Jan 2022 13:29:36 +0530
4Subject: [PATCH] support: Add helpers to create paths longer than PATH_MAX
5
6Add new helpers support_create_and_chdir_toolong_temp_directory and
7support_chdir_toolong_temp_directory to create and descend into
8directory trees longer than PATH_MAX.
9
10Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
11Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
12
13Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commit;h=062ff490c1467059f6cd64bb9c3d85f6cc6cf97a]
14CVE: CVE-2021-3998
15
16Signed-off-by: Pgowda <pgowda.cve@gmail.com>
17---
18 support/temp_file.c | 159 +++++++++++++++++++++++++++++++++++++++++---
19 support/temp_file.h | 9 +++
20 2 files changed, 159 insertions(+), 9 deletions(-)
21
22diff --git a/support/temp_file.c b/support/temp_file.c
23index e7bb8aadb9..e41128c2d4 100644
24--- a/support/temp_file.c
25+++ b/support/temp_file.c
26@@ -1,5 +1,6 @@
27 /* Temporary file handling for tests.
28 Copyright (C) 1998-2021 Free Software Foundation, Inc.
29+ Copyright The GNU Tools Authors.
30 This file is part of the GNU C Library.
31
32 The GNU C Library is free software; you can redistribute it and/or
33@@ -20,15 +21,17 @@
34 some 32-bit platforms. */
35 #define _FILE_OFFSET_BITS 64
36
37+#include <support/check.h>
38 #include <support/temp_file.h>
39 #include <support/temp_file-internal.h>
40 #include <support/support.h>
41
42+#include <errno.h>
43 #include <paths.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47-#include <unistd.h>
48+#include <xunistd.h>
49
50 /* List of temporary files. */
51 static struct temp_name_list
52@@ -36,14 +39,20 @@ static struct temp_name_list
53 struct temp_name_list *next;
54 char *name;
55 pid_t owner;
56+ bool toolong;
57 } *temp_name_list;
58
59 /* Location of the temporary files. Set by the test skeleton via
60 support_set_test_dir. The string is not be freed. */
61 static const char *test_dir = _PATH_TMP;
62
63-void
64-add_temp_file (const char *name)
65+/* Name of subdirectories in a too long temporary directory tree. */
66+static char toolong_subdir[NAME_MAX + 1];
67+static bool toolong_initialized;
68+static size_t toolong_path_max;
69+
70+static void
71+add_temp_file_internal (const char *name, bool toolong)
72 {
73 struct temp_name_list *newp
74 = (struct temp_name_list *) xcalloc (sizeof (*newp), 1);
75@@ -53,12 +62,19 @@ add_temp_file (const char *name)
76 newp->name = newname;
77 newp->next = temp_name_list;
78 newp->owner = getpid ();
79+ newp->toolong = toolong;
80 temp_name_list = newp;
81 }
82 else
83 free (newp);
84 }
85
86+void
87+add_temp_file (const char *name)
88+{
89+ add_temp_file_internal (name, false);
90+}
91+
92 int
93 create_temp_file_in_dir (const char *base, const char *dir, char **filename)
94 {
95@@ -90,8 +106,8 @@ create_temp_file (const char *base, char
96 return create_temp_file_in_dir (base, test_dir, filename);
97 }
98
99-char *
100-support_create_temp_directory (const char *base)
101+static char *
102+create_temp_directory_internal (const char *base, bool toolong)
103 {
104 char *path = xasprintf ("%s/%sXXXXXX", test_dir, base);
105 if (mkdtemp (path) == NULL)
106@@ -99,16 +115,132 @@ support_create_temp_directory (const cha
107 printf ("error: mkdtemp (\"%s\"): %m", path);
108 exit (1);
109 }
110- add_temp_file (path);
111+ add_temp_file_internal (path, toolong);
112 return path;
113 }
114
115-/* Helper functions called by the test skeleton follow. */
116+char *
117+support_create_temp_directory (const char *base)
118+{
119+ return create_temp_directory_internal (base, false);
120+}
121+
122+static void
123+ensure_toolong_initialized (void)
124+{
125+ if (!toolong_initialized)
126+ FAIL_EXIT1 ("uninitialized toolong directory tree\n");
127+}
128+
129+static void
130+initialize_toolong (const char *base)
131+{
132+ long name_max = pathconf (base, _PC_NAME_MAX);
133+ name_max = (name_max < 0 ? 64
134+ : (name_max < sizeof (toolong_subdir) ? name_max
135+ : sizeof (toolong_subdir) - 1));
136+
137+ long path_max = pathconf (base, _PC_PATH_MAX);
138+ path_max = (path_max < 0 ? 1024
139+ : path_max <= PTRDIFF_MAX ? path_max : PTRDIFF_MAX);
140+
141+ /* Sanity check to ensure that the test does not create temporary directories
142+ in different filesystems because this API doesn't support it. */
143+ if (toolong_initialized)
144+ {
145+ if (name_max != strlen (toolong_subdir))
146+ FAIL_UNSUPPORTED ("name_max: Temporary directories in different"
147+ " filesystems not supported yet\n");
148+ if (path_max != toolong_path_max)
149+ FAIL_UNSUPPORTED ("path_max: Temporary directories in different"
150+ " filesystems not supported yet\n");
151+ return;
152+ }
153+
154+ toolong_path_max = path_max;
155+
156+ size_t len = name_max;
157+ memset (toolong_subdir, 'X', len);
158+ toolong_initialized = true;
159+}
160+
161+char *
162+support_create_and_chdir_toolong_temp_directory (const char *basename)
163+{
164+ char *base = create_temp_directory_internal (basename, true);
165+ xchdir (base);
166+
167+ initialize_toolong (base);
168+
169+ size_t sz = strlen (toolong_subdir);
170+
171+ /* Create directories and descend into them so that the final path is larger
172+ than PATH_MAX. */
173+ for (size_t i = 0; i <= toolong_path_max / sz; i++)
174+ {
175+ int ret = mkdir (toolong_subdir, S_IRWXU);
176+ if (ret != 0 && errno == ENAMETOOLONG)
177+ FAIL_UNSUPPORTED ("Filesystem does not support creating too long "
178+ "directory trees\n");
179+ else if (ret != 0)
180+ FAIL_EXIT1 ("Failed to create directory tree: %m\n");
181+ xchdir (toolong_subdir);
182+ }
183+ return base;
184+}
185
186 void
187-support_set_test_dir (const char *path)
188+support_chdir_toolong_temp_directory (const char *base)
189 {
190- test_dir = path;
191+ ensure_toolong_initialized ();
192+
193+ xchdir (base);
194+
195+ size_t sz = strlen (toolong_subdir);
196+ for (size_t i = 0; i <= toolong_path_max / sz; i++)
197+ xchdir (toolong_subdir);
198+}
199+
200+/* Helper functions called by the test skeleton follow. */
201+
202+static void
203+remove_toolong_subdirs (const char *base)
204+{
205+ ensure_toolong_initialized ();
206+
207+ if (chdir (base) != 0)
208+ {
209+ printf ("warning: toolong cleanup base failed: chdir (\"%s\"): %m\n",
210+ base);
211+ return;
212+ }
213+
214+ /* Descend. */
215+ int levels = 0;
216+ size_t sz = strlen (toolong_subdir);
217+ for (levels = 0; levels <= toolong_path_max / sz; levels++)
218+ if (chdir (toolong_subdir) != 0)
219+ {
220+ printf ("warning: toolong cleanup failed: chdir (\"%s\"): %m\n",
221+ toolong_subdir);
222+ break;
223+ }
224+
225+ /* Ascend and remove. */
226+ while (--levels >= 0)
227+ {
228+ if (chdir ("..") != 0)
229+ {
230+ printf ("warning: toolong cleanup failed: chdir (\"..\"): %m\n");
231+ return;
232+ }
233+ if (remove (toolong_subdir) != 0)
234+ {
235+ printf ("warning: could not remove subdirectory: %s: %m\n",
236+ toolong_subdir);
237+ return;
238+ }
239+ }
240 }
241
242 void
243@@ -123,6 +255,9 @@ support_delete_temp_files (void)
244 around, to prevent PID reuse.) */
245 if (temp_name_list->owner == pid)
246 {
247+ if (temp_name_list->toolong)
248+ remove_toolong_subdirs (temp_name_list->name);
249+
250 if (remove (temp_name_list->name) != 0)
251 printf ("warning: could not remove temporary file: %s: %m\n",
252 temp_name_list->name);
253@@ -147,3 +282,9 @@ support_print_temp_files (FILE *f)
254 fprintf (f, ")\n");
255 }
256 }
257+
258+void
259+support_set_test_dir (const char *path)
260+{
261+ test_dir = path;
262+}
263diff --git a/support/temp_file.h b/support/temp_file.h
264index 50a443abe4..8459ddda72 100644
265--- a/support/temp_file.h
266+++ b/support/temp_file.h
267@@ -44,6 +44,15 @@ int create_temp_file_in_dir (const char
268 returns. The caller should free this string. */
269 char *support_create_temp_directory (const char *base);
270
271+/* Create a temporary directory tree that is longer than PATH_MAX and schedule
272+ it for deletion. BASENAME is used as a prefix for the unique directory
273+ name, which the function returns. The caller should free this string. */
274+char *support_create_and_chdir_toolong_temp_directory (const char *basename);
275+
276+/* Change into the innermost directory of the directory tree BASE, which was
277+ created using support_create_and_chdir_toolong_temp_directory. */
278+void support_chdir_toolong_temp_directory (const char *base);
279+
280 __END_DECLS
281
282 #endif /* SUPPORT_TEMP_FILE_H */
diff --git a/meta/recipes-core/glibc/glibc/0002-CVE-2021-3998.patch b/meta/recipes-core/glibc/glibc/0002-CVE-2021-3998.patch
new file mode 100644
index 0000000000..0a4c34452d
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/0002-CVE-2021-3998.patch
@@ -0,0 +1,138 @@
1From f7a79879c0b2bef0dadd6caaaeeb0d26423e04e5 Mon Sep 17 00:00:00 2001
2From: Siddhesh Poyarekar <siddhesh@sourceware.org>
3Date: Thu, 13 Jan 2022 11:28:36 +0530
4Subject: [PATCH] realpath: Set errno to ENAMETOOLONG for result larger than
5 PATH_MAX [BZ #28770]
6
7realpath returns an allocated string when the result exceeds PATH_MAX,
8which is unexpected when its second argument is not NULL. This results
9in the second argument (resolved) being uninitialized and also results
10in a memory leak since the caller expects resolved to be the same as the
11returned value.
12
13Return NULL and set errno to ENAMETOOLONG if the result exceeds
14PATH_MAX. This fixes [BZ #28770], which is CVE-2021-3998.
15
16Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
17Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
18(cherry picked from commit ee8d5e33adb284601c00c94687bc907e10aec9bb)
19
20Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commit;h=f7a79879c0b2bef0dadd6caaaeeb0d26423e04e5]
21CVE: CVE-2021-3998
22
23Signed-off-by: Pgowda <pgowda.cve@gmail.com>
24---
25 NEWS | 4 +++
26 stdlib/Makefile | 1 +
27 stdlib/canonicalize.c | 12 +++++++--
28 stdlib/tst-realpath-toolong.c | 49 +++++++++++++++++++++++++++++++++++
29 4 files changed, 64 insertions(+), 2 deletions(-)
30 create mode 100644 stdlib/tst-realpath-toolong.c
31
32diff --git a/NEWS b/NEWS
33index 7e773bd005..b4f81c2668 100644
34--- a/NEWS
35+++ b/NEWS
36@@ -210,6 +210,10 @@ Security related changes:
37 legacy function could result in a stack-based buffer overflow when
38 using the "unix" protocol. Reported by Martin Sebor.
39
40+ CVE-2021-3998: Passing a path longer than PATH_MAX to the realpath
41+ function could result in a memory leak and potential access of
42+ uninitialized memory. Reported by Qualys.
43+
44 The following bugs are resolved with this release:
45
46 [4737] libc: fork is not async-signal-safe
47diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c
48index 698f9ede25..7a23a51b3a 100644
49--- a/stdlib/canonicalize.c
50+++ b/stdlib/canonicalize.c
51@@ -400,8 +400,16 @@ realpath_stk (const char *name, char *re
52
53 error:
54 *dest++ = '\0';
55- if (resolved != NULL && dest - rname <= get_path_max ())
56- rname = strcpy (resolved, rname);
57+ if (resolved != NULL)
58+ {
59+ if (dest - rname <= get_path_max ())
60+ rname = strcpy (resolved, rname);
61+ else
62+ {
63+ failed = true;
64+ __set_errno (ENAMETOOLONG);
65+ }
66+ }
67
68 error_nomem:
69 scratch_buffer_free (&extra_buffer);
70diff --git a/stdlib/Makefile b/stdlib/Makefile
71index 9bb5c221e8..a4ac30d1f6 100644
72--- a/stdlib/Makefile
73+++ b/stdlib/Makefile
74@@ -88,7 +88,8 @@ tests := tst-strtol tst-strtod testmb t
75 tst-swapcontext1 tst-setcontext4 tst-setcontext5 \
76 tst-setcontext6 tst-setcontext7 tst-setcontext8 \
77 tst-setcontext9 tst-bz20544 tst-canon-bz26341 \
78- tst-realpath
79+ tst-realpath \
80+ tst-realpath-toolong
81
82 tests-internal := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \
83 tst-tls-atexit tst-tls-atexit-nodelete
84diff --git a/stdlib/tst-realpath-toolong.c b/stdlib/tst-realpath-toolong.c
85new file mode 100644
86index 0000000000..8bed772460
87--- /dev/null
88+++ b/stdlib/tst-realpath-toolong.c
89@@ -0,0 +1,49 @@
90+/* Verify that realpath returns NULL with ENAMETOOLONG if the result exceeds
91+ NAME_MAX.
92+ Copyright The GNU Toolchain Authors.
93+ This file is part of the GNU C Library.
94+
95+ The GNU C Library is free software; you can redistribute it and/or
96+ modify it under the terms of the GNU Lesser General Public
97+ License as published by the Free Software Foundation; either
98+ version 2.1 of the License, or (at your option) any later version.
99+
100+ The GNU C Library is distributed in the hope that it will be useful,
101+ but WITHOUT ANY WARRANTY; without even the implied warranty of
102+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
103+ Lesser General Public License for more details.
104+
105+ You should have received a copy of the GNU Lesser General Public
106+ License along with the GNU C Library; if not, see
107+ <https://www.gnu.org/licenses/>. */
108+
109+#include <errno.h>
110+#include <limits.h>
111+#include <stdlib.h>
112+#include <string.h>
113+#include <unistd.h>
114+#include <support/check.h>
115+#include <support/temp_file.h>
116+#include <sys/types.h>
117+#include <sys/stat.h>
118+
119+#define BASENAME "tst-realpath-toolong."
120+
121+int
122+do_test (void)
123+{
124+ char *base = support_create_and_chdir_toolong_temp_directory (BASENAME);
125+
126+ char buf[PATH_MAX + 1];
127+ const char *res = realpath (".", buf);
128+
129+ /* canonicalize.c states that if the real path is >= PATH_MAX, then
130+ realpath returns NULL and sets ENAMETOOLONG. */
131+ TEST_VERIFY (res == NULL);
132+ TEST_VERIFY (errno == ENAMETOOLONG);
133+
134+ free (base);
135+ return 0;
136+}
137+
138+#include <support/test-driver.c>