glibc/glibc-RHEL-75809-2.patch
2025-01-24 23:16:09 +01:00

233 lines
7.8 KiB
Diff

commit 36fcdfbbc5463e55581fec67141df3493fb81f7e
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Jan 24 08:04:23 2025 +0100
Revert "stdlib: Support malloc-managed environ arrays for compatibility"
This reverts commit b62759db04b8ed7f829c06f1d7c3b8fb70616493.
Reason for revert: Incompatible with “env -i” and coreutils (bug 32588).
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
diff --git a/csu/init-first.c b/csu/init-first.c
index 77b5b4941beb3a73..a2cb456ccf9ac5e6 100644
--- a/csu/init-first.c
+++ b/csu/init-first.c
@@ -61,7 +61,6 @@ _init_first (int argc, char **argv, char **envp)
__libc_argc = argc;
__libc_argv = argv;
__environ = envp;
- __environ_startup = envp;
#ifndef SHARED
/* First the initialization which normally would be done by the
diff --git a/csu/libc-start.c b/csu/libc-start.c
index 260027c2396e1f52..d784de0f0bdd70c8 100644
--- a/csu/libc-start.c
+++ b/csu/libc-start.c
@@ -244,7 +244,6 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
char **ev = &argv[argc + 1];
__environ = ev;
- __environ_startup = ev;
/* Store the lowest stack address. This is done in ld.so if this is
the code for the DSO. */
diff --git a/include/unistd.h b/include/unistd.h
index ada957f9d04d272a..e241603b8131a9e9 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -203,9 +203,6 @@ libc_hidden_proto (__tcsetpgrp)
extern int __libc_enable_secure attribute_relro;
rtld_hidden_proto (__libc_enable_secure)
-/* Original value of __environ. Initialized by _init_first (dynamic)
- or __libc_start_main (static). */
-extern char **__environ_startup attribute_hidden;
/* Various internal function. */
extern void __libc_check_standard_fds (void) attribute_hidden;
diff --git a/posix/environ.c b/posix/environ.c
index 2430b47d8eee148c..a0ed0d80eab207f8 100644
--- a/posix/environ.c
+++ b/posix/environ.c
@@ -10,5 +10,3 @@ weak_alias (__environ, environ)
/* The SVR4 ABI says `_environ' will be the name to use
in case the user overrides the weak alias `environ'. */
weak_alias (__environ, _environ)
-
-char **__environ_startup;
diff --git a/stdlib/Makefile b/stdlib/Makefile
index 217600ba60e3c7d4..ff1418f5bb2ea5c9 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -312,7 +312,6 @@ tests := \
tst-setcontext9 \
tst-setcontext10 \
tst-setcontext11 \
- tst-setenv-malloc \
tst-stdbit-Wconversion \
tst-stdbit-builtins \
tst-stdc_bit_ceil \
diff --git a/stdlib/setenv.c b/stdlib/setenv.c
index 79982aa12ac20078..d12401ca77cee5a7 100644
--- a/stdlib/setenv.c
+++ b/stdlib/setenv.c
@@ -191,52 +191,52 @@ __add_to_environ (const char *name, const char *value, const char *combined,
ep[1] = NULL;
else
{
- /* We cannot use __environ as is and need a larger allocation. */
-
- if (start_environ == __environ_startup
- || __environ_is_from_array_list (start_environ))
- {
- /* Allocate a new array, managed in the list. */
- struct environ_array *target_array
- = __environ_new_array (required_size);
- if (target_array == NULL)
- {
- UNLOCK;
- return -1;
- }
- result_environ = &target_array->array[0];
-
- /* Copy over the __environ array contents. This code
- handles the case start_environ == ep == NULL, too. */
- size_t i;
- for (i = 0; start_environ + i < ep; ++i)
- /* Regular store because unless there has been direct
- manipulation of the environment, target_array is still
- a private copy. */
- result_environ[i] = atomic_load_relaxed (start_environ + i);
- }
+ /* We cannot use __environ as is and need to copy over the
+ __environ contents into an array managed via
+ __environ_array_list. */
+
+ struct environ_array *target_array;
+ if (__environ_array_list != NULL
+ && required_size <= __environ_array_list->allocated)
+ /* Existing array has enough room. Contents is copied below. */
+ target_array = __environ_array_list;
else
{
- /* Otherwise the application installed its own pointer.
- Historically, this pointer was managed using realloc.
- Continue doing so. This disables multi-threading
- support. */
- result_environ = __libc_reallocarray (start_environ,
- required_size,
- sizeof (*result_environ));
- if (result_environ == NULL)
+ /* Allocate a new array. */
+ target_array = __environ_new_array (required_size);
+ if (target_array == NULL)
{
UNLOCK;
return -1;
}
}
+ /* Copy over the __environ array contents. This forward
+ copy slides backwards part of the array if __environ
+ points into target_array->array. This happens if an
+ application makes an assignment like:
+
+ environ = &environ[1];
+
+ The forward copy avoids clobbering values that still
+ needing copying. This code handles the case
+ start_environ == ep == NULL, too. */
+ size_t i;
+ for (i = 0; start_environ + i < ep; ++i)
+ /* Regular store because unless there has been direct
+ manipulation of the environment, target_array is still
+ a private copy. */
+ target_array->array[i] = atomic_load_relaxed (start_environ + i);
+
/* This is the new place where we should add the element. */
- ep = result_environ + (required_size - 2);
+ ep = target_array->array + i;
/* Add the null terminator in case there was a pointer there
previously. */
ep[1] = NULL;
+
+ /* And __environ should be repointed to our array. */
+ result_environ = &target_array->array[0];
}
}
diff --git a/stdlib/tst-setenv-malloc.c b/stdlib/tst-setenv-malloc.c
deleted file mode 100644
index 18a9d36842e67aa5..0000000000000000
--- a/stdlib/tst-setenv-malloc.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Test using setenv with a malloc-allocated environ variable.
- Copyright (C) 2025 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <https://www.gnu.org/licenses/>. */
-
-/* This test is not in the scope for POSIX or any other standard, but
- some applications assume that environ is a heap-allocated pointer
- after a call to setenv on an empty environment. */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <support/check.h>
-#include <support/support.h>
-
-static const char *original_path;
-static char **save_environ;
-
-static void
-rewrite_environ (void)
-{
- save_environ = environ;
- environ = xmalloc (sizeof (*environ));
- *environ = NULL;
- TEST_COMPARE (setenv ("A", "1", 1), 0);
- TEST_COMPARE (setenv ("B", "2", 1), 0);
- TEST_VERIFY (environ != save_environ);
- TEST_COMPARE_STRING (environ[0], "A=1");
- TEST_COMPARE_STRING (environ[1], "B=2");
- TEST_COMPARE_STRING (environ[2], NULL);
- TEST_COMPARE_STRING (getenv ("PATH"), NULL);
- free (environ);
- environ = save_environ;
- TEST_COMPARE_STRING (getenv ("PATH"), original_path);
-}
-
-static int
-do_test (void)
-{
- original_path = getenv ("PATH");
- rewrite_environ ();
-
- /* Test again after reallocated the environment due to an initial
- setenv call. */
- TEST_COMPARE (setenv ("TST_SETENV_MALLOC", "1", 1), 0);
- TEST_VERIFY (environ != save_environ);
- rewrite_environ ();
-
- return 0;
-}
-
-#include <support/test-driver.c>