about summary refs log tree commit diff
diff options
context:
space:
mode:
authorZack Weinberg <zackw@panix.com>2019-07-27 19:26:23 -0400
committerZack Weinberg <zackw@panix.com>2019-07-27 20:14:35 -0400
commit3f649995a112b91754b49b7fff389385ce55f54f (patch)
tree3999bdce24cbfc67c223f3610ba6dd92d59d0994
parent50ce3eae5ba304650459d4441d7d246a7cefc26f (diff)
downloadglibc-zack/gtod-no-timezone.tar.gz
glibc-zack/gtod-no-timezone.tar.xz
glibc-zack/gtod-no-timezone.zip
Remove access to legacy time zone support in gettimeofday etc. zack/gtod-no-timezone
gettimeofday and ftime are not quite fully implementable on systems
that only provide a primitive equivalent to clock_gettime, because
they can also report information about a system-wide time zone.  This
mechanism has been deprecated for many years because it can only be
configured on a system-wide basis, and because it only supports the
simplest kinds of daylight-savings rules, but we’ve supported it on a
best-effort basis until now.  This patch removes our support for it:

 * The type 'struct timezone' is still declared as a complete type in
   <sys/time.h>, but code that uses its fields (tz_minuteswest and
   tz_dsttime) will not compile.

 * Similarly, code that uses the 'timezone' and 'dstflag' fields of
   struct timeb will not compile anymore.  (This is a willful
   violation of the older iterations of XPG that included
   sys/timeb.h; the relevant conformance tests are XFAILed.)

 * Old binaries that pass a non-NULL 'tzp' pointer to gettimeofday
   will always receive a 'struct timezone' whose tz_minuteswest and
   tz_dsttime fields are zero (as if the system were operating on UTC).

 * Similarly, old binaries that call ftime will always receive a
   'struct timeb' whose timezone and dstflag fields are zero.

 * If the 'tzp' argument to settimeofday is not NULL, the call will fail
   and set errno to ENOSYS.  (This was already the case on the Hurd.)

 * glibc will always pass a second argument of NULL when invoking a
   kernel-provided gettimeofday.

 * On Alpha, the compat symbols gettimeofday@GLIBC_2.0 and
   settimeofday@GLIBC_2.0 (which used 32-bit time_t) now convert
   their arguments and call system primitives that use 64-bit time_t,
   instead of invoking legacy “osf” system calls.

ChangeLog:

	* time/sys/time.h (struct timezone): Remove tz_minuteswest
	and tz_dsttime fields; replace with padding to preserve the size.
	* time/sys/timeb.h (struct timeb): Remove timezone and dstflag
	fields; replace with padding to preserve the size.
	* conform/Makefile: XFAIL tests because struct timeb is no longer
	fully conformant with Unix98.

	* sysdeps/posix/gettimeofday.c
	* sysdeps/unix/sysv/linux/gettimeofday.c
	* sysdeps/unix/sysv/linux/aarch64/gettimeofday.c
	* sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
	* sysdeps/unix/sysv/linux/x86/gettimeofday.c
	(gettimeofday): When ‘tz’ argument is not NULL, just clear it.
	Always pass a null pointer as the second argument to a
	gettimeofday (v)syscall.

	* sysdeps/unix/bsd/ftime.c: Unconditionally clear the memory that
	was formerly the ‘timezone’ and ‘dstflag’ fields of struct timeb.

	* sysdeps/unix/syscalls.list: Remove entry for settimeofday.
	* sysdeps/unix/settimeofday.c: New file.
	(settimeofday): Fail with ENOSYS if ‘tz’ argument is not NULL.

	* sysdeps/unix/sysv/linux/alpha/syscalls.list: Remove entries for
        osf_gettimeofday, osf_settimeofday, and settimeofday.
	* sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c:
	New file.  Call the 64-bit gettimeofday, then convert to a
	32-bit struct timeval.  On overflow, saturate the struct timeval
	and fail with EOVERFLOW.
	* sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c: New file.
        Convert to a 64-bit struct timeval and call 64-bit settimeofday.
        Fail with ENOSYS if ‘tz’ argument is not NULL.

	* sunrpc/auth_des.c, sunrpc/auth_unix.c
	* sysdeps/posix/time.c, sysdeps/unix/stime.c:
	Remove unnecessary casts of NULL.

	* sysdeps/unix/sysv/linux/powerpc/time.c (time_syscall):
	Use (void *)0 instead of NULL when passing a null pointer
	as an untyped argument.

	* manual/time.texi: Remove documentation of fields of
	struct timezone.  Revise text to further emphasize that
	the second argument to gettimeofday/settimeofday should
	always be a null pointer.
-rw-r--r--NEWS49
-rw-r--r--conform/Makefile7
-rw-r--r--manual/time.texi76
-rw-r--r--sunrpc/auth_des.c4
-rw-r--r--sunrpc/auth_unix.c4
-rw-r--r--sunrpc/create_xid.c2
-rw-r--r--sunrpc/svcauth_des.c2
-rw-r--r--sysdeps/mach/gettimeofday.c4
-rw-r--r--sysdeps/posix/gettimeofday.c31
-rw-r--r--sysdeps/posix/time.c2
-rw-r--r--sysdeps/unix/bsd/ftime.c10
-rw-r--r--sysdeps/unix/settimeofday.c36
-rw-r--r--sysdeps/unix/stime.c2
-rw-r--r--sysdeps/unix/syscalls.list1
-rw-r--r--sysdeps/unix/sysv/linux/aarch64/gettimeofday.c8
-rw-r--r--sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c62
-rw-r--r--sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c51
-rw-r--r--sysdeps/unix/sysv/linux/alpha/syscalls.list3
-rw-r--r--sysdeps/unix/sysv/linux/gettimeofday.c5
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/gettimeofday.c13
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/time.c2
-rw-r--r--sysdeps/unix/sysv/linux/x86/gettimeofday.c8
-rw-r--r--time/sys/time.h4
-rw-r--r--time/sys/timeb.h5
24 files changed, 290 insertions, 101 deletions
diff --git a/NEWS b/NEWS
index ddc800ba59..f83312d276 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,55 @@ See the end for copying conditions.
 Please send GNU C library bug reports via <https://sourceware.org/bugzilla/>
 using `glibc' in the "product" field.
 
+Version 2.31
+
+Major new features:
+
+Deprecated and removed features, and other changes affecting compatibility:
+
+* The crude time zone support in ftime, gettimeofday, and settimeofday
+  has been removed.
+
+  This 4.2-BSD-era feature has been deprecated for many years, as it cannot
+  handle the full complexity of the world's timezones, but hitherto we have
+  supported it on a best-effort basis.  Changes required to support 64-bit
+  time_t on 32-bit architectures have made this no longer practical.
+
+  In this release:
+
+    * The type 'struct timezone' is still declared as a complete type in
+      <sys/time.h>, but code that uses its fields (tz_minuteswest and
+      tz_dsttime) will not compile.
+
+    * Similarly, code that uses the 'timezone' and 'dstflag' fields of
+      struct timeb will not compile anymore.
+
+    * Old binaries that pass a non-NULL 'tzp' pointer to gettimeofday will
+      always receive a 'struct timezone' whose tz_minuteswest and tz_dsttime
+      fields are zero (as if the system were operating on UTC).
+
+    * Similarly, old binaries that call ftime will always receive a
+      'struct timeb' whose timezone and dstflag fields are zero.
+
+    * If the 'tzp' argument to settimeofday is not NULL, the call will fail
+      and set errno to ENOSYS.  (This was already the case on the Hurd.)
+
+  In a future release, 'struct timezone' will be completely removed from
+  <sys/time.h>; the second argument to gettimeofday and settimeofday
+  will have type void *.  (This is already the case when strict POSIX
+  conformance is requested.)  We do not plan to change the behavior of
+  gettimeofday or ftime further.
+
+Changes to build and runtime requirements:
+
+Security related changes:
+
+The following bugs are resolved with this release:
+
+  [The release manager will add the list generated by
+  scripts/list-fixed-bugs.py just before the release.]
+
+
 Version 2.30
 
 Major new features:
diff --git a/conform/Makefile b/conform/Makefile
index 59d569c4c5..7a1b927b45 100644
--- a/conform/Makefile
+++ b/conform/Makefile
@@ -241,3 +241,10 @@ test-xfail-XPG42/ndbm.h/linknamespace = yes
 test-xfail-UNIX98/ndbm.h/linknamespace = yes
 test-xfail-XOPEN2K/ndbm.h/linknamespace = yes
 test-xfail-XOPEN2K8/ndbm.h/linknamespace = yes
+
+# Willful violation of older POSIX standards regarding the contents
+# of struct timeb: the 'timezone' and 'dstflag' fields have been
+# removed, intentionally, to flush out old programs that still use them.
+test-xfail-UNIX98/sys/timeb.h/conform = yes
+test-xfail-XOPEN2K/sys/timeb.h/conform = yes
+test-xfail-XPG42/sys/timeb.h/conform = yes
diff --git a/manual/time.texi b/manual/time.texi
index bfa46dd45b..03d74c4ae7 100644
--- a/manual/time.texi
+++ b/manual/time.texi
@@ -461,46 +461,38 @@ declared in @file{sys/time.h}.
 
 @deftp {Data Type} {struct timezone}
 @standards{BSD, sys/time.h}
-The @code{struct timezone} structure is used to hold minimal information
-about the local time zone.  It has the following members:
-
-@table @code
-@item int tz_minuteswest
-This is the number of minutes west of UTC.
-
-@item int tz_dsttime
-If nonzero, Daylight Saving Time applies during some part of the year.
-@end table
-
-The @code{struct timezone} type is obsolete and should never be used.
-Instead, use the facilities described in @ref{Time Zone Functions}.
+The @w{@code{struct timezone}} type is obsolete and should never be
+used.  @gnusystems{} do not support using @w{@code{struct timezone}}
+to represent time zone information, because it cannot represent the
+full complexity of real-world time zones.  Instead, use the facilities
+described in @ref{Time Zone Functions}.
+
+For backward compatibility, some functions take arguments of type
+@w{@code{struct timezone *}}.  New programs should invariably pass
+a null pointer for any such argument.
 @end deftp
 
 @deftypefun int gettimeofday (struct timeval *@var{tp}, struct timezone *@var{tzp})
 @standards{BSD, sys/time.h}
 @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
-@c On most GNU/Linux systems this is a direct syscall, but the posix/
-@c implementation (not used on GNU/Linux or GNU/Hurd) relies on time and
-@c localtime_r, saving and restoring tzname in an unsafe manner.
 @c On some GNU/Linux variants, ifunc resolvers are used in shared libc
 @c for vdso resolution.  ifunc-vdso-revisit.
 The @code{gettimeofday} function returns the current calendar time as
 the elapsed time since the epoch in the @code{struct timeval} structure
 indicated by @var{tp}.  (@pxref{Elapsed Time} for a description of
-@code{struct timeval}).  Information about the time zone is returned in
-the structure pointed to by @var{tzp}.  If the @var{tzp} argument is a null
-pointer, time zone information is ignored.
+@code{struct timeval}).
+
+The @var{tzp} argument should always be a null pointer.  If it is not
+a null pointer, a crude representation of the time zone may be written
+to the object it points to, or meaningless values may be written there
+instead, or the call may fail.
 
 The return value is @code{0} on success and @code{-1} on failure.  The
 following @code{errno} error condition is defined for this function:
 
 @table @code
 @item ENOSYS
-The operating system does not support getting time zone information, and
-@var{tzp} is not a null pointer.  @gnusystems{} do not
-support using @w{@code{struct timezone}} to represent time zone
-information; that is an obsolete feature of 4.3 BSD.
-Instead, use the facilities described in @ref{Time Zone Functions}.
+@var{tzp} is not a null pointer.
 @end table
 @end deftypefun
 
@@ -510,28 +502,27 @@ Instead, use the facilities described in @ref{Time Zone Functions}.
 @c On HURD, it calls host_set_time with a privileged port.  On other
 @c unix systems, it's a syscall.
 The @code{settimeofday} function sets the current calendar time in the
-system clock according to the arguments.  As for @code{gettimeofday},
-the calendar time is represented as the elapsed time since the epoch.
-As for @code{gettimeofday}, time zone information is ignored if
-@var{tzp} is a null pointer.
+system clock according to its arguments.  You must be a privileged
+user in order to use @code{settimeofday}.
 
-You must be a privileged user in order to use @code{settimeofday}.
-
-Some kernels automatically set the system clock from some source such as
-a hardware clock when they start up.  Others, including Linux, place the
-system clock in an ``invalid'' state (in which attempts to read the clock
-fail).  A call of @code{stime} removes the system clock from an invalid
-state, and system startup scripts typically run a program that calls
-@code{stime}.
+Some operating systems automatically set the system clock from some
+source such as a hardware clock when they start up.  Others place the
+system clock in an ``invalid'' state (in which attempts to read the
+clock fail) when they start up.  A call of @code{settimeofday} removes
+the system clock from an invalid state.
 
 @code{settimeofday} causes a sudden jump forwards or backwards, which
-can cause a variety of problems in a system.  Use @code{adjtime} (below)
-to make a smooth transition from one time to another by temporarily
-speeding up or slowing down the clock.
+can cause a variety of problems in a system.  Use @code{adjtime} or
+@code{adjtimex} (below) to make a smooth transition from one time to
+another by temporarily speeding up or slowing down the clock.
+
+As with @code{gettimeofday}, the calendar time is represented as the
+elapsed time since the epoch.
 
-With a Linux kernel, @code{adjtimex} does the same thing and can also
-make permanent changes to the speed of the system clock so it doesn't
-need to be corrected as often.
+As with @code{gettimeofday}, the @var{tzp} argument should always be a
+null pointer.  If it is not a null pointer, the call may fail, or the
+object pointed to may be ignored, or it may have some effect on future
+calls to @code{gettimeofday} with @var{tzp} not null.
 
 The return value is @code{0} on success and @code{-1} on failure.  The
 following @code{errno} error conditions are defined for this function:
@@ -541,7 +532,6 @@ following @code{errno} error conditions are defined for this function:
 This process cannot set the clock because it is not privileged.
 
 @item ENOSYS
-The operating system does not support setting time zone information, and
 @var{tzp} is not a null pointer.
 @end table
 @end deftypefun
diff --git a/sunrpc/auth_des.c b/sunrpc/auth_des.c
index 5b6f985bc2..d36c34006d 100644
--- a/sunrpc/auth_des.c
+++ b/sunrpc/auth_des.c
@@ -252,7 +252,7 @@ authdes_marshal (AUTH *auth, XDR *xdrs)
    * Figure out the "time", accounting for any time difference
    * with the server if necessary.
    */
-  __gettimeofday (&tval, (struct timezone *) NULL);
+  __gettimeofday (&tval, 0);
   ad->ad_timestamp.tv_sec = tval.tv_sec + ad->ad_timediff.tv_sec;
   ad->ad_timestamp.tv_usec = tval.tv_usec + ad->ad_timediff.tv_usec;
   if (ad->ad_timestamp.tv_usec >= MILLION)
@@ -453,7 +453,7 @@ synchronize (struct sockaddr *syncaddr, struct rpc_timeval *timep)
   if (rtime ((struct sockaddr_in *) syncaddr, timep, &timeout) < 0)
     return FALSE;
 
-  __gettimeofday (&mytime, (struct timezone *) NULL);
+  __gettimeofday (&mytime, 0);
   timep->tv_sec -= mytime.tv_sec;
   if (mytime.tv_usec > timep->tv_usec)
     {
diff --git a/sunrpc/auth_unix.c b/sunrpc/auth_unix.c
index b035fdd870..d87e325712 100644
--- a/sunrpc/auth_unix.c
+++ b/sunrpc/auth_unix.c
@@ -122,7 +122,7 @@ no_memory:
   /*
    * fill in param struct from the given params
    */
-  (void) __gettimeofday (&now, (struct timezone *) 0);
+  (void) __gettimeofday (&now, 0);
   aup.aup_time = now.tv_sec;
   aup.aup_machname = machname;
   aup.aup_uid = uid;
@@ -297,7 +297,7 @@ authunix_refresh (AUTH *auth)
     goto done;
 
   /* update the time and serialize in place */
-  (void) __gettimeofday (&now, (struct timezone *) 0);
+  (void) __gettimeofday (&now, 0);
   aup.aup_time = now.tv_sec;
   xdrs.x_op = XDR_ENCODE;
   XDR_SETPOS (&xdrs, 0);
diff --git a/sunrpc/create_xid.c b/sunrpc/create_xid.c
index a44187f07c..c209cd0b69 100644
--- a/sunrpc/create_xid.c
+++ b/sunrpc/create_xid.c
@@ -41,7 +41,7 @@ _create_xid (void)
     {
       struct timeval now;
 
-      __gettimeofday (&now, (struct timezone *) 0);
+      __gettimeofday (&now, 0);
       __srand48_r (now.tv_sec ^ now.tv_usec ^ pid,
 		   &__rpc_lrand48_data);
       is_initialized = pid;
diff --git a/sunrpc/svcauth_des.c b/sunrpc/svcauth_des.c
index c5a512d6f8..a87ae68bcb 100644
--- a/sunrpc/svcauth_des.c
+++ b/sunrpc/svcauth_des.c
@@ -295,7 +295,7 @@ _svcauth_des (register struct svc_req *rqst, register struct rpc_msg *msg)
 	debug ("timestamp before last seen");
 	return AUTH_REJECTEDVERF;	/* replay */
       }
-    __gettimeofday (&current, (struct timezone *) NULL);
+    __gettimeofday (&current, 0);
     current.tv_sec -= window;	/* allow for expiration */
     if (!BEFORE (&current, &timestamp))
       {
diff --git a/sysdeps/mach/gettimeofday.c b/sysdeps/mach/gettimeofday.c
index 8d0dfbb7dc..f8c9b7ce3f 100644
--- a/sysdeps/mach/gettimeofday.c
+++ b/sysdeps/mach/gettimeofday.c
@@ -28,8 +28,8 @@ __gettimeofday (struct timeval *tv, struct timezone *tz)
 {
   kern_return_t err;
 
-  if (tz != NULL)
-    *tz = (struct timezone){0, 0}; /* XXX */
+  if (tz)
+    memset (tz, 0, sizeof (struct timezone));
 
   if (err = __host_get_time (__mach_host_self (), (time_value_t *) tv))
     {
diff --git a/sysdeps/posix/gettimeofday.c b/sysdeps/posix/gettimeofday.c
index 6ba625e13e..f5c462e11b 100644
--- a/sysdeps/posix/gettimeofday.c
+++ b/sysdeps/posix/gettimeofday.c
@@ -31,34 +31,11 @@ __gettimeofday (struct timeval *tv, struct timezone *tz)
       return -1;
     }
 
-  tv->tv_sec = (long int) time ((time_t *) NULL);
-  tv->tv_usec = 0L;
+  if (tz)
+    memset (tz, 0, sizeof (struct timezone));
 
-  if (tz != NULL)
-    {
-      const time_t timer = tv->tv_sec;
-      struct tm tm;
-      const struct tm *tmp;
-
-      const long int save_timezone = __timezone;
-      const long int save_daylight = __daylight;
-      char *save_tzname[2];
-      save_tzname[0] = __tzname[0];
-      save_tzname[1] = __tzname[1];
-
-      tmp = localtime_r (&timer, &tm);
-
-      tz->tz_minuteswest = __timezone / 60;
-      tz->tz_dsttime = __daylight;
-
-      __timezone = save_timezone;
-      __daylight = save_daylight;
-      __tzname[0] = save_tzname[0];
-      __tzname[1] = save_tzname[1];
-
-      if (tmp == NULL)
-	return -1;
-    }
+  tv->tv_usec = 0;
+  tv->tv_sec = time (0);
 
   return 0;
 }
diff --git a/sysdeps/posix/time.c b/sysdeps/posix/time.c
index e1b3bc8d4c..2f7f7a6f3c 100644
--- a/sysdeps/posix/time.c
+++ b/sysdeps/posix/time.c
@@ -28,7 +28,7 @@ time (time_t *t)
   struct timeval tv;
   time_t result;
 
-  if (__gettimeofday (&tv, (struct timezone *) NULL))
+  if (__gettimeofday (&tv, 0))
     result = (time_t) -1;
   else
     result = (time_t) tv.tv_sec;
diff --git a/sysdeps/unix/bsd/ftime.c b/sysdeps/unix/bsd/ftime.c
index 3a1c6e9b01..32ce84e662 100644
--- a/sysdeps/unix/bsd/ftime.c
+++ b/sysdeps/unix/bsd/ftime.c
@@ -17,14 +17,14 @@
 
 #include <sys/timeb.h>
 #include <sys/time.h>
+#include <string.h>
 
 int
 ftime (struct timeb *timebuf)
 {
   struct timeval tv;
-  struct timezone tz;
 
-  if (__gettimeofday (&tv, &tz) < 0)
+  if (__gettimeofday (&tv, 0) < 0)
     return -1;
 
   timebuf->time = tv.tv_sec;
@@ -34,7 +34,9 @@ ftime (struct timeb *timebuf)
       ++timebuf->time;
       timebuf->millitm = 0;
     }
-  timebuf->timezone = tz.tz_minuteswest;
-  timebuf->dstflag = tz.tz_dsttime;
+
+  memset (timebuf->__preserve_historic_size, 0,
+          sizeof timebuf->__preserve_historic_size);
+
   return 0;
 }
diff --git a/sysdeps/unix/settimeofday.c b/sysdeps/unix/settimeofday.c
new file mode 100644
index 0000000000..741493b470
--- /dev/null
+++ b/sysdeps/unix/settimeofday.c
@@ -0,0 +1,36 @@
+/* settimeofday -- Set the current time of day.  Unix version.
+   Copyright (C) 2019 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <sys/time.h>
+#include <sysdep.h>
+#include <libc-symbols.h>
+
+/* Set the current time of day and timezone information.
+   This call is restricted to the super-user.  */
+int
+__settimeofday (const struct timeval *tv, const struct timezone *tz)
+{
+  if (tz)
+    {
+      __set_errno (ENOSYS);
+      return -1;
+    }
+  return INLINE_SYSCALL_CALL (settimeofday, tv, (void *)0);
+}
+weak_alias (__settimeofday, settimeofday);
diff --git a/sysdeps/unix/stime.c b/sysdeps/unix/stime.c
index b0809be400..554b3efa60 100644
--- a/sysdeps/unix/stime.c
+++ b/sysdeps/unix/stime.c
@@ -35,5 +35,5 @@ stime (const time_t *when)
 
   tv.tv_sec = *when;
   tv.tv_usec = 0;
-  return __settimeofday (&tv, (struct timezone *) 0);
+  return __settimeofday (&tv, 0);
 }
diff --git a/sysdeps/unix/syscalls.list b/sysdeps/unix/syscalls.list
index 61e5360b4d..5fedd5733d 100644
--- a/sysdeps/unix/syscalls.list
+++ b/sysdeps/unix/syscalls.list
@@ -76,7 +76,6 @@ setreuid	-	setreuid	i:ii	__setreuid	setreuid
 setrlimit	-	setrlimit	i:ip	__setrlimit setrlimit
 setsid		-	setsid		i:	__setsid	setsid
 setsockopt	-	setsockopt	i:iiibn	setsockopt	__setsockopt
-settimeofday	-	settimeofday	i:PP	__settimeofday	settimeofday
 setuid		-	setuid		i:i	__setuid	setuid
 shutdown	-	shutdown	i:ii	shutdown
 sigaction	-	sigaction	i:ipp	__sigaction	sigaction
diff --git a/sysdeps/unix/sysv/linux/aarch64/gettimeofday.c b/sysdeps/unix/sysv/linux/aarch64/gettimeofday.c
index 9180b50bf7..47330e2f83 100644
--- a/sysdeps/unix/sysv/linux/aarch64/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/aarch64/gettimeofday.c
@@ -35,7 +35,9 @@
 static int
 __gettimeofday_vsyscall (struct timeval *tv, struct timezone *tz)
 {
-  return INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+  if (tz)
+    memset (tz, 0, sizeof (struct timezone));
+  return INLINE_VSYSCALL (gettimeofday, 2, tv, (void *)0);
 }
 
 /* PREPARE_VERSION_KNOWN will need an __LP64__ ifdef when ILP32 support
@@ -61,7 +63,9 @@ __hidden_ver1 (__gettimeofday_vsyscall, __GI___gettimeofday,
 int
 __gettimeofday (struct timeval *tv, struct timezone *tz)
 {
-  return INLINE_SYSCALL (gettimeofday, 2, tv, tz);
+  if (tz)
+    memset (tz, 0, sizeof (struct timezone));
+  return INLINE_SYSCALL (gettimeofday, 2, tv, (void *)0);
 }
 libc_hidden_def (__gettimeofday)
 
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c b/sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c
new file mode 100644
index 0000000000..8e57727887
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c
@@ -0,0 +1,62 @@
+/* gettimeofday -- Get the current time of day.  Linux/Alpha/tv32 version.
+   Copyright (C) 2019 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <limits.h>
+#include <sys/time.h>
+#include <sysdep.h>
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+
+struct timeval32
+{
+    int tv_sec, tv_usec;
+};
+
+/* Get the current time of day and timezone information.  */
+int
+attribute_compat_text_section
+__gettimeofday_tv32 (struct timeval32 *tv32,
+                     struct timezone *tz)
+{
+  struct timeval tv64;
+  if (__gettimeofday (&tv64, tz))
+    return -1;
+
+  /* The tv_sec field of a 64-bit struct timeval will overflow the
+     range representable by 'int' at 2038-01-19 03:14:07 +0000.  */
+  if (tv64.tv_sec > (time_t)INT_MAX)
+    {
+      tv32.tv_sec = INT_MAX;
+      tv32.tv_usec = 0;
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+  tv32.tv_sec = (int)tv64.tv_sec;
+
+  /* The tv_usec field of a 64-bit struct timeval may be a 64-bit
+     type, but it never contains a value outside the range [0, 999999],
+     so this cast is guaranteed not to lose information.  */
+  tv32.tv_usec = (int)tv64.tv_usec;
+
+  return 0;
+}
+
+compat_symbol (libc, __gettimeofday_tv32, gettimeofday, GLIBC_2_0);
+#endif
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c b/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c
new file mode 100644
index 0000000000..2ab2f8163d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c
@@ -0,0 +1,51 @@
+/* settimeofday -- Set the current time of day.  Linux/Alpha/tv32 version.
+   Copyright (C) 2019 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <sys/time.h>
+#include <sysdep.h>
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+
+struct timeval32
+{
+    int tv_sec, tv_usec;
+};
+
+/* Set the current time of day and timezone information.
+   This call is restricted to the super-user.  */
+int
+attribute_compat_text_section
+__settimeofday_tv32 (const struct timeval32 *tv32,
+                     const struct timezone *tz)
+{
+  if (tz)
+    {
+      __set_errno (ENOSYS);
+      return -1;
+    }
+
+  struct timeval tv64;
+  tv64.tv_sec = tv32.tv_sec;
+  tv64.tv_usec = tv32.tv_usec;
+  return INLINE_SYSCALL_CALL (settimeofday, tv, (void *)0);
+}
+
+compat_symbol (libc, __settimeofday_tv32, settimeofday, GLIBC_2_0);
+#endif
diff --git a/sysdeps/unix/sysv/linux/alpha/syscalls.list b/sysdeps/unix/sysv/linux/alpha/syscalls.list
index 12cd021b60..8244f941b8 100644
--- a/sysdeps/unix/sysv/linux/alpha/syscalls.list
+++ b/sysdeps/unix/sysv/linux/alpha/syscalls.list
@@ -23,8 +23,6 @@ pciconfig_write	EXTRA	pciconfig_write	5	pciconfig_write
 pciconfig_iobase EXTRA	pciconfig_iobase 3	__pciconfig_iobase pciconfig_iobase
 
 # support old timeval32 entry points
-osf_gettimeofday -	osf_gettimeofday 2	__gettimeofday_tv32  __gettimeofday@GLIBC_2.0 gettimeofday@GLIBC_2.0
-osf_settimeofday -	osf_settimeofday 2	__settimeofday_tv32  settimeofday@GLIBC_2.0
 osf_getitimer	-	osf_getitimer	2	__getitimer_tv32  getitimer@GLIBC_2.0
 osf_setitimer	-	osf_setitimer	3	__setitimer_tv32  setitimer@GLIBC_2.0
 osf_utimes	-	osf_utimes	2	__utimes_tv32  utimes@GLIBC_2.0
@@ -33,7 +31,6 @@ osf_wait4	-	osf_wait4	4	__wait4_tv32  wait4@GLIBC_2.0
 
 # support new timeval64 entry points
 gettimeofday	-	gettimeofday	2	__GI___gettimeofday gettimeofday@@GLIBC_2.1 __gettimeofday@@GLIBC_2.1
-settimeofday	-	settimeofday	2	__settimeofday settimeofday@@GLIBC_2.1
 getitimer	-	getitimer	2	__getitimer getitimer@@GLIBC_2.1
 setitimer	-	setitimer	3	__setitimer setitimer@@GLIBC_2.1
 utimes		-	utimes		2	__utimes utimes@@GLIBC_2.1
diff --git a/sysdeps/unix/sysv/linux/gettimeofday.c b/sysdeps/unix/sysv/linux/gettimeofday.c
index a74f03825a..3509ca9530 100644
--- a/sysdeps/unix/sysv/linux/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/gettimeofday.c
@@ -18,6 +18,7 @@
 
 #include <errno.h>
 #include <sys/time.h>
+#include <string.h>
 
 #undef __gettimeofday
 
@@ -32,7 +33,9 @@
 int
 __gettimeofday (struct timeval *tv, struct timezone *tz)
 {
-  return INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+  if (tz)
+    memset (tz, 0, sizeof (struct timezone));
+  return INLINE_VSYSCALL (gettimeofday, 2, tv, (void *)0);
 }
 libc_hidden_def (__gettimeofday)
 weak_alias (__gettimeofday, gettimeofday)
diff --git a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
index 463b678ad9..e798a80ee0 100644
--- a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
@@ -22,6 +22,7 @@
 #endif
 
 #include <sys/time.h>
+#include <string.h>
 
 #ifdef SHARED
 
@@ -35,7 +36,9 @@
 int
 __gettimeofday_vsyscall (struct timeval *tv, struct timezone *tz)
 {
-  return INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+  if (tz)
+    memset (tz, 0, sizeof (struct timezone));
+  return INLINE_VSYSCALL (gettimeofday, 2, tv, (void *)0);
 }
 
 /* __GI___gettimeofday is defined as hidden and for ppc32 it enables the
@@ -54,7 +57,9 @@ __gettimeofday_vsyscall (struct timeval *tv, struct timezone *tz)
 static int
 __gettimeofday_syscall (struct timeval *tv, struct timezone *tz)
 {
-  return INLINE_SYSCALL (gettimeofday, 2, tv, tz);
+  if (tz)
+    memset (tz, 0, sizeof (struct timezone));
+  return INLINE_SYSCALL (gettimeofday, 2, tv, (void *)0);
 }
 
 # define INIT_ARCH()						\
@@ -76,7 +81,9 @@ libc_hidden_def (__gettimeofday)
 int
 __gettimeofday (struct timeval *tv, struct timezone *tz)
 {
-  return INLINE_SYSCALL (gettimeofday, 2, tv, tz);
+  if (tz)
+    memset (tz, 0, sizeof (struct timezone));
+  return INLINE_SYSCALL (gettimeofday, 2, tv, (void *)0);
 }
 libc_hidden_def (__gettimeofday)
 
diff --git a/sysdeps/unix/sysv/linux/powerpc/time.c b/sysdeps/unix/sysv/linux/powerpc/time.c
index cb3e8b9a73..42b0d2d562 100644
--- a/sysdeps/unix/sysv/linux/powerpc/time.c
+++ b/sysdeps/unix/sysv/linux/powerpc/time.c
@@ -56,7 +56,7 @@ time_syscall (time_t *t)
   struct timeval tv;
   time_t result;
 
-  if (INLINE_VSYSCALL (gettimeofday, 2, &tv, NULL) < 0)
+  if (INLINE_VSYSCALL (gettimeofday, 2, &tv, (void *)0) < 0)
     result = (time_t) -1;
   else
     result = (time_t) tv.tv_sec;
diff --git a/sysdeps/unix/sysv/linux/x86/gettimeofday.c b/sysdeps/unix/sysv/linux/x86/gettimeofday.c
index 8886ccd707..58a8763ef9 100644
--- a/sysdeps/unix/sysv/linux/x86/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/x86/gettimeofday.c
@@ -26,7 +26,9 @@
 static int
 __gettimeofday_syscall (struct timeval *tv, struct timezone *tz)
 {
-  return INLINE_SYSCALL (gettimeofday, 2, tv, tz);
+  if (tz)
+    memset (tz, 0, sizeof (struct timezone));
+  return INLINE_SYSCALL (gettimeofday, 2, tv, (void *)0);
 }
 
 # ifndef __gettimeofday_type
@@ -52,7 +54,9 @@ libc_hidden_def (__gettimeofday)
 int
 __gettimeofday (struct timeval *tv, struct timezone *tz)
 {
-  return INLINE_SYSCALL (gettimeofday, 2, tv, tz);
+  if (tz)
+    memset (tz, 0, sizeof (struct timezone));
+  return INLINE_SYSCALL (gettimeofday, 2, tv, (void *)0);
 }
 libc_hidden_def (__gettimeofday)
 
diff --git a/time/sys/time.h b/time/sys/time.h
index 5dbc7fc627..2d5984204f 100644
--- a/time/sys/time.h
+++ b/time/sys/time.h
@@ -51,8 +51,8 @@ __BEGIN_DECLS
    This is obsolete and should never be used.  */
 struct timezone
   {
-    int tz_minuteswest;		/* Minutes west of GMT.  */
-    int tz_dsttime;		/* Nonzero if DST is ever in effect.  */
+    /* Formerly: int tz_minuteswest; int tz_dsttime;  */
+    char __preserve_historic_size [2 * sizeof (int)];
   };
 
 typedef struct timezone *__restrict __timezone_ptr_t;
diff --git a/time/sys/timeb.h b/time/sys/timeb.h
index 6333e8074d..11f47e9d6b 100644
--- a/time/sys/timeb.h
+++ b/time/sys/timeb.h
@@ -30,8 +30,9 @@ struct timeb
   {
     time_t time;		/* Seconds since epoch, as from `time'.  */
     unsigned short int millitm;	/* Additional milliseconds.  */
-    short int timezone;		/* Minutes west of GMT.  */
-    short int dstflag;		/* Nonzero if Daylight Savings Time used.  */
+
+    /* Formerly: short int timezone; short int dstflag;  */
+    char __preserve_historic_size [2 * sizeof (short int)];
   };
 
 /* Fill in TIMEBUF with information about the current time.  */