summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2019-06-12 14:48:33 +0200
committerFlorian Weimer <fweimer@redhat.com>2019-06-12 14:48:33 +0200
commitcfa611447b44d2fa1cb3d8f853b6f3f75ade366a (patch)
tree52f89d4d9ddf45959ab478d4701b80e42e66614f
parent744e829637162bb7d5029632aacf341c64b86990 (diff)
downloadglibc-cfa611447b44d2fa1cb3d8f853b6f3f75ade366a.tar.gz
glibc-cfa611447b44d2fa1cb3d8f853b6f3f75ade366a.tar.xz
glibc-cfa611447b44d2fa1cb3d8f853b6f3f75ade366a.zip
libio: freopen of default streams crashes in old programs [BZ #24632]
As seen with very old i386 GCC binaries.
-rw-r--r--ChangeLog6
-rw-r--r--libio/freopen.c2
-rw-r--r--libio/libioP.h5
3 files changed, 12 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 865fcec63d..6efe9c464c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2019-06-12  Florian Weimer  <fweimer@redhat.com>
 
+	[BZ #24632]
+	* libio/libioP.h (_IO_JUMPS_FUNC_UPDATE): New macro.
+	* libio/freopen.c (freopen): Use it.
+
+2019-06-12  Florian Weimer  <fweimer@redhat.com>
+
 	Linux: Deprecate sysctl.
 	* include/sysctl.h (__sysctl): Remove declaration.
 	* scripts/check-installed-headers.sh (sys/sysctl.h): Disable
diff --git a/libio/freopen.c b/libio/freopen.c
index 17b00258cd..82e39f5028 100644
--- a/libio/freopen.c
+++ b/libio/freopen.c
@@ -62,7 +62,7 @@ freopen (const char *filename, const char *mode, FILE *fp)
 	 to the old libio may be passed into shared C library and wind
 	 up here. */
       _IO_old_file_close_it (fp);
-      _IO_JUMPS_FILE_plus (fp) = &_IO_old_file_jumps;
+      _IO_JUMPS_FUNC_UPDATE (fp, &_IO_old_file_jumps);
       result = _IO_old_file_fopen (fp, gfilename, mode);
     }
   else
diff --git a/libio/libioP.h b/libio/libioP.h
index 66afaa8968..afa46cc519 100644
--- a/libio/libioP.h
+++ b/libio/libioP.h
@@ -108,9 +108,14 @@
   (IO_validate_vtable                                                   \
    (*(struct _IO_jump_t **) ((void *) &_IO_JUMPS_FILE_plus (THIS)	\
 			     + (THIS)->_vtable_offset)))
+# define _IO_JUMPS_FUNC_UPDATE(THIS, VTABLE)				\
+  (*(const struct _IO_jump_t **) ((void *) &_IO_JUMPS_FILE_plus (THIS)	\
+				  + (THIS)->_vtable_offset) = (VTABLE))
 # define _IO_vtable_offset(THIS) (THIS)->_vtable_offset
 #else
 # define _IO_JUMPS_FUNC(THIS) (IO_validate_vtable (_IO_JUMPS_FILE_plus (THIS)))
+# define _IO_JUMPS_FUNC_UPDATE(THIS, VTABLE) \
+  (_IO_JUMPS_FILE_plus (THIS) = (VTABLE))
 # define _IO_vtable_offset(THIS) 0
 #endif
 #define _IO_WIDE_JUMPS_FUNC(THIS) _IO_WIDE_JUMPS(THIS)