glibc/fix-locking-in-_IO_cleanup.patch
Andreas Schwab 98df90238a Accepting request 1098077 from home:Andreas_Schwab:Factory
- gshadow-erange-rhandling.patch: gshadow: Matching sgetsgent, sgetsgent_r
  ERANGE handling (BZ #30151)
- system-sigchld-block.patch: posix: Fix system blocks SIGCHLD erroneously
  (BZ #30163)
- gmon-buffer-alloc.patch: gmon: Fix allocated buffer overflow (BZ #29444)
- check-pf-cancel-handler.patch: __check_pf: Add a cancellation cleanup
  handler (BZ #20975)
- powerpc64-fcntl-lock.patch: io: Fix F_GETLK, F_SETLK, and F_SETLKW for
  powerpc64
- realloc-limit-chunk-reuse.patch: realloc: Limit chunk reuse to only
  growing requests (BZ #30579)
- dl-find-object-return.patch: elf: _dl_find_object may return 1 during
  early startup (BZ #30515)

- Need to build with GCC 12 as minimum

- fix-locking-in-_IO_cleanup.patch: Update to final version

OBS-URL: https://build.opensuse.org/request/show/1098077
OBS-URL: https://build.opensuse.org/package/show/Base:System/glibc?expand=0&rev=655
2023-07-11 07:54:23 +00:00

234 lines
6.5 KiB
Diff

Always do locking when accessing streams (bug 15142, bug 14697)
Now that abort no longer calls fflush there is no reason to avoid locking
the stdio streams anywhere. This fixes a conformance issue and potential
heap corruption during exit.
Index: glibc-2.37/libio/genops.c
===================================================================
--- glibc-2.37.orig/libio/genops.c
+++ glibc-2.37/libio/genops.c
@@ -682,7 +682,7 @@ _IO_adjust_column (unsigned start, const
libc_hidden_def (_IO_adjust_column)
int
-_IO_flush_all_lockp (int do_lock)
+_IO_flush_all (void)
{
int result = 0;
FILE *fp;
@@ -695,8 +695,7 @@ _IO_flush_all_lockp (int do_lock)
for (fp = (FILE *) _IO_list_all; fp != NULL; fp = fp->_chain)
{
run_fp = fp;
- if (do_lock)
- _IO_flockfile (fp);
+ _IO_flockfile (fp);
if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)
|| (_IO_vtable_offset (fp) == 0
@@ -706,8 +705,7 @@ _IO_flush_all_lockp (int do_lock)
&& _IO_OVERFLOW (fp, EOF) == EOF)
result = EOF;
- if (do_lock)
- _IO_funlockfile (fp);
+ _IO_funlockfile (fp);
run_fp = NULL;
}
@@ -718,14 +716,6 @@ _IO_flush_all_lockp (int do_lock)
return result;
}
-
-
-int
-_IO_flush_all (void)
-{
- /* We want locking. */
- return _IO_flush_all_lockp (1);
-}
libc_hidden_def (_IO_flush_all)
void
@@ -791,6 +781,9 @@ _IO_unbuffer_all (void)
{
int legacy = 0;
+ run_fp = fp;
+ _IO_flockfile (fp);
+
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
if (__glibc_unlikely (_IO_vtable_offset (fp) != 0))
legacy = 1;
@@ -800,18 +793,6 @@ _IO_unbuffer_all (void)
/* Iff stream is un-orientated, it wasn't used. */
&& (legacy || fp->_mode != 0))
{
-#ifdef _IO_MTSAFE_IO
- int cnt;
-#define MAXTRIES 2
- for (cnt = 0; cnt < MAXTRIES; ++cnt)
- if (fp->_lock == NULL || _IO_lock_trylock (*fp->_lock) == 0)
- break;
- else
- /* Give the other thread time to finish up its use of the
- stream. */
- __sched_yield ();
-#endif
-
if (! legacy && ! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
{
fp->_flags |= _IO_USER_BUF;
@@ -825,17 +806,15 @@ _IO_unbuffer_all (void)
if (! legacy && fp->_mode > 0)
_IO_wsetb (fp, NULL, NULL, 0);
-
-#ifdef _IO_MTSAFE_IO
- if (cnt < MAXTRIES && fp->_lock != NULL)
- _IO_lock_unlock (*fp->_lock);
-#endif
}
/* Make sure that never again the wide char functions can be
used. */
if (! legacy)
fp->_mode = -1;
+
+ _IO_funlockfile (fp);
+ run_fp = NULL;
}
#ifdef _IO_MTSAFE_IO
@@ -861,9 +840,7 @@ libc_freeres_fn (buffer_free)
int
_IO_cleanup (void)
{
- /* We do *not* want locking. Some threads might use streams but
- that is their problem, we flush them underneath them. */
- int result = _IO_flush_all_lockp (0);
+ int result = _IO_flush_all ();
/* We currently don't have a reliable mechanism for making sure that
C++ static destructors are executed in the correct order.
Index: glibc-2.37/libio/libioP.h
===================================================================
--- glibc-2.37.orig/libio/libioP.h
+++ glibc-2.37/libio/libioP.h
@@ -488,7 +488,6 @@ extern int _IO_new_do_write (FILE *, con
extern int _IO_old_do_write (FILE *, const char *, size_t);
extern int _IO_wdo_write (FILE *, const wchar_t *, size_t);
libc_hidden_proto (_IO_wdo_write)
-extern int _IO_flush_all_lockp (int);
extern int _IO_flush_all (void);
libc_hidden_proto (_IO_flush_all)
extern int _IO_cleanup (void);
Index: glibc-2.37/support/delayed_exit.c
===================================================================
--- glibc-2.37.orig/support/delayed_exit.c
+++ glibc-2.37/support/delayed_exit.c
@@ -23,33 +23,58 @@
#include <stdio.h>
#include <stdlib.h>
#include <support/check.h>
+#include <support/support.h>
#include <time.h>
+#include <unistd.h>
+
+struct delayed_exit_request
+{
+ void (*exitfunc) (int);
+ int seconds;
+};
static void *
-delayed_exit_thread (void *seconds_as_ptr)
+delayed_exit_thread (void *closure)
{
- int seconds = (uintptr_t) seconds_as_ptr;
- struct timespec delay = { seconds, 0 };
+ struct delayed_exit_request *request = closure;
+ void (*exitfunc) (int) = request->exitfunc;
+ struct timespec delay = { request->seconds, 0 };
struct timespec remaining = { 0 };
+ free (request);
+
if (nanosleep (&delay, &remaining) != 0)
FAIL_EXIT1 ("nanosleep: %m");
/* Exit the process sucessfully. */
- exit (0);
+ exitfunc (0);
return NULL;
}
-void
-delayed_exit (int seconds)
+static void
+delayed_exit_1 (int seconds, void (*exitfunc) (int))
{
/* Create the new thread with all signals blocked. */
sigset_t all_blocked;
sigfillset (&all_blocked);
sigset_t old_set;
xpthread_sigmask (SIG_SETMASK, &all_blocked, &old_set);
+ struct delayed_exit_request *request = xmalloc (sizeof (*request));
+ request->seconds = seconds;
+ request->exitfunc = exitfunc;
/* Create a detached thread. */
- pthread_t thr = xpthread_create
- (NULL, delayed_exit_thread, (void *) (uintptr_t) seconds);
+ pthread_t thr = xpthread_create (NULL, delayed_exit_thread, request);
xpthread_detach (thr);
/* Restore the original signal mask. */
xpthread_sigmask (SIG_SETMASK, &old_set, NULL);
}
+
+void
+delayed_exit (int seconds)
+{
+ delayed_exit_1 (seconds, exit);
+}
+
+void
+delayed__exit (int seconds)
+{
+ delayed_exit_1 (seconds, _exit);
+}
Index: glibc-2.37/support/xthread.h
===================================================================
--- glibc-2.37.orig/support/xthread.h
+++ glibc-2.37/support/xthread.h
@@ -25,11 +25,14 @@
__BEGIN_DECLS
-/* Terminate the process (with exit status 0) after SECONDS have
- elapsed, from a helper thread. The process is terminated with the
- exit function, so atexit handlers are executed. */
+/* Terminate the process (with exit (0)) after SECONDS have elapsed,
+ from a helper thread. The process is terminated with the exit
+ function, so atexit handlers are executed. */
void delayed_exit (int seconds);
+/* Like delayed_exit, but use _exit (0). */
+void delayed__exit (int seconds);
+
/* Returns true if Priority Inheritance support CLOCK_MONOTONIC. */
bool support_mutex_pi_monotonic (void);
Index: glibc-2.37/sysdeps/pthread/tst-stdio1.c
===================================================================
--- glibc-2.37.orig/sysdeps/pthread/tst-stdio1.c
+++ glibc-2.37/sysdeps/pthread/tst-stdio1.c
@@ -46,7 +46,7 @@ do_test (void)
_exit (1);
}
- delayed_exit (1);
+ delayed__exit (1);
xpthread_join (th);
puts ("join returned");