summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/glibc/glibc/0001-CVE-2021-3998.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-core/glibc/glibc/0001-CVE-2021-3998.patch')
-rw-r--r--meta/recipes-core/glibc/glibc/0001-CVE-2021-3998.patch282
1 files changed, 282 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 @@
+From fb7bff12e81c677a6622f724edd4d4987dd9d971 Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Tue, 18 Jan 2022 13:29:36 +0530
+Subject: [PATCH] support: Add helpers to create paths longer than PATH_MAX
+
+Add new helpers support_create_and_chdir_toolong_temp_directory and
+support_chdir_toolong_temp_directory to create and descend into
+directory trees longer than PATH_MAX.
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+
+Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commit;h=062ff490c1467059f6cd64bb9c3d85f6cc6cf97a]
+CVE: CVE-2021-3998
+
+Signed-off-by: Pgowda <pgowda.cve@gmail.com>
+---
+ support/temp_file.c | 159 +++++++++++++++++++++++++++++++++++++++++---
+ support/temp_file.h | 9 +++
+ 2 files changed, 159 insertions(+), 9 deletions(-)
+
+diff --git a/support/temp_file.c b/support/temp_file.c
+index e7bb8aadb9..e41128c2d4 100644
+--- a/support/temp_file.c
++++ b/support/temp_file.c
+@@ -1,5 +1,6 @@
+ /* Temporary file handling for tests.
+ Copyright (C) 1998-2021 Free Software Foundation, Inc.
++ Copyright The GNU Tools Authors.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+@@ -20,15 +21,17 @@
+ some 32-bit platforms. */
+ #define _FILE_OFFSET_BITS 64
+
++#include <support/check.h>
+ #include <support/temp_file.h>
+ #include <support/temp_file-internal.h>
+ #include <support/support.h>
+
++#include <errno.h>
+ #include <paths.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+-#include <unistd.h>
++#include <xunistd.h>
+
+ /* List of temporary files. */
+ static struct temp_name_list
+@@ -36,14 +39,20 @@ static struct temp_name_list
+ struct temp_name_list *next;
+ char *name;
+ pid_t owner;
++ bool toolong;
+ } *temp_name_list;
+
+ /* Location of the temporary files. Set by the test skeleton via
+ support_set_test_dir. The string is not be freed. */
+ static const char *test_dir = _PATH_TMP;
+
+-void
+-add_temp_file (const char *name)
++/* Name of subdirectories in a too long temporary directory tree. */
++static char toolong_subdir[NAME_MAX + 1];
++static bool toolong_initialized;
++static size_t toolong_path_max;
++
++static void
++add_temp_file_internal (const char *name, bool toolong)
+ {
+ struct temp_name_list *newp
+ = (struct temp_name_list *) xcalloc (sizeof (*newp), 1);
+@@ -53,12 +62,19 @@ add_temp_file (const char *name)
+ newp->name = newname;
+ newp->next = temp_name_list;
+ newp->owner = getpid ();
++ newp->toolong = toolong;
+ temp_name_list = newp;
+ }
+ else
+ free (newp);
+ }
+
++void
++add_temp_file (const char *name)
++{
++ add_temp_file_internal (name, false);
++}
++
+ int
+ create_temp_file_in_dir (const char *base, const char *dir, char **filename)
+ {
+@@ -90,8 +106,8 @@ create_temp_file (const char *base, char
+ return create_temp_file_in_dir (base, test_dir, filename);
+ }
+
+-char *
+-support_create_temp_directory (const char *base)
++static char *
++create_temp_directory_internal (const char *base, bool toolong)
+ {
+ char *path = xasprintf ("%s/%sXXXXXX", test_dir, base);
+ if (mkdtemp (path) == NULL)
+@@ -99,16 +115,132 @@ support_create_temp_directory (const cha
+ printf ("error: mkdtemp (\"%s\"): %m", path);
+ exit (1);
+ }
+- add_temp_file (path);
++ add_temp_file_internal (path, toolong);
+ return path;
+ }
+
+-/* Helper functions called by the test skeleton follow. */
++char *
++support_create_temp_directory (const char *base)
++{
++ return create_temp_directory_internal (base, false);
++}
++
++static void
++ensure_toolong_initialized (void)
++{
++ if (!toolong_initialized)
++ FAIL_EXIT1 ("uninitialized toolong directory tree\n");
++}
++
++static void
++initialize_toolong (const char *base)
++{
++ long name_max = pathconf (base, _PC_NAME_MAX);
++ name_max = (name_max < 0 ? 64
++ : (name_max < sizeof (toolong_subdir) ? name_max
++ : sizeof (toolong_subdir) - 1));
++
++ long path_max = pathconf (base, _PC_PATH_MAX);
++ path_max = (path_max < 0 ? 1024
++ : path_max <= PTRDIFF_MAX ? path_max : PTRDIFF_MAX);
++
++ /* Sanity check to ensure that the test does not create temporary directories
++ in different filesystems because this API doesn't support it. */
++ if (toolong_initialized)
++ {
++ if (name_max != strlen (toolong_subdir))
++ FAIL_UNSUPPORTED ("name_max: Temporary directories in different"
++ " filesystems not supported yet\n");
++ if (path_max != toolong_path_max)
++ FAIL_UNSUPPORTED ("path_max: Temporary directories in different"
++ " filesystems not supported yet\n");
++ return;
++ }
++
++ toolong_path_max = path_max;
++
++ size_t len = name_max;
++ memset (toolong_subdir, 'X', len);
++ toolong_initialized = true;
++}
++
++char *
++support_create_and_chdir_toolong_temp_directory (const char *basename)
++{
++ char *base = create_temp_directory_internal (basename, true);
++ xchdir (base);
++
++ initialize_toolong (base);
++
++ size_t sz = strlen (toolong_subdir);
++
++ /* Create directories and descend into them so that the final path is larger
++ than PATH_MAX. */
++ for (size_t i = 0; i <= toolong_path_max / sz; i++)
++ {
++ int ret = mkdir (toolong_subdir, S_IRWXU);
++ if (ret != 0 && errno == ENAMETOOLONG)
++ FAIL_UNSUPPORTED ("Filesystem does not support creating too long "
++ "directory trees\n");
++ else if (ret != 0)
++ FAIL_EXIT1 ("Failed to create directory tree: %m\n");
++ xchdir (toolong_subdir);
++ }
++ return base;
++}
+
+ void
+-support_set_test_dir (const char *path)
++support_chdir_toolong_temp_directory (const char *base)
+ {
+- test_dir = path;
++ ensure_toolong_initialized ();
++
++ xchdir (base);
++
++ size_t sz = strlen (toolong_subdir);
++ for (size_t i = 0; i <= toolong_path_max / sz; i++)
++ xchdir (toolong_subdir);
++}
++
++/* Helper functions called by the test skeleton follow. */
++
++static void
++remove_toolong_subdirs (const char *base)
++{
++ ensure_toolong_initialized ();
++
++ if (chdir (base) != 0)
++ {
++ printf ("warning: toolong cleanup base failed: chdir (\"%s\"): %m\n",
++ base);
++ return;
++ }
++
++ /* Descend. */
++ int levels = 0;
++ size_t sz = strlen (toolong_subdir);
++ for (levels = 0; levels <= toolong_path_max / sz; levels++)
++ if (chdir (toolong_subdir) != 0)
++ {
++ printf ("warning: toolong cleanup failed: chdir (\"%s\"): %m\n",
++ toolong_subdir);
++ break;
++ }
++
++ /* Ascend and remove. */
++ while (--levels >= 0)
++ {
++ if (chdir ("..") != 0)
++ {
++ printf ("warning: toolong cleanup failed: chdir (\"..\"): %m\n");
++ return;
++ }
++ if (remove (toolong_subdir) != 0)
++ {
++ printf ("warning: could not remove subdirectory: %s: %m\n",
++ toolong_subdir);
++ return;
++ }
++ }
+ }
+
+ void
+@@ -123,6 +255,9 @@ support_delete_temp_files (void)
+ around, to prevent PID reuse.) */
+ if (temp_name_list->owner == pid)
+ {
++ if (temp_name_list->toolong)
++ remove_toolong_subdirs (temp_name_list->name);
++
+ if (remove (temp_name_list->name) != 0)
+ printf ("warning: could not remove temporary file: %s: %m\n",
+ temp_name_list->name);
+@@ -147,3 +282,9 @@ support_print_temp_files (FILE *f)
+ fprintf (f, ")\n");
+ }
+ }
++
++void
++support_set_test_dir (const char *path)
++{
++ test_dir = path;
++}
+diff --git a/support/temp_file.h b/support/temp_file.h
+index 50a443abe4..8459ddda72 100644
+--- a/support/temp_file.h
++++ b/support/temp_file.h
+@@ -44,6 +44,15 @@ int create_temp_file_in_dir (const char
+ returns. The caller should free this string. */
+ char *support_create_temp_directory (const char *base);
+
++/* Create a temporary directory tree that is longer than PATH_MAX and schedule
++ it for deletion. BASENAME is used as a prefix for the unique directory
++ name, which the function returns. The caller should free this string. */
++char *support_create_and_chdir_toolong_temp_directory (const char *basename);
++
++/* Change into the innermost directory of the directory tree BASE, which was
++ created using support_create_and_chdir_toolong_temp_directory. */
++void support_chdir_toolong_temp_directory (const char *base);
++
+ __END_DECLS
+
+ #endif /* SUPPORT_TEMP_FILE_H */