unofficial mirror of libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/6] y2038: Linux: Provide __clock_* functions supporting 64 bit time
@ 2019-04-14 22:08 Lukasz Majewski
  2019-04-14 22:08 ` [PATCH 1/6] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
                   ` (10 more replies)
  0 siblings, 11 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-14 22:08 UTC (permalink / raw)
  To: libc-alpha; +Cc: Paul Eggert, Joseph Myers, Lukasz Majewski

This patch set introduces the conversion of __clock_{settime|
gettime|getres|nanosleep} to explicit 64 bit struct __timespec64
arguments. As a result those functions are now Y2038 safe

To achieve the above goal - new, internal to glibc,
struct __timespec64 has been also introduced as well as
helper functions to handle time conversions on 32 bit systems.

The code from this patch set uses new clock_* syscalls (explicit
64 bits) from Linux kernel (5.1+) as well

This work is (loosely) based on a previous development/patches:
https://libc-alpha.sourceware.narkive.com/zniMOWui/rfc-patch-00-52-make-glibc-y2038-proof#post68

Those patches shall be applied on top of:
https://github.com/lmajewski/y2038_glibc/commit/c17d6107d205026f476076948269763f5d177481
https://github.com/lmajewski/y2038_glibc/commit/a9835a888842078ea4d317086375d8f518a490d7

Github branch (including the y2038 conversion example):
https://github.com/lmajewski/y2038_glibc/commits/Y2038-2.29-glibc-__clock-internal-struct-timespec-v1


Shall be used with provided meta-y2038 for development and testing:
https://github.com/lmajewski/meta-y2038

I've used guidelines from:
https://www.gnu.org/software/libc/manual/html_mono/libc.html
"D.2.1 64-bit time symbol handling in the GNU C Library"
to convert *clock_settime*.

and most notably from:
https://sourceware.org/glibc/wiki/Y2038ProofnessDesign#clock_gettime.28.29

Comments are more than welcome.


Lukasz Majewski (6):
  y2038: Introduce internal for glibc struct __timespec64
  y2038: Provide conversion helpers for struct __timespec64
  y2038: linux: Provide __clock_settime64 implementation
  y2038: linux: Provide __clock_getres64 implementation
  y2038: linux: Provide __clock_gettime64 implementation
  y2038: linux: Provide __clock_nanosleep64 implementation

 include/time.h                            | 142 ++++++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/clock_getres.c    |  33 ++++++-
 sysdeps/unix/sysv/linux/clock_gettime.c   |  33 ++++++-
 sysdeps/unix/sysv/linux/clock_nanosleep.c |  52 ++++++++++-
 sysdeps/unix/sysv/linux/clock_settime.c   |  34 ++++++-
 5 files changed, 285 insertions(+), 9 deletions(-)

-- 
2.11.0


^ permalink raw reply	[flat|nested] 111+ messages in thread

* [PATCH 1/6] y2038: Introduce internal for glibc struct __timespec64
  2019-04-14 22:08 [PATCH 0/6] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
@ 2019-04-14 22:08 ` Lukasz Majewski
  2019-04-14 22:08 ` [PATCH 2/6] y2038: Provide conversion helpers for " Lukasz Majewski
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-14 22:08 UTC (permalink / raw)
  To: libc-alpha; +Cc: Paul Eggert, Joseph Myers, Lukasz Majewski

This type is a glibc's type similar to struct timespec
but whose tv_sec field is a __time64_t rather than a time_t,
which makes it Y2038-proof and usable to pass between user
code and Y2038-proof kernel syscalls (e.g. clock_gettime()).

To support passing this structure to the kernel - the tv_pad,
32 bit padding field has been introduced. The placement of it
depends on endiannes of the SoC.

Tested on x86_64 and ARM.

* include/time.h: Add struct __timespec64 definition
---
 include/time.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/include/time.h b/include/time.h
index ac3163c2a5..a4a06201d5 100644
--- a/include/time.h
+++ b/include/time.h
@@ -5,6 +5,7 @@
 # include <bits/types/locale_t.h>
 # include <stdbool.h>
 # include <time/mktime-internal.h>
+# include <endian.h>
 
 extern __typeof (strftime_l) __strftime_l;
 libc_hidden_proto (__strftime_l)
@@ -52,6 +53,27 @@ extern void __tz_compute (__time64_t timer, struct tm *tm, int use_localtime)
   __THROW attribute_hidden;
 
 #if __TIMESIZE == 64
+# define __timespec64 timespec
+#else
+/* The glibc Y2038-proof struct __timespec64 structure for a time value.
+   To keep things Posix-ish, we keep the nanoseconds field a 32-bit
+   signed long, but since the Linux field is a 64-bit signed int, we
+   pad our tv_nsec with a 32-bit bitfield, which should always be 0. */
+
+struct __timespec64
+{
+  __time64_t tv_sec;         /* Seconds */
+# if BYTE_ORDER == BIG_ENDIAN
+  int tv_pad: 32;            /* Padding named for checking/setting */
+  __int32_t tv_nsec;         /* Nanoseconds */
+# else
+  __int32_t tv_nsec;         /* Nanoseconds */
+  int tv_pad: 32;            /* Padding named for checking/setting */
+# endif
+};
+#endif
+
+#if __TIMESIZE == 64
 # define __ctime64 ctime
 #else
 extern char *__ctime64 (const __time64_t *__timer) __THROW;
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH 2/6] y2038: Provide conversion helpers for struct __timespec64
  2019-04-14 22:08 [PATCH 0/6] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
  2019-04-14 22:08 ` [PATCH 1/6] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
@ 2019-04-14 22:08 ` Lukasz Majewski
  2019-04-14 22:08 ` [PATCH 3/6] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-14 22:08 UTC (permalink / raw)
  To: libc-alpha; +Cc: Paul Eggert, Joseph Myers, Lukasz Majewski

Those functions allow easy conversion between Y2038 safe struct
 __timespec64 and other time related data structures.

Moreover, those functions are NOT compiled when one runs 64 bit system
(the __TIMESIZE == 64) and are used only for 32 bit wrappers (
like __clock_gettime).

* include/time.h (valid_timeval_to_timespec64): Add.
* include/time.h (valid_timespec_to_timespec64): Likewise.
* include/time.h (valid_timespec64_to_timespec): Likewise.
* include/time.h (valid_timespec64_to_timeval): Likewise.
* include/time.h (IS_VALID_NANOSECONDS): Likewise.
* include/time.h (timespec_to_timespec64): Likewise.
* include/time.h (timespec64_to_timespec): Likewise.
* include/time.h (timespec64_to_timeval): Likewise.
---
 include/time.h | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/include/time.h b/include/time.h
index a4a06201d5..9eed500cf1 100644
--- a/include/time.h
+++ b/include/time.h
@@ -178,5 +178,92 @@ in_time_t_range (__time64_t t)
   return s == t;
 }
 
+# if __TIMESIZE != 64
+/* Convert a known valid struct timeval into a struct __timespec64.  */
+static inline void
+valid_timeval_to_timespec64 (const struct timeval *tv32,
+			     struct __timespec64 *ts64)
+{
+  ts64->tv_sec = tv32->tv_sec;
+  ts64->tv_nsec = tv32->tv_usec * 1000;
+}
+
+/* Convert a known valid struct timespec into a struct __timespec64.  */
+static inline void
+valid_timespec_to_timespec64 (const struct timespec *ts32,
+			      struct __timespec64 *ts64)
+{
+  ts64->tv_sec = ts32->tv_sec;
+  ts64->tv_nsec = ts32->tv_nsec;
+  /* We only need to zero ts64->tv_pad if we pass it to the kernel.  */
+}
+
+/* Convert a known valid struct __timespec64 into a struct timespec.  */
+static inline void
+valid_timespec64_to_timespec (const struct __timespec64 *ts64,
+			      struct timespec *ts32)
+{
+  ts32->tv_sec = (time_t) ts64->tv_sec;
+  ts32->tv_nsec = ts64->tv_nsec;
+}
+
+/* Convert a known valid struct __timespec64 into a struct timeval.  */
+static inline void
+valid_timespec64_to_timeval (const struct __timespec64 *ts64,
+			     struct timeval *tv32)
+{
+  tv32->tv_sec = (time_t) ts64->tv_sec;
+  tv32->tv_usec = ts64->tv_nsec / 1000;
+}
+
+/* Check if a value lies with the valid nanoseconds range.  */
+#define IS_VALID_NANOSECONDS(ns) ((ns) >= 0 && (ns) <= 999999999)
+
+/* Check and convert a struct timespec into a struct __timespec64.  */
+static inline bool
+timespec_to_timespec64 (const struct timespec *ts32,
+                        struct __timespec64 *ts64)
+{
+  /* Check that ts32 holds a valid count of nanoseconds.  */
+  if (! IS_VALID_NANOSECONDS (ts32->tv_nsec))
+    return false;
+  /* All ts32 fields can fit in ts64, so copy them.  */
+  valid_timespec_to_timespec64 (ts32, ts64);
+  /* We only need to zero ts64->tv_pad if we pass it to the kernel.  */
+  return true;
+}
+
+/* Check and convert a struct __timespec64 into a struct timespec.  */
+static inline bool
+timespec64_to_timespec (const struct __timespec64 *ts64,
+                        struct timespec *ts32)
+{
+  /* Check that tv_nsec holds a valid count of nanoseconds.  */
+  if (! IS_VALID_NANOSECONDS (ts64->tv_nsec))
+    return false;
+  /* Check that tv_sec can fit in a __time_t.  */
+  if (! in_time_t_range (ts64->tv_sec))
+    return false;
+  /* All ts64 fields can fit in ts32, so copy them.  */
+  valid_timespec64_to_timespec (ts64, ts32);
+  return true;
+}
+
+/* Check and convert a struct __timespec64 into a struct timeval.  */
+static inline bool
+timespec64_to_timeval (const struct __timespec64 *ts64,
+                       struct timeval *tv32)
+{
+  /* Check that tv_nsec holds a valid count of nanoseconds.  */
+  if (! IS_VALID_NANOSECONDS (ts64->tv_nsec))
+    return false;
+  /* Check that tv_sec can fit in a __time_t.  */
+  if (! in_time_t_range (ts64->tv_sec))
+    return false;
+  /* All ts64 fields can fit in tv32, so copy them.  */
+  valid_timespec64_to_timeval (ts64, tv32);
+  return true;
+}
+# endif
 #endif
 #endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH 3/6] y2038: linux: Provide __clock_settime64 implementation
  2019-04-14 22:08 [PATCH 0/6] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
  2019-04-14 22:08 ` [PATCH 1/6] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
  2019-04-14 22:08 ` [PATCH 2/6] y2038: Provide conversion helpers for " Lukasz Majewski
@ 2019-04-14 22:08 ` Lukasz Majewski
  2019-04-17 22:08   ` Joseph Myers
  2019-04-20  0:20   ` Stepan Golosunov
  2019-04-14 22:08 ` [PATCH 4/6] y2038: linux: Provide __clock_getres64 implementation Lukasz Majewski
                   ` (7 subsequent siblings)
  10 siblings, 2 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-14 22:08 UTC (permalink / raw)
  To: libc-alpha; +Cc: Paul Eggert, Joseph Myers, Lukasz Majewski

This patch provides new __clock_settime64 explicit 64 bit function for
setting the time. Moreover, a 32 bit version - __clock_settime has been
refactored to internally use __clock_settime64.

The __clock_settime is now supposed to be used on 32 bit systems -
hence the necessary checks and conversion to 64 bit type. After this
change it is intrinsically Y2038 safe.

The new 64 bit syscall (clock_settime64) available from Linux
5.1+ has been used when applicable on 32 bit systems.
The execution path on 64 bit systems has not been changed or affected in
any way.

Tests:
- The code has been tested with x86_64/x86 (native compilation):
make PARALLELMFLAGS="-j8" && make xcheck PARALLELMFLAGS="-j8"

- Run specific tests on ARM/x86 32bit systems (qemu):
https://github.com/lmajewski/meta-y2038
and run tests:
https://github.com/lmajewski/y2038-tests/commits/master
on kernels with and without 64 bit time support.

No regressions were observed.

* include/time.h (__clock_settime64):
  Add __clock_settime alias according to __TIMESIZE define
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime):
  Refactor this function to be used only on 32 bit machines as a wrapper
  on __clock_settime64.
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime64): Add
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime64):
  Use clock_settime64 kernel syscall (available from 5.1-rc1+ Linux) by
  32 bit Y2038 safe systems
---
 include/time.h                          |  8 ++++++++
 sysdeps/unix/sysv/linux/clock_settime.c | 34 ++++++++++++++++++++++++++++++---
 2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/include/time.h b/include/time.h
index 9eed500cf1..33eee8eb9a 100644
--- a/include/time.h
+++ b/include/time.h
@@ -124,6 +124,14 @@ extern __time64_t __timegm64 (struct tm *__tp) __THROW;
 libc_hidden_proto (__timegm64)
 #endif
 
+#if __TIMESIZE == 64
+# define __clock_settime64 __clock_settime
+#else
+extern int __clock_settime64 (clockid_t clock_id,
+                              const struct __timespec64 *tp);
+libc_hidden_proto (__clock_settime64)
+#endif
+
 /* Compute the `struct tm' representation of T,
    offset OFFSET seconds east of UTC,
    and store year, yday, mon, mday, wday, hour, min, sec into *TP.
diff --git a/sysdeps/unix/sysv/linux/clock_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c
index d837e3019c..a1ea1cac28 100644
--- a/sysdeps/unix/sysv/linux/clock_settime.c
+++ b/sysdeps/unix/sysv/linux/clock_settime.c
@@ -19,11 +19,9 @@
 #include <sysdep.h>
 #include <time.h>
 
-#include "kernel-posix-cpu-timers.h"
-
 /* Set CLOCK to value TP.  */
 int
-__clock_settime (clockid_t clock_id, const struct timespec *tp)
+__clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
 {
   /* Make sure the time cvalue is OK.  */
   if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
@@ -32,6 +30,36 @@ __clock_settime (clockid_t clock_id, const struct timespec *tp)
       return -1;
     }
 
+#if defined (__TIMESIZE) && __TIMESIZE != 64
+# if defined __NR_clock_settime64
+  /* Make sure that passed __timespec64 struct pad is 0.  */
+  struct __timespec64 ts = *tp;
+  ts.tv_pad = 0;
+  return INLINE_SYSCALL_CALL (clock_settime64, clock_id, &ts);
+# else
+  struct timespec ts32;
+  valid_timespec64_to_timespec(tp, &ts32);
+  return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);
+# endif
+#else
   return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp);
+#endif
 }
 weak_alias (__clock_settime, clock_settime)
+
+#if __TIMESIZE != 64
+int
+__clock_settime (clockid_t clock_id, const struct timespec *tp)
+{
+  struct __timespec64 ts64;
+
+  if (! in_time_t_range (tp->tv_sec))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  valid_timespec_to_timespec64 (tp, &ts64);
+  return __clock_settime64 (clock_id, &ts64);
+}
+#endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH 4/6] y2038: linux: Provide __clock_getres64 implementation
  2019-04-14 22:08 [PATCH 0/6] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
                   ` (2 preceding siblings ...)
  2019-04-14 22:08 ` [PATCH 3/6] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
@ 2019-04-14 22:08 ` Lukasz Majewski
  2019-04-14 22:08 ` [PATCH 5/6] y2038: linux: Provide __clock_gettime64 implementation Lukasz Majewski
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-14 22:08 UTC (permalink / raw)
  To: libc-alpha; +Cc: Paul Eggert, Joseph Myers, Lukasz Majewski

This patch provides new __clock_getres64 explicit 64 bit function for
getting the resolution (precision) of specified clock ID. Moreover, a
32 bit version - __clock_getres has been refactored to internally use
__clock_getres64.

The __clock_getres is now supposed to be used on 32 bit systems -
hence the necessary checks and conversion to 64 bit type. After this
change it is intrinsically Y2038 safe.

The new 64 bit syscall (clock_getres_time64) available from Linux
5.1+ has been used when applicable on 32 bit systems.
The execution path on 64 bit systems has not been changed or affected
in any way.

Tests:
- The code has been tested with x86_64/x86 (native compilation):
make PARALLELMFLAGS="-j8" && make xcheck PARALLELMFLAGS="-j8"

- Run specific tests on ARM/x86 32bit systems (qemu):
https://github.com/lmajewski/meta-y2038
and run tests:
https://github.com/lmajewski/y2038-tests/commits/master
on kernels with and without 64 bit time support.

No regressions were observed.

* include/time.h (__clock_getres64):
  Add __clock_getres alias according to __TIMESIZE define
* sysdeps/unix/sysv/linux/clock_getres.c (__clock_getres):
  Refactor this function to be used only on 32 bit machines as a
  wrapper on __clock_getres64.
* sysdeps/unix/sysv/linux/clock_getres.c (__clock_getres64): Add
* sysdeps/unix/sysv/linux/clock_getres.c (__clock_getres64):
  Use clock_getres_time6464 kernel syscall (available from 5.1-rc1+
  Linux) by 32 bit Y2038 safe systems
---
 include/time.h                         |  8 ++++++++
 sysdeps/unix/sysv/linux/clock_getres.c | 33 ++++++++++++++++++++++++++++++++-
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/include/time.h b/include/time.h
index 33eee8eb9a..20b9974078 100644
--- a/include/time.h
+++ b/include/time.h
@@ -132,6 +132,14 @@ extern int __clock_settime64 (clockid_t clock_id,
 libc_hidden_proto (__clock_settime64)
 #endif
 
+#if __TIMESIZE == 64
+# define __clock_getres64 __clock_getres
+#else
+extern int __clock_getres64 (clockid_t clock_id,
+                             struct __timespec64 *tp);
+libc_hidden_proto (__clock_getres64);
+#endif
+
 /* Compute the `struct tm' representation of T,
    offset OFFSET seconds east of UTC,
    and store year, yday, mon, mday, wday, hour, min, sec into *TP.
diff --git a/sysdeps/unix/sysv/linux/clock_getres.c b/sysdeps/unix/sysv/linux/clock_getres.c
index 24b2299938..3f6c24f1dd 100644
--- a/sysdeps/unix/sysv/linux/clock_getres.c
+++ b/sysdeps/unix/sysv/linux/clock_getres.c
@@ -28,8 +28,39 @@
 
 /* Get resolution of clock.  */
 int
-__clock_getres (clockid_t clock_id, struct timespec *res)
+__clock_getres64 (clockid_t clock_id, struct __timespec64 *res)
 {
+#if defined (__TIMESIZE) && __TIMESIZE != 64
+# if defined __NR_clock_getres_time64
+  return INLINE_VSYSCALL (clock_getres_time64, 2, clock_id, res);
+# else
+  struct timespec ts32;
+  int retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, &ts32);
+  if (! retval)
+    valid_timespec_to_timespec64(&ts32, res);
+
+  return retval;
+# endif
+#else
   return INLINE_VSYSCALL (clock_getres, 2, clock_id, res);
+#endif
 }
 weak_alias (__clock_getres, clock_getres)
+
+#if __TIMESIZE != 64
+int
+__clock_getres (clockid_t clock_id, struct timespec *res)
+{
+  struct __timespec64 ts64;
+  int retval;
+
+  retval = __clock_getres64 (clock_id, &ts64);
+  if (! retval && res && ! timespec64_to_timespec (&ts64, res))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  return retval;
+}
+#endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH 5/6] y2038: linux: Provide __clock_gettime64 implementation
  2019-04-14 22:08 [PATCH 0/6] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
                   ` (3 preceding siblings ...)
  2019-04-14 22:08 ` [PATCH 4/6] y2038: linux: Provide __clock_getres64 implementation Lukasz Majewski
@ 2019-04-14 22:08 ` Lukasz Majewski
  2019-04-14 22:08 ` [PATCH 6/6] y2038: linux: Provide __clock_nanosleep64 implementation Lukasz Majewski
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-14 22:08 UTC (permalink / raw)
  To: libc-alpha; +Cc: Paul Eggert, Joseph Myers, Lukasz Majewski

This patch provides new __clock_gettime64 explicit 64 bit function for
getting the value of specified clock ID. Moreover, a
32 bit version - __clock_gettime has been refactored to internally use
__clock_gettime64.

The __clock_gettime is now supposed to be used on 32 bit systems -
hence the necessary checks and conversion to 64 bit type. After this
change it is intrinsically Y2038 safe.

The new 64 bit syscall (clock_gettime64) available from Linux
5.1+ has been used when applicable on 32 bit systems.
The execution path on 64 bit systems has not been changed or affected
in any way.

Tests:
- The code has been tested with x86_64/x86 (native compilation):
make PARALLELMFLAGS="-j8" && make xcheck PARALLELMFLAGS="-j8"

- Run specific tests on ARM/x86 32bit systems (qemu):
https://github.com/lmajewski/meta-y2038
and run tests:
https://github.com/lmajewski/y2038-tests/commits/master
on kernels with and without 64 bit time support.

No regressions were observed.

* include/time.h (__clock_gettime64):
  Add __clock_gettime alias according to __TIMESIZE define
* sysdeps/unix/sysv/linux/clock_gettime.c (__clock_gettime):
  Refactor this function to be used only on 32 bit machines as a
  wrapper on __clock_gettime64.
* sysdeps/unix/sysv/linux/clock_gettime.c (__clock_gettime64): Add
* sysdeps/unix/sysv/linux/clock_gettime.c (__clock_gettime64):
  Use clock_gettime64 kernel syscall (available from 5.1-rc1+
  Linux) by 32 bit Y2038 safe systems
---
 include/time.h                          |  8 ++++++++
 sysdeps/unix/sysv/linux/clock_gettime.c | 33 ++++++++++++++++++++++++++++++++-
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/include/time.h b/include/time.h
index 20b9974078..7176ddbb84 100644
--- a/include/time.h
+++ b/include/time.h
@@ -133,6 +133,14 @@ libc_hidden_proto (__clock_settime64)
 #endif
 
 #if __TIMESIZE == 64
+# define __clock_gettime64 __clock_gettime
+#else
+extern int __clock_gettime64 (clockid_t clock_id,
+                              struct __timespec64 *tp);
+libc_hidden_proto (__clock_gettime64);
+#endif
+
+#if __TIMESIZE == 64
 # define __clock_getres64 __clock_getres
 #else
 extern int __clock_getres64 (clockid_t clock_id,
diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c
index 5fc47fb7dc..fd94c6fec4 100644
--- a/sysdeps/unix/sysv/linux/clock_gettime.c
+++ b/sysdeps/unix/sysv/linux/clock_gettime.c
@@ -28,9 +28,40 @@
 
 /* Get current value of CLOCK and store it in TP.  */
 int
-__clock_gettime (clockid_t clock_id, struct timespec *tp)
+__clock_gettime64 (clockid_t clock_id, struct __timespec64 *tp)
 {
+#if defined (__TIMESIZE) && __TIMESIZE != 64
+# if defined __NR_clock_gettime64
+  return INLINE_SYSCALL_CALL (clock_gettime64, clock_id, tp);
+# else
+  struct timespec ts32;
+  int retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32);
+  if (! retval)
+    valid_timespec_to_timespec64(&ts32, tp);
+
+  return retval;
+# endif
+#else
   return INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp);
+#endif
 }
 weak_alias (__clock_gettime, clock_gettime)
 libc_hidden_def (__clock_gettime)
+
+#if __TIMESIZE != 64
+int
+__clock_gettime (clockid_t clock_id, struct timespec *tp)
+{
+  struct __timespec64 ts64;
+  int retval;
+
+  retval = __clock_gettime64 (clock_id, &ts64);
+  if (! retval && ! timespec64_to_timespec (&ts64, tp))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  return retval;
+}
+#endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH 6/6] y2038: linux: Provide __clock_nanosleep64 implementation
  2019-04-14 22:08 [PATCH 0/6] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
                   ` (4 preceding siblings ...)
  2019-04-14 22:08 ` [PATCH 5/6] y2038: linux: Provide __clock_gettime64 implementation Lukasz Majewski
@ 2019-04-14 22:08 ` Lukasz Majewski
  2019-04-17 22:11   ` Joseph Myers
  2019-04-29 10:46 ` [PATCH v2 0/7] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-14 22:08 UTC (permalink / raw)
  To: libc-alpha; +Cc: Paul Eggert, Joseph Myers, Lukasz Majewski

This patch provides new __clock_nanosleep64 explicit 64 bit function
for sleeping specified time on specified clock ID. Moreover, a
32 bit version - __clock_nanosleep has been refactored to internally
use __clock_nanosleep64.

The __clock_nanosleep is now supposed to be used on 32 bit systems -
hence the necessary checks and conversions to 64 bit type. After this
change it is intrinsically Y2038 safe.

The new 64 bit syscall (clock_nanosleep_time64) available from Linux
5.1+ has been used when applicable on 32 bit systems.
The execution path on 64 bit systems has not been changed or affected
in any way.

Tests:
- The code has been tested with x86_64/x86 (native compilation):
make PARALLELMFLAGS="-j8" && make xcheck PARALLELMFLAGS="-j8"

- Run specific tests on ARM/x86 32bit systems (qemu):
https://github.com/lmajewski/meta-y2038
and run tests:
https://github.com/lmajewski/y2038-tests/commits/master
on kernels with and without 64 bit time support.

No regressions were observed.

* include/time.h (__clock_nanosleep64):
  Add __clock_nanosleep alias according to __TIMESIZE define
* sysdeps/unix/sysv/linux/clock_nanosleep.c (__clock_nanosleep):
  Refactor this function to be used only on 32 bit machines as a
  wrapper on __clock_nanosleep64.
* sysdeps/unix/sysv/linux/clock_nanosleep.c (__clock_nanosleep64):
  Add
* sysdeps/unix/sysv/linux/clock_nanosleep.c (__clock_nanosleep64):
  Use clock_nanosleep_time64 kernel syscall (available from
  5.1-rc1+ Linux) by 32 bit Y2038 safe systems
---
 include/time.h                            |  9 ++++++
 sysdeps/unix/sysv/linux/clock_nanosleep.c | 52 ++++++++++++++++++++++++++++---
 2 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/include/time.h b/include/time.h
index 7176ddbb84..75f3456017 100644
--- a/include/time.h
+++ b/include/time.h
@@ -148,6 +148,15 @@ extern int __clock_getres64 (clockid_t clock_id,
 libc_hidden_proto (__clock_getres64);
 #endif
 
+#if __TIMESIZE == 64
+# define __clock_nanosleep64 __clock_nanosleep
+#else
+extern int __clock_nanosleep64 (clockid_t clock_id, int flags,
+                                const struct __timespec64 *req,
+                                struct __timespec64 *rem);
+libc_hidden_proto (__clock_nanosleep64);
+#endif
+
 /* Compute the `struct tm' representation of T,
    offset OFFSET seconds east of UTC,
    and store year, yday, mon, mday, wday, hour, min, sec into *TP.
diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c
index 0cb6614dc9..3f99b5df00 100644
--- a/sysdeps/unix/sysv/linux/clock_nanosleep.c
+++ b/sysdeps/unix/sysv/linux/clock_nanosleep.c
@@ -25,8 +25,8 @@
 /* We can simply use the syscall.  The CPU clocks are not supported
    with this function.  */
 int
-__clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
-		   struct timespec *rem)
+__clock_nanosleep64 (clockid_t clock_id, int flags,
+                     const struct __timespec64 *req, struct __timespec64 *rem)
 {
   if (clock_id == CLOCK_THREAD_CPUTIME_ID)
     return EINVAL;
@@ -36,9 +36,53 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
   /* If the call is interrupted by a signal handler or encounters an error,
      it returns a positive value similar to errno.  */
   INTERNAL_SYSCALL_DECL (err);
+#if defined (__TIMESIZE) && __TIMESIZE != 64
+# if defined __NR_clock_nanosleep_time64
+  struct __timespec64 ts = *req;
+  ts.tv_pad = 0;
+  int r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err, clock_id,
+                                   flags, &ts, rem);
+# else
+  struct timespec req32, rem32;
+  valid_timespec64_to_timespec(req, &req32);
+  int r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, err, clock_id, flags,
+                                   &req32, &rem32);
+
+  if (! INTERNAL_SYSCALL_ERROR_P (r, err))
+      valid_timespec_to_timespec64(&rem32, rem);
+# endif
+#else
   int r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, err, clock_id, flags,
-				   req, rem);
+                                   req, rem);
+#endif
   return (INTERNAL_SYSCALL_ERROR_P (r, err)
-	  ? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
+          ? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
 }
 weak_alias (__clock_nanosleep, clock_nanosleep)
+
+#if __TIMESIZE != 64
+int
+__clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
+                   struct timespec *rem)
+{
+  struct __timespec64 req64, rem64;
+  int retval;
+
+  if (! in_time_t_range (req->tv_sec))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  valid_timespec_to_timespec64 (req, &req64);
+  retval = __clock_nanosleep64 (clock_id, flags, &req64, &rem64);
+
+  if (! retval && rem && ! timespec64_to_timespec (&rem64, rem))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  return retval;
+}
+#endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* Re: [PATCH 3/6] y2038: linux: Provide __clock_settime64 implementation
  2019-04-14 22:08 ` [PATCH 3/6] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
@ 2019-04-17 22:08   ` Joseph Myers
  2019-04-18  6:46     ` Lukasz Majewski
  2019-04-20  0:20   ` Stepan Golosunov
  1 sibling, 1 reply; 111+ messages in thread
From: Joseph Myers @ 2019-04-17 22:08 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: libc-alpha, Paul Eggert

On Mon, 15 Apr 2019, Lukasz Majewski wrote:

> The new 64 bit syscall (clock_settime64) available from Linux
> 5.1+ has been used when applicable on 32 bit systems.
> The execution path on 64 bit systems has not been changed or affected in
> any way.

Is this unchanged specifically because of __TIMESIZE conditionals in the 
code (so that it doesn't matter whether the 64-bit systems define any new 
syscall names)?

Also, I don't see any __ASSUME_* / ENOSYS handling in this patch.  As 
usual, for any new syscall that might be used in code that could also use 
an older syscall:

* If the appropriate __ASSUME_* is defined, the new syscall can simply be 
used unconditionally.

* If the appropriate __ASSUME_* is not defined, there needs to be runtime 
fallback to the old syscall if the new one returns an ENOSYS error (of 
course, that runtime fallback needs to check for the time overflowing the 
32-bit range and give an appropriate error in that case, before calling 
the 32-bit syscall - and it's necessary to figure out what the priority 
should be of errors for invalid nanoseconds values versus overflowing 
seconds).  It is normal and expected for the kernel headers used to build 
glibc to be (much) newer than the oldest kernel version supported by the 
resulting glibc binaries at runtime.

This __ASSUME_* macro definition in kernel-features.h would need a 
multi-paragraph comment discussing exactly what the semantics of such 
__ASSUME_* macros are in the context of the sets of syscall names and 
numbers present on different kinds of Linux kernel architectures.

> +#if __TIMESIZE != 64
> +int
> +__clock_settime (clockid_t clock_id, const struct timespec *tp)
> +{
> +  struct __timespec64 ts64;
> +
> +  if (! in_time_t_range (tp->tv_sec))
> +    {
> +      __set_errno (EOVERFLOW);
> +      return -1;
> +    }

I don't see how an overflow check makes sense in this context (converting 
a 32-bit timespec to a 64-bit one).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH 6/6] y2038: linux: Provide __clock_nanosleep64 implementation
  2019-04-14 22:08 ` [PATCH 6/6] y2038: linux: Provide __clock_nanosleep64 implementation Lukasz Majewski
@ 2019-04-17 22:11   ` Joseph Myers
  2019-04-18  5:54     ` Lukasz Majewski
  0 siblings, 1 reply; 111+ messages in thread
From: Joseph Myers @ 2019-04-17 22:11 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: libc-alpha, Paul Eggert

On Mon, 15 Apr 2019, Lukasz Majewski wrote:

> +  if (! INTERNAL_SYSCALL_ERROR_P (r, err))
> +      valid_timespec_to_timespec64(&rem32, rem);

Missing space before '('.  Indentation in GNU style is two columns, so two 
levels of indentation should be four columns (you have two columns 
followed by six columns here).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH 6/6] y2038: linux: Provide __clock_nanosleep64 implementation
  2019-04-17 22:11   ` Joseph Myers
@ 2019-04-18  5:54     ` Lukasz Majewski
  0 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-18  5:54 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 668 bytes --]

Hi Joseph,

> On Mon, 15 Apr 2019, Lukasz Majewski wrote:
> 
> > +  if (! INTERNAL_SYSCALL_ERROR_P (r, err))
> > +      valid_timespec_to_timespec64(&rem32, rem);  
> 
> Missing space before '('.  Indentation in GNU style is two columns,
> so two levels of indentation should be four columns (you have two
> columns followed by six columns here).
> 

Thanks for spotting. I will fix it in v2.


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH 3/6] y2038: linux: Provide __clock_settime64 implementation
  2019-04-17 22:08   ` Joseph Myers
@ 2019-04-18  6:46     ` Lukasz Majewski
  0 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-18  6:46 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 4194 bytes --]

Hi Joseph,

> On Mon, 15 Apr 2019, Lukasz Majewski wrote:
> 
> > The new 64 bit syscall (clock_settime64) available from Linux
> > 5.1+ has been used when applicable on 32 bit systems.
> > The execution path on 64 bit systems has not been changed or
> > affected in any way.  
> 
> Is this unchanged specifically because of __TIMESIZE conditionals in
> the code (so that it doesn't matter whether the 64-bit systems define
> any new syscall names)?

I think yes.

When __TIMESIZE == 64 the clock_settime syscall is supporting 64 bit
time. The goal is to not change execution path for e.g. x86_64.
IMHO this shall be kept separate from Y2038 and 32 bit execution path.


This patch tries to follow 64 bit conversion for __clock_* functions as
presented in:
https://sourceware.org/glibc/wiki/Y2038ProofnessDesign#clock_gettime.28.29

__TIMESIZE is necessary to distinct the 32/64 bit case as
__clock_settime64 is used for both cases.

In this function I also need to check if __TIMESIZE is defined
https://github.com/lmajewski/y2038_glibc/commit/80f3b6220d80a8579e88b63fb90ba8ea7b771c5c#diff-725737619c471831ff796099fbab5c0aR33

as __clock_settime64 is aliased to clock_settime on 64 bit systems and
then aliased/linked to librt (for backward compatibility).

> 
> Also, I don't see any __ASSUME_* / ENOSYS handling in this patch.  As 
> usual, for any new syscall that might be used in code that could also
> use an older syscall:

I've followed some code pattern from glibc sources; for example:
sysdeps/unix/sysv/linux/lseek.c
Here the new syscall is only guarded by: # ifdef __NR__llseek
There was no __ASSUME_* for it.


However, the statx for example uses __ASSUME_STATX, which is defined
when kernel is newer than specified version. I will rewrite the code to
be similar to statx.

> 
> * If the appropriate __ASSUME_* is defined, the new syscall can
> simply be used unconditionally.
> 
> * If the appropriate __ASSUME_* is not defined, there needs to be
> runtime fallback to the old syscall if the new one returns an ENOSYS
> error (of course, that runtime fallback needs to check for the time
> overflowing the 32-bit range and give an appropriate error in that
> case, before calling the 32-bit syscall - and it's necessary to
> figure out what the priority should be of errors for invalid
> nanoseconds values versus overflowing seconds).  It is normal and
> expected for the kernel headers used to build glibc to be (much)
> newer than the oldest kernel version supported by the resulting glibc
> binaries at runtime.

Ach... I see your point. The __ASSUME_ prevents from nonfunctional glibc
when one uses new headers to compile glibc (which have
__NR__clock_settime64 defined) afterwards installed in a system with
old kernel (so __clock_settime64 returns -ENOSYS). I do agree that with
current patch there is no fallback to old syscall in that case.

I will fix it in v2.

> 
> This __ASSUME_* macro definition in kernel-features.h would need a 
> multi-paragraph comment discussing exactly what the semantics of such 
> __ASSUME_* macros are in the context of the sets of syscall names and 
> numbers present on different kinds of Linux kernel architectures.

Ok. I will add it to v2.

> 
> > +#if __TIMESIZE != 64
> > +int
> > +__clock_settime (clockid_t clock_id, const struct timespec *tp)
> > +{
> > +  struct __timespec64 ts64;
> > +
> > +  if (! in_time_t_range (tp->tv_sec))
> > +    {
> > +      __set_errno (EOVERFLOW);
> > +      return -1;
> > +    }  
> 
> I don't see how an overflow check makes sense in this context
> (converting a 32-bit timespec to a 64-bit one).

The above code is for the case when _TIME_BITS is not set (on 32
bit system) and we are after Y2038. The data provided by *tp has wrong
value and shall not be passed to the kernel (no matter if it supports
Y2038 time or not).

> 




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH 3/6] y2038: linux: Provide __clock_settime64 implementation
  2019-04-14 22:08 ` [PATCH 3/6] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
  2019-04-17 22:08   ` Joseph Myers
@ 2019-04-20  0:20   ` Stepan Golosunov
  2019-04-20 11:21     ` Lukasz Majewski
  1 sibling, 1 reply; 111+ messages in thread
From: Stepan Golosunov @ 2019-04-20  0:20 UTC (permalink / raw)
  To: Lukasz Majewski, Arnd Bergmann, Deepa Dinamani
  Cc: libc-alpha, Paul Eggert, Joseph Myers, John Stultz,
	Thomas Gleixner, linux-kernel

15.04.2019 в 00:08:38 +0200 Lukasz Majewski написал:
> +# if defined __NR_clock_settime64
> +  /* Make sure that passed __timespec64 struct pad is 0.  */
> +  struct __timespec64 ts = *tp;
> +  ts.tv_pad = 0;
> +  return INLINE_SYSCALL_CALL (clock_settime64, clock_id, &ts);

Isn't kernel supposed to zero out padding on its own?
At least comment in kernel's get_timespec64 says so:

	/* Zero out the padding for 32 bit systems or in compat mode */
	if (IS_ENABLED(CONFIG_64BIT_TIME) && in_compat_syscall())
		kts.tv_nsec &= 0xFFFFFFFFUL;

The code looks buggy though. It fails to zero out the padding in
32-bit kernels. That part is probably broken since
98f76206b3350 ("compat: Cleanup in_compat_syscall() callers").

And, hmm, is CONFIG_64BIT_TIME enabled anywhere?

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH 3/6] y2038: linux: Provide __clock_settime64 implementation
  2019-04-20  0:20   ` Stepan Golosunov
@ 2019-04-20 11:21     ` Lukasz Majewski
  2019-04-22  9:07       ` Stepan Golosunov
  0 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-20 11:21 UTC (permalink / raw)
  To: Stepan Golosunov
  Cc: Arnd Bergmann, Deepa Dinamani, libc-alpha, Paul Eggert,
	Joseph Myers, John Stultz, Thomas Gleixner, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2312 bytes --]

Hi Stepan,

> 15.04.2019 в 00:08:38 +0200 Lukasz Majewski написал:
> > +# if defined __NR_clock_settime64
> > +  /* Make sure that passed __timespec64 struct pad is 0.  */
> > +  struct __timespec64 ts = *tp;
> > +  ts.tv_pad = 0;
> > +  return INLINE_SYSCALL_CALL (clock_settime64, clock_id, &ts);  
> 
> Isn't kernel supposed to zero out padding on its own?
> At least comment in kernel's get_timespec64 says so:
> 
> 	/* Zero out the padding for 32 bit systems or in compat mode
> */ if (IS_ENABLED(CONFIG_64BIT_TIME) && in_compat_syscall())
> 		kts.tv_nsec &= 0xFFFFFFFFUL;
> 

For ARM (and x86) 32 bit machines I do use following syscalls (like
clock_settime64):
https://elixir.bootlin.com/linux/v5.1-rc4/source/arch/arm/tools/syscall.tbl#L420

which are providing 64 bit time support on 32 bit systems.

Yes. In those systems the upper part (32 bits) of tv_nsec is cleared up
with mask in the kernel. However, I would prefer not to pass random data
to the kernel, and hence I do clear it up explicitly in glibc.

> The code looks buggy though. It fails to zero out the padding in
> 32-bit kernels.

For the 32 bit systems without Y2038 support enabled in glibc - the
clock_settime would be used, which corresponds to sys_clock_settime32()
in the kernel.

> That part is probably broken since
> 98f76206b3350 ("compat: Cleanup in_compat_syscall() callers").
> 
> And, hmm, is CONFIG_64BIT_TIME enabled anywhere?

When I do use clock_settime64 on the glibc side (with _TIME_BITS=64), I
do not need to enable such config in the kernel. 

If the kernel supports this call (5.1+), then use it, otherwise
fallback to clock_settime().

For 64 bit systems, I do not change the execution path.

If you are interested, please look on the following repo (which has
some more commits than those posted to the mailing list):
https://github.com/lmajewski/y2038_glibc/commits/Y2038-2.29-glibc-__clock-internal-struct-timespec-v1

And meta layer for testing.

https://github.com/lmajewski/meta-y2038

Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH 3/6] y2038: linux: Provide __clock_settime64 implementation
  2019-04-20 11:21     ` Lukasz Majewski
@ 2019-04-22  9:07       ` Stepan Golosunov
  2019-04-22 21:45         ` Arnd Bergmann
  0 siblings, 1 reply; 111+ messages in thread
From: Stepan Golosunov @ 2019-04-22  9:07 UTC (permalink / raw)
  To: Lukasz Majewski, Arnd Bergmann
  Cc: Deepa Dinamani, libc-alpha, Paul Eggert, Joseph Myers,
	John Stultz, Thomas Gleixner, linux-kernel

20.04.2019 в 13:21:12 +0200 Lukasz Majewski написал:
> Hi Stepan,
> 
> > 15.04.2019 в 00:08:38 +0200 Lukasz Majewski написал:
> > > +# if defined __NR_clock_settime64
> > > +  /* Make sure that passed __timespec64 struct pad is 0.  */
> > > +  struct __timespec64 ts = *tp;
> > > +  ts.tv_pad = 0;
> > > +  return INLINE_SYSCALL_CALL (clock_settime64, clock_id, &ts);  
> > 
> > Isn't kernel supposed to zero out padding on its own?
> > At least comment in kernel's get_timespec64 says so:
> > 
> > 	/* Zero out the padding for 32 bit systems or in compat mode
> > */ if (IS_ENABLED(CONFIG_64BIT_TIME) && in_compat_syscall())
> > 		kts.tv_nsec &= 0xFFFFFFFFUL;
> > 
> 
> For ARM (and x86) 32 bit machines I do use following syscalls (like
> clock_settime64):
> https://elixir.bootlin.com/linux/v5.1-rc4/source/arch/arm/tools/syscall.tbl#L420
> 
> which are providing 64 bit time support on 32 bit systems.
> 
> Yes. In those systems the upper part (32 bits) of tv_nsec is cleared up
> with mask in the kernel.

Is it? The kernel (5.1-rc6) code looks to me like

	/* Zero out the padding for 32 bit systems or in compat mode */
	if (false && false)
		kts.tv_nsec &= 0xFFFFFFFFUL;

in 32-bit kernels. And like

	if (false && true)
		kts.tv_nsec &= 0xFFFFFFFFUL;

for COMPAT syscalls in 64-bit kernels.

It should probably be changed into

	if (!IS_ENABLED(CONFIG_64BIT) || in_compat_syscall())
		kts.tv_nsec &= 0xFFFFFFFFUL;

(Or into something like

	if (!IS_ENABLED(CONFIG_64BIT) || in_compat_syscall() && !COMPAT_USE_64BIT_TIME)
		kts.tv_nsec &= 0xFFFFFFFFUL;

if x32 should retain 64-bit tv_nsec.)

> However, I would prefer not to pass random data
> to the kernel, and hence I do clear it up explicitly in glibc.

If the kernel does not ignore padding on its own, then zeroing it out
is required everywhere timespec is passed to kernel, including via
code not known to glibc. (Does anyone promise that there won't be any
ioctls that accept timespec, for example?) That seems to be
error-prone (and might requre copying larger structes).

On the other hand, if kernel 5.1+ ignores padding as intended there is
no need to create additional copy of structs in glibc code that calls
into clock_settime64 (or into timer_settime64 that accepts larger
struct, for example).

> > The code looks buggy though. It fails to zero out the padding in
> > 32-bit kernels.
> 
> For the 32 bit systems without Y2038 support enabled in glibc - the
> clock_settime would be used, which corresponds to sys_clock_settime32()
> in the kernel.

I am talking about kernels with Y2038 support.

> > That part is probably broken since
> > 98f76206b3350 ("compat: Cleanup in_compat_syscall() callers").
> > 
> > And, hmm, is CONFIG_64BIT_TIME enabled anywhere?

I guess that the remaining CONFIG_64BIT_TIME in kernel should be
replaced with CONFIG_COMPAT_32BIT_TIME or removed.

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH 3/6] y2038: linux: Provide __clock_settime64 implementation
  2019-04-22  9:07       ` Stepan Golosunov
@ 2019-04-22 21:45         ` Arnd Bergmann
  2019-04-23 15:45           ` Lukasz Majewski
  0 siblings, 1 reply; 111+ messages in thread
From: Arnd Bergmann @ 2019-04-22 21:45 UTC (permalink / raw)
  To: Stepan Golosunov
  Cc: Lukasz Majewski, Deepa Dinamani, GNU C Library, Paul Eggert,
	Joseph Myers, John Stultz, Thomas Gleixner,
	Linux Kernel Mailing List

On Mon, Apr 22, 2019 at 11:07 AM Stepan Golosunov
<stepan@golosunov.pp.ru> wrote:
> 20.04.2019 в 13:21:12 +0200 Lukasz Majewski написал:
> Is it? The kernel (5.1-rc6) code looks to me like
>
>         /* Zero out the padding for 32 bit systems or in compat mode */
>         if (false && false)
>                 kts.tv_nsec &= 0xFFFFFFFFUL;
>
> in 32-bit kernels. And like
>
>         if (false && true)
>                 kts.tv_nsec &= 0xFFFFFFFFUL;
>
> for COMPAT syscalls in 64-bit kernels.
>
> It should probably be changed into
>
>         if (!IS_ENABLED(CONFIG_64BIT) || in_compat_syscall())
>                 kts.tv_nsec &= 0xFFFFFFFFUL;
>
> (Or into something like
>
>         if (!IS_ENABLED(CONFIG_64BIT) || in_compat_syscall() && !COMPAT_USE_64BIT_TIME)
>                 kts.tv_nsec &= 0xFFFFFFFFUL;
>
> if x32 should retain 64-bit tv_nsec.)

I think the problem is that at some point CONFIG_64BIT_TIME was
meant to be enabled on both 32-bit and 64-bit kernels, but the
definition got changed along  the way.

We probably just want

        if (in_compat_syscall() )
               kts.tv_nsec &= 0xFFFFFFFFUL;

here, which would then truncate the nanoseconds for all compat
mode including x32. For native mode, we don't need to truncate
it, since timespec64 has a 32-bit 'tv_nsec' field in the kernel.

> > However, I would prefer not to pass random data
> > to the kernel, and hence I do clear it up explicitly in glibc.
>
> If the kernel does not ignore padding on its own, then zeroing it out
> is required everywhere timespec is passed to kernel, including via
> code not known to glibc. (Does anyone promise that there won't be any
> ioctls that accept timespec, for example?) That seems to be
> error-prone (and might requre copying larger structes).
>
> On the other hand, if kernel 5.1+ ignores padding as intended there is
> no need to create additional copy of structs in glibc code that calls
> into clock_settime64 (or into timer_settime64 that accepts larger
> struct, for example).

The intention is that the kernel ignores the padding. If you find
another place in the kernel that forget that, we should fix it.

> > > And, hmm, is CONFIG_64BIT_TIME enabled anywhere?
>
> I guess that the remaining CONFIG_64BIT_TIME in kernel should be
> replaced with CONFIG_COMPAT_32BIT_TIME or removed.

We should remove CONFIG_64BIT_TIME. CONFIG_COMPAT_32BIT_TIME
is still needed to identify architectures that don't have it, in
particular riscv32.

       Arnd

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH 3/6] y2038: linux: Provide __clock_settime64 implementation
  2019-04-22 21:45         ` Arnd Bergmann
@ 2019-04-23 15:45           ` Lukasz Majewski
  0 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-23 15:45 UTC (permalink / raw)
  To: Arnd Bergmann, Stepan Golosunov, Joseph Myers
  Cc: Deepa Dinamani, GNU C Library, Paul Eggert, John Stultz,
	Thomas Gleixner, Linux Kernel Mailing List

[-- Attachment #1: Type: text/plain, Size: 3764 bytes --]

Hi Arnd and Stepan,

> On Mon, Apr 22, 2019 at 11:07 AM Stepan Golosunov
> <stepan@golosunov.pp.ru> wrote:
> > 20.04.2019 в 13:21:12 +0200 Lukasz Majewski написал:
> > Is it? The kernel (5.1-rc6) code looks to me like
> >
> >         /* Zero out the padding for 32 bit systems or in compat
> > mode */ if (false && false)
> >                 kts.tv_nsec &= 0xFFFFFFFFUL;
> >
> > in 32-bit kernels. And like
> >
> >         if (false && true)
> >                 kts.tv_nsec &= 0xFFFFFFFFUL;
> >
> > for COMPAT syscalls in 64-bit kernels.
> >
> > It should probably be changed into
> >
> >         if (!IS_ENABLED(CONFIG_64BIT) || in_compat_syscall())
> >                 kts.tv_nsec &= 0xFFFFFFFFUL;
> >
> > (Or into something like
> >
> >         if (!IS_ENABLED(CONFIG_64BIT) || in_compat_syscall()
> > && !COMPAT_USE_64BIT_TIME) kts.tv_nsec &= 0xFFFFFFFFUL;
> >
> > if x32 should retain 64-bit tv_nsec.)  
> 
> I think the problem is that at some point CONFIG_64BIT_TIME was
> meant to be enabled on both 32-bit and 64-bit kernels, but the
> definition got changed along  the way.
> 
> We probably just want
> 
>         if (in_compat_syscall() )
>                kts.tv_nsec &= 0xFFFFFFFFUL;
> 
> here, which would then truncate the nanoseconds for all compat
> mode including x32. For native mode, we don't need to truncate
> it, since timespec64 has a 32-bit 'tv_nsec' field in the kernel.
> 
> > > However, I would prefer not to pass random data
> > > to the kernel, and hence I do clear it up explicitly in glibc.  
> >
> > If the kernel does not ignore padding on its own, then zeroing it
> > out is required everywhere timespec is passed to kernel, including
> > via code not known to glibc. (Does anyone promise that there won't
> > be any ioctls that accept timespec, for example?) That seems to be
> > error-prone (and might requre copying larger structes).
> >
> > On the other hand, if kernel 5.1+ ignores padding as intended there
> > is no need to create additional copy of structs in glibc code that
> > calls into clock_settime64 (or into timer_settime64 that accepts
> > larger struct, for example).  

Ok, I think I see your point:

- As kernel is ignoring padding, there is no need to copy the structure
  and set the padding to 0.

However, in patch:
[PATCH 1/6] y2038: Introduce internal for glibc struct __timespec64

The internal (for glibc) structure has been introduced - it has 32 bit
tv_nsec and 32 bit padding. As it is passed to the kernel - the padding
can have random values and hence shall be zeroed before passing to the
kernel.

The rationale for 32 bit tv_nsec is to be as close as possible to what
is exported by glibc (64 bit tv_sec and 32 bit tv_nsec) for Y2038.

I'm now wondering if it would be better to have glibc internal struct
__timespec64 having both fields 64 bit (as it would be easier to pass
it to Linux).


> 
> The intention is that the kernel ignores the padding. If you find
> another place in the kernel that forget that, we should fix it.
> 

Thanks Arnd for clarification.

> > > > And, hmm, is CONFIG_64BIT_TIME enabled anywhere?  
> >
> > I guess that the remaining CONFIG_64BIT_TIME in kernel should be
> > replaced with CONFIG_COMPAT_32BIT_TIME or removed.  
> 
> We should remove CONFIG_64BIT_TIME. CONFIG_COMPAT_32BIT_TIME
> is still needed to identify architectures that don't have it, in
> particular riscv32.
> 
>        Arnd




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* [PATCH v2 0/7] y2038: Linux: Provide __clock_* functions supporting 64 bit time
  2019-04-14 22:08 [PATCH 0/6] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
                   ` (5 preceding siblings ...)
  2019-04-14 22:08 ` [PATCH 6/6] y2038: linux: Provide __clock_nanosleep64 implementation Lukasz Majewski
@ 2019-04-29 10:46 ` Lukasz Majewski
  2019-04-29 10:46   ` [PATCH v2 1/7] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
                     ` (6 more replies)
  2019-05-07 13:18 ` [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time Lukasz Majewski
                   ` (3 subsequent siblings)
  10 siblings, 7 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-29 10:46 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This patch set introduces the conversion of __clock_{settime|
gettime|getres|nanosleep} to explicit 64 bit struct __timespec64
arguments. As a result those functions are now Y2038 safe

To achieve the above goal - new, internal to glibc,
struct __timespec64 has been also introduced as well as
helper functions to handle time conversions on 32 bit systems.

The code from this patch set uses new clock_* syscalls (explicit
64 bits) from Linux kernel (5.1+) as well.

In glibc new __ASSUME_64BIT_TIME define has been introduced to
indicate if above syscalls are provided by the kernel.

This work is (loosely) based on a previous development/patches:
https://libc-alpha.sourceware.narkive.com/zniMOWui/rfc-patch-00-52-make-glibc-y2038-proof#post68

Github branch (including the y2038 conversion example):
https://github.com/lmajewski/y2038_glibc/commits/Y2038-2.29-glibc-__clock-internal-struct-timespec-v2

Those patches have been applied on top of master branch:
SHA1: c57afec0a9b318bb691e0f5fa4e9681cf30df7a4

Shall be used with provided meta-y2038 for development and testing:
https://github.com/lmajewski/meta-y2038

I've used guidelines from:
https://www.gnu.org/software/libc/manual/html_mono/libc.html
"D.2.1 64-bit time symbol handling in the GNU C Library"
to convert *clock_settime*.

and most notably from:
https://sourceware.org/glibc/wiki/Y2038ProofnessDesign#clock_gettime.28.29

Feedback and comments are more than welcome.


Lukasz Majewski (7):
  y2038: Introduce internal for glibc struct __timespec64
  y2038: Introduce __ASSUME_64BIT_TIME define
  y2038: Provide conversion helpers for struct __timespec64
  y2038: linux: Provide __clock_settime64 implementation
  y2038: linux: Provide __clock_getres64 implementation
  y2038: linux: Provide __clock_gettime64 implementation
  y2038: linux: Provide __clock_nanosleep64 implementation

 include/time.h                            | 157 ++++++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/clock_getres.c    |  39 +++++++-
 sysdeps/unix/sysv/linux/clock_gettime.c   |  39 +++++++-
 sysdeps/unix/sysv/linux/clock_nanosleep.c |  71 +++++++++++++-
 sysdeps/unix/sysv/linux/clock_settime.c   |  50 +++++++++-
 sysdeps/unix/sysv/linux/kernel-features.h |  14 +++
 6 files changed, 361 insertions(+), 9 deletions(-)

-- 
2.11.0


^ permalink raw reply	[flat|nested] 111+ messages in thread

* [PATCH v2 1/7] y2038: Introduce internal for glibc struct __timespec64
  2019-04-29 10:46 ` [PATCH v2 0/7] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
@ 2019-04-29 10:46   ` Lukasz Majewski
  2019-04-29 10:46   ` [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define Lukasz Majewski
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-29 10:46 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This type is a glibc's type similar to struct timespec
but whose tv_sec field is a __time64_t rather than a time_t,
which makes it Y2038-proof and usable to pass between user
code and Y2038-proof kernel syscalls (e.g. clock_gettime()).

To support passing this structure to the kernel - the tv_pad,
32 bit padding field has been introduced. The placement of it
depends on endiannes of the SoC.

Tested on x86_64 and ARM.

* include/time.h: Add struct __timespec64 definition

---
Changes for v2:
- None
---
 include/time.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/include/time.h b/include/time.h
index 61dd9e180b..7540ac0f8b 100644
--- a/include/time.h
+++ b/include/time.h
@@ -3,6 +3,7 @@
 
 #ifndef _ISOMAC
 # include <bits/types/locale_t.h>
+# include <endian.h>
 
 extern __typeof (strftime_l) __strftime_l;
 libc_hidden_proto (__strftime_l)
@@ -58,6 +59,27 @@ extern time_t __mktime_internal (struct tm *__tp,
 				 long int *__offset) attribute_hidden;
 
 #if __TIMESIZE == 64
+# define __timespec64 timespec
+#else
+/* The glibc Y2038-proof struct __timespec64 structure for a time value.
+   To keep things Posix-ish, we keep the nanoseconds field a 32-bit
+   signed long, but since the Linux field is a 64-bit signed int, we
+   pad our tv_nsec with a 32-bit bitfield, which should always be 0. */
+
+struct __timespec64
+{
+  __time64_t tv_sec;         /* Seconds */
+# if BYTE_ORDER == BIG_ENDIAN
+  int tv_pad: 32;            /* Padding named for checking/setting */
+  __int32_t tv_nsec;         /* Nanoseconds */
+# else
+  __int32_t tv_nsec;         /* Nanoseconds */
+  int tv_pad: 32;            /* Padding named for checking/setting */
+# endif
+};
+#endif
+
+#if __TIMESIZE == 64
 # define __ctime64 ctime
 #else
 extern char *__ctime64 (const __time64_t *__timer) __THROW;
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-04-29 10:46 ` [PATCH v2 0/7] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
  2019-04-29 10:46   ` [PATCH v2 1/7] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
@ 2019-04-29 10:46   ` Lukasz Majewski
  2019-04-29 21:50     ` Joseph Myers
  2019-04-29 10:46   ` [PATCH v2 3/7] y2038: Provide conversion helpers for struct __timespec64 Lukasz Majewski
                     ` (4 subsequent siblings)
  6 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-29 10:46 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This define indicates if the Linux kernel (5.1+) provides 64 bit versions
of time related syscalls (e.g. clock_settime64, clock_nanosleep_time64).

Those syscalls are now available on actively supported Linux architectures
and most of all are providing Y2038 correct time on 32 bit systems.

* sysdeps/unix/sysv/linux/kernel-features.h: (__ASSUME_64BIT_TIME):
[__LINUX_KERNEL_VERSION >= 0x050100]: Define.

---
Changes for v2:
- New patch
---
 sysdeps/unix/sysv/linux/kernel-features.h | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
index bc5c959f58..2dbe5ada4c 100644
--- a/sysdeps/unix/sysv/linux/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/kernel-features.h
@@ -143,3 +143,17 @@
    */
 
 #define __ASSUME_CLONE_DEFAULT 1
+
+/* Support for 64 bit version of clock_* Linux syscalls.
+
+   Support for following time related (and Y2038 safe) syscalls has been added
+   in the 5.1 Linux kernel:
+
+   clock_gettime64 (nr. 403)
+   clock_settime64 (nr. 404)
+   clock_getres_time64 (nr. 406)
+   clock_nanosleep_time64 (nr. 407)
+  */
+#if __LINUX_KERNEL_VERSION >= 0x050100
+# define __ASSUME_64BIT_TIME 1
+#endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH v2 3/7] y2038: Provide conversion helpers for struct __timespec64
  2019-04-29 10:46 ` [PATCH v2 0/7] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
  2019-04-29 10:46   ` [PATCH v2 1/7] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
  2019-04-29 10:46   ` [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define Lukasz Majewski
@ 2019-04-29 10:46   ` Lukasz Majewski
  2019-05-02 11:56     ` Stepan Golosunov
  2019-04-29 10:46   ` [PATCH v2 4/7] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
                     ` (3 subsequent siblings)
  6 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-29 10:46 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

Those functions allow easy conversion between Y2038 safe struct
 __timespec64 and other time related data structures.

An inline function has been added to clear padding of struct
__timespec64. This function shall be used when Y2038 safe system
passes the data to Linux kernel (as it expects upper 32 bits of
tv_nsec being zeroed).

Moreover, those functions are NOT compiled when one runs 64 bit
system (the __TIMESIZE == 64) and are used only for 32 bit
wrappers (like __clock_gettime).

* include/time.h (valid_timeval_to_timespec64): Add.
* include/time.h (valid_timespec_to_timespec64): Likewise.
* include/time.h (valid_timespec64_to_timespec): Likewise.
* include/time.h (valid_timespec64_to_timeval): Likewise.
* include/time.h (IS_VALID_NANOSECONDS): Likewise.
* include/time.h (timespec_to_timespec64): Likewise.
* include/time.h (timespec64_to_timespec): Likewise.
* include/time.h (timespec64_to_timeval): Likewise.
* include/time.h (timespec64_clear_padding): Likewise.

---
Changes for v2:
- Add timespec64_clear_padding function
---
 include/time.h | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 102 insertions(+)

diff --git a/include/time.h b/include/time.h
index 7540ac0f8b..9827d2f045 100644
--- a/include/time.h
+++ b/include/time.h
@@ -3,6 +3,7 @@
 
 #ifndef _ISOMAC
 # include <bits/types/locale_t.h>
+# include <stdbool.h>
 # include <endian.h>
 
 extern __typeof (strftime_l) __strftime_l;
@@ -177,5 +178,106 @@ extern double __difftime (time_t time1, time_t time0);
    actual clock ID.  */
 #define CLOCK_IDFIELD_SIZE	3
 
+/* Check whether T fits in time_t.  */
+static inline bool
+in_time_t_range (__time64_t t)
+{
+  time_t s = t;
+  return s == t;
+}
+
+# if __TIMESIZE != 64
+/* Set to zero the struct __timespec64's tv_pad.  */
+static inline void
+timespec64_clear_padding (const struct __timespec64 *tp)
+{
+  ((struct __timespec64*)tp)->tv_pad = 0;
+}
+/* Convert a known valid struct timeval into a struct __timespec64.  */
+static inline void
+valid_timeval_to_timespec64 (const struct timeval *tv32,
+			     struct __timespec64 *ts64)
+{
+  ts64->tv_sec = tv32->tv_sec;
+  ts64->tv_nsec = tv32->tv_usec * 1000;
+}
+
+/* Convert a known valid struct timespec into a struct __timespec64.  */
+static inline void
+valid_timespec_to_timespec64 (const struct timespec *ts32,
+			      struct __timespec64 *ts64)
+{
+  ts64->tv_sec = ts32->tv_sec;
+  ts64->tv_nsec = ts32->tv_nsec;
+  /* We only need to zero ts64->tv_pad if we pass it to the kernel.  */
+}
+
+/* Convert a known valid struct __timespec64 into a struct timespec.  */
+static inline void
+valid_timespec64_to_timespec (const struct __timespec64 *ts64,
+			      struct timespec *ts32)
+{
+  ts32->tv_sec = (time_t) ts64->tv_sec;
+  ts32->tv_nsec = ts64->tv_nsec;
+}
+
+/* Convert a known valid struct __timespec64 into a struct timeval.  */
+static inline void
+valid_timespec64_to_timeval (const struct __timespec64 *ts64,
+			     struct timeval *tv32)
+{
+  tv32->tv_sec = (time_t) ts64->tv_sec;
+  tv32->tv_usec = ts64->tv_nsec / 1000;
+}
+
+/* Check if a value lies with the valid nanoseconds range.  */
+#define IS_VALID_NANOSECONDS(ns) ((ns) >= 0 && (ns) <= 999999999)
+
+/* Check and convert a struct timespec into a struct __timespec64.  */
+static inline bool
+timespec_to_timespec64 (const struct timespec *ts32,
+                        struct __timespec64 *ts64)
+{
+  /* Check that ts32 holds a valid count of nanoseconds.  */
+  if (! IS_VALID_NANOSECONDS (ts32->tv_nsec))
+    return false;
+  /* All ts32 fields can fit in ts64, so copy them.  */
+  valid_timespec_to_timespec64 (ts32, ts64);
+  /* We only need to zero ts64->tv_pad if we pass it to the kernel.  */
+  return true;
+}
+
+/* Check and convert a struct __timespec64 into a struct timespec.  */
+static inline bool
+timespec64_to_timespec (const struct __timespec64 *ts64,
+                        struct timespec *ts32)
+{
+  /* Check that tv_nsec holds a valid count of nanoseconds.  */
+  if (! IS_VALID_NANOSECONDS (ts64->tv_nsec))
+    return false;
+  /* Check that tv_sec can fit in a __time_t.  */
+  if (! in_time_t_range (ts64->tv_sec))
+    return false;
+  /* All ts64 fields can fit in ts32, so copy them.  */
+  valid_timespec64_to_timespec (ts64, ts32);
+  return true;
+}
+
+/* Check and convert a struct __timespec64 into a struct timeval.  */
+static inline bool
+timespec64_to_timeval (const struct __timespec64 *ts64,
+                       struct timeval *tv32)
+{
+  /* Check that tv_nsec holds a valid count of nanoseconds.  */
+  if (! IS_VALID_NANOSECONDS (ts64->tv_nsec))
+    return false;
+  /* Check that tv_sec can fit in a __time_t.  */
+  if (! in_time_t_range (ts64->tv_sec))
+    return false;
+  /* All ts64 fields can fit in tv32, so copy them.  */
+  valid_timespec64_to_timeval (ts64, tv32);
+  return true;
+}
+# endif
 #endif
 #endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH v2 4/7] y2038: linux: Provide __clock_settime64 implementation
  2019-04-29 10:46 ` [PATCH v2 0/7] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
                     ` (2 preceding siblings ...)
  2019-04-29 10:46   ` [PATCH v2 3/7] y2038: Provide conversion helpers for struct __timespec64 Lukasz Majewski
@ 2019-04-29 10:46   ` Lukasz Majewski
  2019-04-29 10:46   ` [PATCH v2 5/7] y2038: linux: Provide __clock_getres64 implementation Lukasz Majewski
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-29 10:46 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This patch provides new __clock_settime64 explicit 64 bit function for
setting the time. Moreover, a 32 bit version - __clock_settime has been
refactored to internally use __clock_settime64.

The __clock_settime is now supposed to be used on 32 bit systems -
hence the necessary checks and conversion to 64 bit type. After this
change it is intrinsically Y2038 safe.

The new 64 bit syscall (clock_settime64) available from Linux
5.1+ has been used when applicable on 32 bit systems.

The __ASSUME_64BIT_TIME flag indicates if the Linux kernel provides 64 bit
version of clock_settime (i.e. clock_settime64). If defined - return value
is returned unconditionally. If not - the 32 bit version of this syscall
is executed instead.

When working on 32 bit systems without Y2038 time support the clock_settime
returns error when one wants to set time with wrong (overflowed) tv_sec
value. Moreover, the correctness of tv_nsec is checked.

In this patch the internal padding (tv_pad) of struct __timespec64 is set to
zero (on 32 bit systems) to avoid passing random data to Linux kernel.

The execution path on 64 bit systems has not been changed or affected in
any way.

Tests:
- The code has been tested with x86_64/x86 (native compilation):
make PARALLELMFLAGS="-j8" && make xcheck PARALLELMFLAGS="-j8"

- Run specific tests on ARM/x86 32bit systems (qemu):
https://github.com/lmajewski/meta-y2038
and run tests:
https://github.com/lmajewski/y2038-tests/commits/master
on kernels with and without 64 bit time support.

No regressions were observed.

* include/time.h (__clock_settime64):
  Add __clock_settime alias according to __TIMESIZE define
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime):
  Refactor this function to be used only on 32 bit machines as a wrapper
  on __clock_settime64.
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime64): Add
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime64):
  Use clock_settime64 kernel syscall (available from 5.1-rc1+ Linux) by
  32 bit Y2038 safe systems

---
Changes for v2:
- Add support for __ASSUME_64BIT_TIME flag when Linux kernel provides syscalls
  supporting 64 bit time on 32 bit systems
- Provide fallback to 32 bit version of clock_settime when clock_settime64
  is not available
- Do not copy *tp to timespec - this seems like an overkill as in clock_settime()
  the 32 bit struct timespec is copied to internal 64 bit struct __timespec64
---
 include/time.h                          |  8 ++++++
 sysdeps/unix/sysv/linux/clock_settime.c | 50 +++++++++++++++++++++++++++++++--
 2 files changed, 55 insertions(+), 3 deletions(-)

diff --git a/include/time.h b/include/time.h
index 9827d2f045..7f08559072 100644
--- a/include/time.h
+++ b/include/time.h
@@ -132,6 +132,14 @@ extern struct tm *__gmtime64_r (const __time64_t *__restrict __timer,
 libc_hidden_proto (__gmtime64_r);
 #endif
 
+#if __TIMESIZE == 64
+# define __clock_settime64 __clock_settime
+#else
+extern int __clock_settime64 (clockid_t clock_id,
+                              const struct __timespec64 *tp);
+libc_hidden_proto (__clock_settime64)
+#endif
+
 /* Compute the `struct tm' representation of T,
    offset OFFSET seconds east of UTC,
    and store year, yday, mon, mday, wday, hour, min, sec into *TP.
diff --git a/sysdeps/unix/sysv/linux/clock_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c
index d837e3019c..8037ab0eb1 100644
--- a/sysdeps/unix/sysv/linux/clock_settime.c
+++ b/sysdeps/unix/sysv/linux/clock_settime.c
@@ -19,11 +19,9 @@
 #include <sysdep.h>
 #include <time.h>
 
-#include "kernel-posix-cpu-timers.h"
-
 /* Set CLOCK to value TP.  */
 int
-__clock_settime (clockid_t clock_id, const struct timespec *tp)
+__clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
 {
   /* Make sure the time cvalue is OK.  */
   if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
@@ -32,6 +30,52 @@ __clock_settime (clockid_t clock_id, const struct timespec *tp)
       return -1;
     }
 
+#if defined (__TIMESIZE) && __TIMESIZE != 64
+# ifdef __NR_clock_settime64
+  /* For 32 bit systems with no Y2038 support the *tp may have tv_pad
+     with some random values as *tp from __clock_settime is converted
+     to automatically allocated struct __timespec64 (ts64).
+
+     For 32 bit systems being Y2038 safe the tv_pad may be not zero,
+     as glibc exported struct timespec has 64 bit tv_sec, 32 bit
+     tv_nsec (to be still POSIX compliant -> long tv_nsec ) and 32
+     bits of unnamed padding.
+     If user program allocates the struct timespec automatically, the
+     padding may have random value and as being directly passed to
+     *tp needs to be cleared.  */
+  timespec64_clear_padding (tp);
+  int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
+#  ifdef __ASSUME_64BIT_TIME
+  return ret;
+#  else
+  if (ret == 0 || errno != ENOSYS)
+    /* Preserve non-error/non-ENOSYS return values.  */
+    return ret;
+#  endif
+# endif
+  /* Fall back to syscall supporting 32bit struct timespec.  */
+  struct timespec ts32;
+  valid_timespec64_to_timespec (tp, &ts32);
+  return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);
+#else
   return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp);
+#endif
 }
 weak_alias (__clock_settime, clock_settime)
+
+#if __TIMESIZE != 64
+int
+__clock_settime (clockid_t clock_id, const struct timespec *tp)
+{
+  struct __timespec64 ts64;
+
+  if (! in_time_t_range (tp->tv_sec))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  valid_timespec_to_timespec64 (tp, &ts64);
+  return __clock_settime64 (clock_id, &ts64);
+}
+#endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH v2 5/7] y2038: linux: Provide __clock_getres64 implementation
  2019-04-29 10:46 ` [PATCH v2 0/7] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
                     ` (3 preceding siblings ...)
  2019-04-29 10:46   ` [PATCH v2 4/7] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
@ 2019-04-29 10:46   ` Lukasz Majewski
  2019-04-29 10:46   ` [PATCH v2 6/7] y2038: linux: Provide __clock_gettime64 implementation Lukasz Majewski
  2019-04-29 10:46   ` [PATCH v2 7/7] y2038: linux: Provide __clock_nanosleep64 implementation Lukasz Majewski
  6 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-29 10:46 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This patch provides new __clock_getres64 explicit 64 bit function for
getting the resolution (precision) of specified clock ID. Moreover, a
32 bit version - __clock_getres has been refactored to internally use
__clock_getres64.

The __clock_getres is now supposed to be used on 32 bit systems -
hence the necessary checks and conversion to 64 bit type. After this
change it is intrinsically Y2038 safe.

The new 64 bit syscall (clock_getres_time64) available from Linux
5.1+ has been used when applicable on 32 bit systems.

The __ASSUME_64BIT_TIME flag indicates if the Linux kernel provides 64 bit
version of clock_getres (i.e. clock_getres_time64). If defined - return
value is returned unconditionally. If not - the 32 bit version of this
syscall is executed instead.

When working on 32 bit systems without Y2038 time support the
clock_getres returns error when received tv_sec is wrong (i.e. overflowed).
Moreover, the correctness of tv_nsec is checked.

The execution path on 64 bit systems has not been changed or affected
in any way.

Tests:
- The code has been tested with x86_64/x86 (native compilation):
make PARALLELMFLAGS="-j8" && make xcheck PARALLELMFLAGS="-j8"

- Run specific tests on ARM/x86 32bit systems (qemu):
https://github.com/lmajewski/meta-y2038
and run tests:
https://github.com/lmajewski/y2038-tests/commits/master
on kernels with and without 64 bit time support.

No regressions were observed.

* include/time.h (__clock_getres64):
  Add __clock_getres alias according to __TIMESIZE define
* sysdeps/unix/sysv/linux/clock_getres.c (__clock_getres):
  Refactor this function to be used only on 32 bit machines as a
  wrapper on __clock_getres64.
* sysdeps/unix/sysv/linux/clock_getres.c (__clock_getres64): Add
* sysdeps/unix/sysv/linux/clock_getres.c (__clock_getres64):
  Use clock_getres_time64 kernel syscall (available from 5.1-rc1+
  Linux) by 32 bit Y2038 safe systems

---
Changes for v2:
- Add support for __ASSUME_64BIT_TIME flag when Linux kernel provides
  syscalls supporting 64 bit time on 32 bit systems
- Provide fallback to 32 bit version of clock_getres when
  clock_getres_time64 is not available
---
 include/time.h                         |  8 +++++++
 sysdeps/unix/sysv/linux/clock_getres.c | 39 +++++++++++++++++++++++++++++++++-
 2 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/include/time.h b/include/time.h
index 7f08559072..2ec5e80d9e 100644
--- a/include/time.h
+++ b/include/time.h
@@ -140,6 +140,14 @@ extern int __clock_settime64 (clockid_t clock_id,
 libc_hidden_proto (__clock_settime64)
 #endif
 
+#if __TIMESIZE == 64
+# define __clock_getres64 __clock_getres
+#else
+extern int __clock_getres64 (clockid_t clock_id,
+                             struct __timespec64 *tp);
+libc_hidden_proto (__clock_getres64);
+#endif
+
 /* Compute the `struct tm' representation of T,
    offset OFFSET seconds east of UTC,
    and store year, yday, mon, mday, wday, hour, min, sec into *TP.
diff --git a/sysdeps/unix/sysv/linux/clock_getres.c b/sysdeps/unix/sysv/linux/clock_getres.c
index 24b2299938..48dca5fc09 100644
--- a/sysdeps/unix/sysv/linux/clock_getres.c
+++ b/sysdeps/unix/sysv/linux/clock_getres.c
@@ -28,8 +28,45 @@
 
 /* Get resolution of clock.  */
 int
-__clock_getres (clockid_t clock_id, struct timespec *res)
+__clock_getres64 (clockid_t clock_id, struct __timespec64 *res)
 {
+#if defined (__TIMESIZE) && __TIMESIZE != 64
+# ifdef __NR_clock_getres_time64
+  int ret = INLINE_VSYSCALL (clock_getres_time64, 2, clock_id, res);
+#  ifdef __ASSUME_64BIT_TIME
+  return ret;
+#  else
+  if (ret == 0 || errno != ENOSYS)
+    /* Preserve non-error/non-ENOSYS return values.  */
+    return ret;
+#  endif
+# endif
+  struct timespec ts32;
+  int retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, &ts32);
+  if (! retval)
+    valid_timespec_to_timespec64(&ts32, res);
+
+  return retval;
+#else
   return INLINE_VSYSCALL (clock_getres, 2, clock_id, res);
+#endif
 }
 weak_alias (__clock_getres, clock_getres)
+
+#if __TIMESIZE != 64
+int
+__clock_getres (clockid_t clock_id, struct timespec *res)
+{
+  struct __timespec64 ts64;
+  int retval;
+
+  retval = __clock_getres64 (clock_id, &ts64);
+  if (! retval && res && ! timespec64_to_timespec (&ts64, res))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  return retval;
+}
+#endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH v2 6/7] y2038: linux: Provide __clock_gettime64 implementation
  2019-04-29 10:46 ` [PATCH v2 0/7] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
                     ` (4 preceding siblings ...)
  2019-04-29 10:46   ` [PATCH v2 5/7] y2038: linux: Provide __clock_getres64 implementation Lukasz Majewski
@ 2019-04-29 10:46   ` Lukasz Majewski
  2019-04-29 10:46   ` [PATCH v2 7/7] y2038: linux: Provide __clock_nanosleep64 implementation Lukasz Majewski
  6 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-29 10:46 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This patch provides new __clock_gettime64 explicit 64 bit function for
getting the value of specified clock ID. Moreover, a
32 bit version - __clock_gettime has been refactored to internally use
__clock_gettime64.

The __clock_gettime is now supposed to be used on 32 bit systems -
hence the necessary checks and conversion to 64 bit type. After this
change it is intrinsically Y2038 safe.

The new 64 bit syscall (clock_gettime64) available from Linux
5.1+ has been used when applicable on 32 bit systems.

The __ASSUME_64BIT_TIME flag indicates if the Linux kernel provides 64 bit
version of clock_gettime (i.e. clock_gettime64). If defined - return
value is returned unconditionally. If not - the 32 bit version of this
syscall is executed instead.

When working on 32 bit systems without Y2038 time support the
clock_gettime returns error when received tv_sec is wrong (i.e. overflowed).
Moreover, the correctness of tv_nsec is checked.

The execution path on 64 bit systems has not been changed or affected
in any way.

Tests:
- The code has been tested with x86_64/x86 (native compilation):
make PARALLELMFLAGS="-j8" && make xcheck PARALLELMFLAGS="-j8"

- Run specific tests on ARM/x86 32bit systems (qemu):
https://github.com/lmajewski/meta-y2038
and run tests:
https://github.com/lmajewski/y2038-tests/commits/master
on kernels with and without 64 bit time support.

No regressions were observed.

* include/time.h (__clock_gettime64):
  Add __clock_gettime alias according to __TIMESIZE define
* sysdeps/unix/sysv/linux/clock_gettime.c (__clock_gettime):
  Refactor this function to be used only on 32 bit machines as a
  wrapper on __clock_gettime64.
* sysdeps/unix/sysv/linux/clock_gettime.c (__clock_gettime64): Add
* sysdeps/unix/sysv/linux/clock_gettime.c (__clock_gettime64):
  Use clock_gettime64 kernel syscall (available from 5.1-rc1+
  Linux) by 32 bit Y2038 safe systems

---
Changes for v2:
- Add support for __ASSUME_64BIT_TIME flag when Linux kernel provides
  syscalls supporting 64 bit time on 32 bit systems
- Provide fallback to 32 bit version of clock_gettime when
  clock_gettime64 is not available
---
 include/time.h                          |  8 +++++++
 sysdeps/unix/sysv/linux/clock_gettime.c | 39 ++++++++++++++++++++++++++++++++-
 2 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/include/time.h b/include/time.h
index 2ec5e80d9e..73d8f1a0cc 100644
--- a/include/time.h
+++ b/include/time.h
@@ -141,6 +141,14 @@ libc_hidden_proto (__clock_settime64)
 #endif
 
 #if __TIMESIZE == 64
+# define __clock_gettime64 __clock_gettime
+#else
+extern int __clock_gettime64 (clockid_t clock_id,
+                              struct __timespec64 *tp);
+libc_hidden_proto (__clock_gettime64);
+#endif
+
+#if __TIMESIZE == 64
 # define __clock_getres64 __clock_getres
 #else
 extern int __clock_getres64 (clockid_t clock_id,
diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c
index 5fc47fb7dc..0295475c9b 100644
--- a/sysdeps/unix/sysv/linux/clock_gettime.c
+++ b/sysdeps/unix/sysv/linux/clock_gettime.c
@@ -28,9 +28,46 @@
 
 /* Get current value of CLOCK and store it in TP.  */
 int
-__clock_gettime (clockid_t clock_id, struct timespec *tp)
+__clock_gettime64 (clockid_t clock_id, struct __timespec64 *tp)
 {
+#if defined (__TIMESIZE) && __TIMESIZE != 64
+# ifdef __NR_clock_gettime64
+  int ret = INLINE_SYSCALL_CALL (clock_gettime64, clock_id, tp);
+#  ifdef __ASSUME_64BIT_TIME
+  return ret;
+#  else
+  if (ret == 0 || errno != ENOSYS)
+    /* Preserve non-error/non-ENOSYS return values.  */
+    return ret;
+#  endif
+# endif
+  struct timespec ts32;
+  int retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32);
+  if (! retval)
+    valid_timespec_to_timespec64(&ts32, tp);
+
+  return retval;
+#else
   return INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp);
+#endif
 }
 weak_alias (__clock_gettime, clock_gettime)
 libc_hidden_def (__clock_gettime)
+
+#if __TIMESIZE != 64
+int
+__clock_gettime (clockid_t clock_id, struct timespec *tp)
+{
+  struct __timespec64 ts64;
+  int retval;
+
+  retval = __clock_gettime64 (clock_id, &ts64);
+  if (! retval && ! timespec64_to_timespec (&ts64, tp))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  return retval;
+}
+#endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH v2 7/7] y2038: linux: Provide __clock_nanosleep64 implementation
  2019-04-29 10:46 ` [PATCH v2 0/7] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
                     ` (5 preceding siblings ...)
  2019-04-29 10:46   ` [PATCH v2 6/7] y2038: linux: Provide __clock_gettime64 implementation Lukasz Majewski
@ 2019-04-29 10:46   ` Lukasz Majewski
  6 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-29 10:46 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This patch provides new __clock_nanosleep64 explicit 64 bit function
for sleeping specified time on specified clock ID. Moreover, a
32 bit version - __clock_nanosleep has been refactored to internally
use __clock_nanosleep64.

The __clock_nanosleep is now supposed to be used on 32 bit systems -
hence the necessary checks and conversions to 64 bit type. After this
change it is intrinsically Y2038 safe.

The new 64 bit syscall (clock_nanosleep_time64) available from Linux
5.1+ has been used when applicable on 32 bit systems.

The __ASSUME_64BIT_TIME flag indicates if the Linux kernel provides 64 bit
version of clock_nanosleep (i.e. clock_nanosleep_time64). If defined -
return value is returned unconditionally. If not - the 32 bit version of
this syscall is executed instead.

When working on 32 bit systems without Y2038 time support the
clock_nanosleep returns error when received tv_sec is wrong (i.e.
overflowed). Moreover, the correctness of tv_nsec is checked.
The data passed to it is checked as well.

The execution path on 64 bit systems has not been changed or affected
in any way.

Tests:
- The code has been tested with x86_64/x86 (native compilation):
make PARALLELMFLAGS="-j8" && make xcheck PARALLELMFLAGS="-j8"

- Run specific tests on ARM/x86 32bit systems (qemu):
https://github.com/lmajewski/meta-y2038
and run tests:
https://github.com/lmajewski/y2038-tests/commits/master
on kernels with and without 64 bit time support.

No regressions were observed.

* include/time.h (__clock_nanosleep64):
  Add __clock_nanosleep alias according to __TIMESIZE define
* sysdeps/unix/sysv/linux/clock_nanosleep.c (__clock_nanosleep):
  Refactor this function to be used only on 32 bit machines as a
  wrapper on __clock_nanosleep64.
* sysdeps/unix/sysv/linux/clock_nanosleep.c (__clock_nanosleep64):
  Add
* sysdeps/unix/sysv/linux/clock_nanosleep.c (__clock_nanosleep64):
  Use clock_nanosleep_time64 kernel syscall (available from
  5.1-rc1+ Linux) by 32 bit Y2038 safe systems

---
Changes for v2:
- Add support for __ASSUME_64BIT_TIME flag when Linux kernel provides syscalls
supporting 64 bit time on 32 bit systems
- Provide fallback to 32 bit version of clock_nanosleep when
clock_nanosleep_time64 is not available
- Do not copy *req to timespec - this seems like an overkill as in
clock_nanosleep() the 32 bit struct timespec is copied to internal 64 bit
struct __timespec64
---
 include/time.h                            |  9 ++++
 sysdeps/unix/sysv/linux/clock_nanosleep.c | 71 +++++++++++++++++++++++++++++--
 2 files changed, 76 insertions(+), 4 deletions(-)

diff --git a/include/time.h b/include/time.h
index 73d8f1a0cc..e37e623bf4 100644
--- a/include/time.h
+++ b/include/time.h
@@ -156,6 +156,15 @@ extern int __clock_getres64 (clockid_t clock_id,
 libc_hidden_proto (__clock_getres64);
 #endif
 
+#if __TIMESIZE == 64
+# define __clock_nanosleep64 __clock_nanosleep
+#else
+extern int __clock_nanosleep64 (clockid_t clock_id, int flags,
+                                const struct __timespec64 *req,
+                                struct __timespec64 *rem);
+libc_hidden_proto (__clock_nanosleep64);
+#endif
+
 /* Compute the `struct tm' representation of T,
    offset OFFSET seconds east of UTC,
    and store year, yday, mon, mday, wday, hour, min, sec into *TP.
diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c
index 0cb6614dc9..a2b3896950 100644
--- a/sysdeps/unix/sysv/linux/clock_nanosleep.c
+++ b/sysdeps/unix/sysv/linux/clock_nanosleep.c
@@ -25,8 +25,8 @@
 /* We can simply use the syscall.  The CPU clocks are not supported
    with this function.  */
 int
-__clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
-		   struct timespec *rem)
+__clock_nanosleep64 (clockid_t clock_id, int flags,
+                     const struct __timespec64 *req, struct __timespec64 *rem)
 {
   if (clock_id == CLOCK_THREAD_CPUTIME_ID)
     return EINVAL;
@@ -36,9 +36,72 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
   /* If the call is interrupted by a signal handler or encounters an error,
      it returns a positive value similar to errno.  */
   INTERNAL_SYSCALL_DECL (err);
+#if defined (__TIMESIZE) && __TIMESIZE != 64
+  int r;
+# ifdef __NR_clock_nanosleep_time64
+  /* For 32 bit systems with no Y2038 support the *req may have tv_pad
+     with some random values as *req from __clock_nanosleep is converted
+     to automatically allocated struct __timespec64 (req64).
+
+     For 32 bit systems being Y2038 safe the tv_pad may be not zero,
+     as glibc exported struct timespec has 64 bit tv_sec, 32 bit
+     tv_nsec (to be still POSIX compliant -> long tv_nsec ) and 32
+     bits of unnamed padding.
+     If user program allocates the struct timespec automatically, the
+     padding may have random value and as being directly passed to
+     *req needs to be cleared.  */
+  timespec64_clear_padding (req);
+  r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err, clock_id,
+                               flags, req, rem);
+  int ret = (INTERNAL_SYSCALL_ERROR_P (r, err)
+             ? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
+#  ifdef __ASSUME_64BIT_TIME
+  return ret;
+#  else
+  if (r == 0 || errno != ENOSYS)
+    /* Preserve non-error/non-ENOSYS return values.  */
+    return ret;
+#  endif
+# endif
+  struct timespec req32, rem32;
+  valid_timespec64_to_timespec(req, &req32);
+  r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, err, clock_id, flags,
+                               &req32, &rem32);
+
+  if (! INTERNAL_SYSCALL_ERROR_P (r, err))
+      valid_timespec_to_timespec64(&rem32, rem);
+#else
   int r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, err, clock_id, flags,
-				   req, rem);
+                                   req, rem);
+#endif
   return (INTERNAL_SYSCALL_ERROR_P (r, err)
-	  ? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
+          ? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
 }
 weak_alias (__clock_nanosleep, clock_nanosleep)
+
+#if __TIMESIZE != 64
+int
+__clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
+                   struct timespec *rem)
+{
+  struct __timespec64 req64, rem64;
+  int retval;
+
+  if (! in_time_t_range (req->tv_sec))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  valid_timespec_to_timespec64 (req, &req64);
+  retval = __clock_nanosleep64 (clock_id, flags, &req64, &rem64);
+
+  if (! retval && rem && ! timespec64_to_timespec (&rem64, rem))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  return retval;
+}
+#endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-04-29 10:46   ` [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define Lukasz Majewski
@ 2019-04-29 21:50     ` Joseph Myers
  2019-04-30  9:05       ` Lukasz Majewski
  0 siblings, 1 reply; 111+ messages in thread
From: Joseph Myers @ 2019-04-29 21:50 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert

On Mon, 29 Apr 2019, Lukasz Majewski wrote:

> +/* Support for 64 bit version of clock_* Linux syscalls.
> +
> +   Support for following time related (and Y2038 safe) syscalls has been added
> +   in the 5.1 Linux kernel:
> +
> +   clock_gettime64 (nr. 403)
> +   clock_settime64 (nr. 404)
> +   clock_getres_time64 (nr. 406)
> +   clock_nanosleep_time64 (nr. 407)
> +  */
> +#if __LINUX_KERNEL_VERSION >= 0x050100
> +# define __ASSUME_64BIT_TIME 1
> +#endif

This comment and macro definition are the key thing that need reviewing, 
probably over several iterations, before the rest of this patch series can 
be properly reviewed.  It is critical that the comment is completely clear 
and unambiguous about the exact macro semantics on the various relevant 
classes of architectures.

See what I wrote in 
<https://sourceware.org/ml/libc-alpha/2018-09/msg00448.html> and 
<https://sourceware.org/ml/libc-alpha/2018-12/msg00568.html>.  I don't 
think the comment meets those requirements at present - that is, if you 
try to deduce from it what the macro definition should be on all the 
listed classes of architectures, either the conclusion is not clear or it 
sometimes conflicts with the actual definition.

In particular, for existing 64-bit architectures, my understanding is that 
the kernel *does not* add new syscall names or numbers for the syscalls 
you list, and so it would be incorrect to define the macro in that case, 
but this patch defines it anyway.

Note 1: the comment should not reference the above URLs; it should be 
self-contained.  As stated in the second message above, it needs to be 
clear to people who haven't read any of the mailing list discussions 
around Y2038 issues.

Note 2: if the comment actually needs to define the classes 1a, 1b, 2a, 
2b, 3, it's probably using the wrong abstractions.  It should be very 
careful to refer to the abstraction that actually most reliably determines 
the presence or absence of the new syscalls (which might be the size of 
"long int" used in the syscall interface - glibc's __syscall_slong_t, 
which happens always to be the same size as __TIMESIZE for existing glibc 
ports but might not be for future ports - but make sure of that).  Once 
the relevant abstraction is very clear, the reader can deduce the answer 
for each class of glibc ports.

Note 3: it's wrong to state the syscall numbers in the comment; that is 
not a relevant part of understanding the interface.  Stating the names, 
however, makes sense, provided you make sure not to use the __ASSUME_ 
macro for any *other* syscalls without updating the comment, and, at that 
time, reviewing whether the same definition conditions still work for all 
those syscalls.  (Given that, as previously discussed, there might be 
*some* new syscalls even for architectures that already have 64-bit time, 
in order to provide timespec-based versions of syscalls currently using 
timeval.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-04-29 21:50     ` Joseph Myers
@ 2019-04-30  9:05       ` Lukasz Majewski
  2019-04-30 21:47         ` Stepan Golosunov
  2019-05-02 15:04         ` Joseph Myers
  0 siblings, 2 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-04-30  9:05 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 5690 bytes --]

Hi Joseph,

Thanks for your reply.

> On Mon, 29 Apr 2019, Lukasz Majewski wrote:
> 
> > +/* Support for 64 bit version of clock_* Linux syscalls.
> > +
> > +   Support for following time related (and Y2038 safe) syscalls
> > has been added
> > +   in the 5.1 Linux kernel:
> > +
> > +   clock_gettime64 (nr. 403)
> > +   clock_settime64 (nr. 404)
> > +   clock_getres_time64 (nr. 406)
> > +   clock_nanosleep_time64 (nr. 407)
> > +  */
> > +#if __LINUX_KERNEL_VERSION >= 0x050100
> > +# define __ASSUME_64BIT_TIME 1
> > +#endif  
> 
> This comment and macro definition are the key thing that need
> reviewing, probably over several iterations,

Ok. Please find my comments/concerns below regarding this __ASSUME
define.

> before the rest of this
> patch series can be properly reviewed.

I would like to point out one thing - the rest of this patch series
also has an important goal - reviewing them would set the direction
(despite the __ASSUME discussion) for future Y2038 development and
conversion of other parts of glibc.

For example:

 - The decisions about the shape of internal/external struct timespec
   in glibc.

 - The need for explicit clearing padding when calling syscalls (as to
   be better safe than sorry in the future - there was related
   discussion started by Stepan).

 - If the conversion itself (__clock_settime64 vs clock_settime) is
   correct/acceptable.

Would greatly facilitate the development process and reduce the number
of iterations.

>  It is critical that the
> comment is completely clear and unambiguous about the exact macro
> semantics on the various relevant classes of architectures.
> 
> See what I wrote in 
> <https://sourceware.org/ml/libc-alpha/2018-09/msg00448.html> and 
> <https://sourceware.org/ml/libc-alpha/2018-12/msg00568.html>.  I
> don't think the comment meets those requirements at present - that
> is, if you try to deduce from it what the macro definition should be
> on all the listed classes of architectures, either the conclusion is
> not clear or it sometimes conflicts with the actual definition.
> 
> In particular, for existing 64-bit architectures, my understanding is
> that the kernel *does not* add new syscall names or numbers for the
> syscalls you list,

With the 5.1-rc6 it seems like 64 bit architectures are not add those
syscalls (like e.g. clock_settime64).

> and so it would be incorrect to define the macro
> in that case, but this patch defines it anyway.

You are right here - the 

#if __TIMESIZE != 64
# if __LINUX_KERNEL_VERSION >= 0x050100
#  define __ASSUME_64BIT_TIME 1
# endif
#endif

would do the trick.

> 
> Note 1: the comment should not reference the above URLs; it should be 
> self-contained.  As stated in the second message above, it needs to
> be clear to people who haven't read any of the mailing list
> discussions around Y2038 issues.

Ok. I will prepare self contained comment.

> 
> Note 2: if the comment actually needs to define the classes 1a, 1b,
> 2a, 2b, 3, it's probably using the wrong abstractions.  It should be
> very careful to refer to the abstraction that actually most reliably
> determines the presence or absence of the new syscalls (which might
> be the size of "long int" used in the syscall interface - glibc's
> __syscall_slong_t, which happens always to be the same size as
> __TIMESIZE for existing glibc ports but might not be for future ports
> - but make sure of that). 

The ABI (syscalls) compatibility was one of the concerns raised in this
patch series as a whole.

The glibc's internal struct __timespec64 passed to e.g. clock_settime64
syscall has explicit __time64_t (tv_sec), __int32_t (tv_nsec) and 32 bit
padding.


> Once the relevant abstraction is very
> clear, the reader can deduce the answer for each class of glibc ports.

IMHO, the abstraction would be:

1. The __ASSUME_64BIT_TIME is _never_ defined for 64 bit native systems

2. It is defined by default in:
sysdeps/unix/sysv/linux/kernel-features.h for 32 bit systems (and the
actual presence of the syscall is decided upon definitions of __NR_xxx*
(i.e. # ifdef __NR_clock_settime64).

As those syscalls are provided on almost every 32 bit system now
(5.1-rc6):
git grep -n "clock_settime64"

gives support for: arm, arm64 (compat mode), m68k, microblaze, mips,
parisc, powerpc, s390, sh, sparc, x86, xtensa

So it would be reasonable to just add this __ASSUME definition code to
sysdeps/unix/sysv/linux/kernel-features.h and #undef it for
architectures not supporting it (i.e. c-sky and riscv).

> 
> Note 3: it's wrong to state the syscall numbers in the comment; that
> is not a relevant part of understanding the interface.  Stating the
> names, however, makes sense, provided you make sure not to use the
> __ASSUME_ macro for any *other* syscalls without updating the
> comment, and, at that time, reviewing whether the same definition
> conditions still work for all those syscalls. 

Correct, the names of supported syscalls also shall be written to the
comment (and the comment itself shall be extended with other, upcoming
patches).

> (Given that, as
> previously discussed, there might be *some* new syscalls even for
> architectures that already have 64-bit time, in order to provide
> timespec-based versions of syscalls currently using timeval.)
> 



Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-04-30  9:05       ` Lukasz Majewski
@ 2019-04-30 21:47         ` Stepan Golosunov
  2019-05-02  8:51           ` Lukasz Majewski
  2019-05-02 15:04         ` Joseph Myers
  1 sibling, 1 reply; 111+ messages in thread
From: Stepan Golosunov @ 2019-04-30 21:47 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: Joseph Myers, libc-alpha, Arnd Bergmann, Paul Eggert

30.04.2019 в 11:05:05 +0200 Lukasz Majewski написал:
> #if __TIMESIZE != 64
> # if __LINUX_KERNEL_VERSION >= 0x050100
> #  define __ASSUME_64BIT_TIME 1
> # endif
> #endif

I think __WORDSIZE would be more appropriate here than __TIMESIZE.


> IMHO, the abstraction would be:
> 
> 1. The __ASSUME_64BIT_TIME is _never_ defined for 64 bit native systems
> 
> 2. It is defined by default in:
> sysdeps/unix/sysv/linux/kernel-features.h for 32 bit systems (and the
> actual presence of the syscall is decided upon definitions of __NR_xxx*
> (i.e. # ifdef __NR_clock_settime64).

I think that __NR_clock_settime64 should be used unconditionally when
__ASSUME_64BIT_TIME is defined.

(__ASSUME_TIME64_SYSCALLS would probably be better name.)


> As those syscalls are provided on almost every 32 bit system now
> (5.1-rc6):
> git grep -n "clock_settime64"
> 
> gives support for: arm, arm64 (compat mode), m68k, microblaze, mips,
> parisc, powerpc, s390, sh, sparc, x86, xtensa
> 
> So it would be reasonable to just add this __ASSUME definition code to
> sysdeps/unix/sysv/linux/kernel-features.h and #undef it for
> architectures not supporting it (i.e. c-sky and riscv).

I believe that the only 32-bit architecture without
__NR_clock_settime64 is x32.  While newer 32-bit architectures like
riscv do not have __NR_clock_settime:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d4c08b9776b392e20efc6198ebe1bc8ec1911d9b

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-04-30 21:47         ` Stepan Golosunov
@ 2019-05-02  8:51           ` Lukasz Majewski
  2019-05-02 11:54             ` Stepan Golosunov
  0 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-02  8:51 UTC (permalink / raw)
  To: Stepan Golosunov; +Cc: Joseph Myers, libc-alpha, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 2550 bytes --]

Hi Stepan,

Thank you for your reply.

> 30.04.2019 в 11:05:05 +0200 Lukasz Majewski написал:
> > #if __TIMESIZE != 64
> > # if __LINUX_KERNEL_VERSION >= 0x050100
> > #  define __ASSUME_64BIT_TIME 1
> > # endif
> > #endif  
> 
> I think __WORDSIZE would be more appropriate here than __TIMESIZE.
> 

Yes. I do agree.

> 
> > IMHO, the abstraction would be:
> > 
> > 1. The __ASSUME_64BIT_TIME is _never_ defined for 64 bit native
> > systems
> > 
> > 2. It is defined by default in:
> > sysdeps/unix/sysv/linux/kernel-features.h for 32 bit systems (and
> > the actual presence of the syscall is decided upon definitions of
> > __NR_xxx* (i.e. # ifdef __NR_clock_settime64).  
> 
> I think that __NR_clock_settime64 should be used unconditionally when
> __ASSUME_64BIT_TIME is defined.

Could you clarify it a bit?

In the code as proposed in:
https://patchwork.ozlabs.org/patch/1092583/

The call to clock_settime64 is protected with # ifdef
__NR_clock_settime64 - otherwise we do a fallback to (32 bit)
clock_settime.

Moreover, the # ifdef __ASSUME_64BIT_TIME provides a fallback path if
kernel version is older than 5.1.

> 
> (__ASSUME_TIME64_SYSCALLS would probably be better name.)

I do tend to agree. The __ASSUME_TIME64_SYSCALLS is more descriptive
than __ASSUME_64BIT_TIME.

> 
> 
> > As those syscalls are provided on almost every 32 bit system now
> > (5.1-rc6):
> > git grep -n "clock_settime64"
> > 
> > gives support for: arm, arm64 (compat mode), m68k, microblaze, mips,
> > parisc, powerpc, s390, sh, sparc, x86, xtensa
> > 
> > So it would be reasonable to just add this __ASSUME definition code
> > to sysdeps/unix/sysv/linux/kernel-features.h and #undef it for
> > architectures not supporting it (i.e. c-sky and riscv).  
> 
> I believe that the only 32-bit architecture without
> __NR_clock_settime64 is x32. 

Ok, I see. 

Please correct me - would it be feasible to just #undef
__ASSYME_TIME64_SYSCALLS for x32 ?

> While newer 32-bit architectures like
> riscv do not have __NR_clock_settime:
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d4c08b9776b392e20efc6198ebe1bc8ec1911d9b

Then it shall use clock_settime64 from the outset if support added.

Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-02  8:51           ` Lukasz Majewski
@ 2019-05-02 11:54             ` Stepan Golosunov
  2019-05-02 13:55               ` Lukasz Majewski
  0 siblings, 1 reply; 111+ messages in thread
From: Stepan Golosunov @ 2019-05-02 11:54 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: Joseph Myers, libc-alpha, Arnd Bergmann, Paul Eggert

02.05.2019 в 10:51:08 +0200 Lukasz Majewski написал:
> Hi Stepan,
> 
> > 30.04.2019 в 11:05:05 +0200 Lukasz Majewski написал:
> > > IMHO, the abstraction would be:
> > > 
> > > 1. The __ASSUME_64BIT_TIME is _never_ defined for 64 bit native
> > > systems
> > > 
> > > 2. It is defined by default in:
> > > sysdeps/unix/sysv/linux/kernel-features.h for 32 bit systems (and
> > > the actual presence of the syscall is decided upon definitions of
> > > __NR_xxx* (i.e. # ifdef __NR_clock_settime64).  
> > 
> > I think that __NR_clock_settime64 should be used unconditionally when
> > __ASSUME_64BIT_TIME is defined.
> 
> Could you clarify it a bit?

I meant something like this:

int
__clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
{
#ifdef __ASSUME_64BIT_TIME
  return INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
#else
…

But I see now that most of the existing code would just miscompile in
cases where __ASSUME_* is defined while corresponding __NR_* is not.

> In the code as proposed in:
> https://patchwork.ozlabs.org/patch/1092583/
> 
> The call to clock_settime64 is protected with # ifdef
> __NR_clock_settime64 - otherwise we do a fallback to (32 bit)
> clock_settime.
> 
> Moreover, the # ifdef __ASSUME_64BIT_TIME provides a fallback path if
> kernel version is older than 5.1.

The fallback would be wrong in cases where __NR_clock_settime is not
defined or is not 32-bit.

> > > As those syscalls are provided on almost every 32 bit system now
> > > (5.1-rc6):
> > > git grep -n "clock_settime64"
> > > 
> > > gives support for: arm, arm64 (compat mode), m68k, microblaze, mips,
> > > parisc, powerpc, s390, sh, sparc, x86, xtensa
> > > 
> > > So it would be reasonable to just add this __ASSUME definition code
> > > to sysdeps/unix/sysv/linux/kernel-features.h and #undef it for
> > > architectures not supporting it (i.e. c-sky and riscv).  
> > 
> > I believe that the only 32-bit architecture without
> > __NR_clock_settime64 is x32. 
> 
> Ok, I see. 
> 
> Please correct me - would it be feasible to just #undef
> __ASSYME_TIME64_SYSCALLS for x32 ?

You'll need to know whether to use __NR_clock_settime64 or
__NR_clock_settime in cases where __TIMESIZE == 64 and
__WORDSIZE == 32.

One way would be by defining __ASSUME_TIME64_SYSCALLS unconditionally
on x32 and then defining __NR_clock_settime64 to __NR_clock_settime
when __ASSUME_TIME64_SYSCALLS is defined while __NR_clock_settime64
isn't.

> > While newer 32-bit architectures like
> > riscv do not have __NR_clock_settime:
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d4c08b9776b392e20efc6198ebe1bc8ec1911d9b
> 
> Then it shall use clock_settime64 from the outset if support added.

It probably should have __TIMESIZE == 64 though.

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 3/7] y2038: Provide conversion helpers for struct __timespec64
  2019-04-29 10:46   ` [PATCH v2 3/7] y2038: Provide conversion helpers for struct __timespec64 Lukasz Majewski
@ 2019-05-02 11:56     ` Stepan Golosunov
  2019-05-02 14:17       ` Lukasz Majewski
  0 siblings, 1 reply; 111+ messages in thread
From: Stepan Golosunov @ 2019-05-02 11:56 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: libc-alpha, Arnd Bergmann, Paul Eggert, Joseph Myers

29.04.2019 в 12:46:09 +0200 Lukasz Majewski написал:
> +/* Set to zero the struct __timespec64's tv_pad.  */
> +static inline void
> +timespec64_clear_padding (const struct __timespec64 *tp)
> +{
> +  ((struct __timespec64*)tp)->tv_pad = 0;
> +}

Modification of const values isn't going to work.

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-02 11:54             ` Stepan Golosunov
@ 2019-05-02 13:55               ` Lukasz Majewski
  2019-05-06 13:38                 ` Lukasz Majewski
  0 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-02 13:55 UTC (permalink / raw)
  To: Stepan Golosunov; +Cc: Joseph Myers, libc-alpha, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 3379 bytes --]

Hi Stepan,

> 02.05.2019 в 10:51:08 +0200 Lukasz Majewski написал:
> > Hi Stepan,
> >   
> > > 30.04.2019 в 11:05:05 +0200 Lukasz Majewski написал:  
> > > > IMHO, the abstraction would be:
> > > > 
> > > > 1. The __ASSUME_64BIT_TIME is _never_ defined for 64 bit native
> > > > systems
> > > > 
> > > > 2. It is defined by default in:
> > > > sysdeps/unix/sysv/linux/kernel-features.h for 32 bit systems
> > > > (and the actual presence of the syscall is decided upon
> > > > definitions of __NR_xxx* (i.e. # ifdef
> > > > __NR_clock_settime64).    
> > > 
> > > I think that __NR_clock_settime64 should be used unconditionally
> > > when __ASSUME_64BIT_TIME is defined.  
> > 
> > Could you clarify it a bit?  
> 
> I meant something like this:
> 
> int
> __clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
> {
> #ifdef __ASSUME_64BIT_TIME
>   return INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
> #else
> …
> 
> But I see now that most of the existing code would just miscompile in
> cases where __ASSUME_* is defined while corresponding __NR_* is not.
> 
> > In the code as proposed in:
> > https://patchwork.ozlabs.org/patch/1092583/
> > 
> > The call to clock_settime64 is protected with # ifdef
> > __NR_clock_settime64 - otherwise we do a fallback to (32 bit)
> > clock_settime.
> > 
> > Moreover, the # ifdef __ASSUME_64BIT_TIME provides a fallback path
> > if kernel version is older than 5.1.  
> 
> The fallback would be wrong in cases where __NR_clock_settime is not
> defined or is not 32-bit.
> 
> > > > As those syscalls are provided on almost every 32 bit system now
> > > > (5.1-rc6):
> > > > git grep -n "clock_settime64"
> > > > 
> > > > gives support for: arm, arm64 (compat mode), m68k, microblaze,
> > > > mips, parisc, powerpc, s390, sh, sparc, x86, xtensa
> > > > 
> > > > So it would be reasonable to just add this __ASSUME definition
> > > > code to sysdeps/unix/sysv/linux/kernel-features.h and #undef it
> > > > for architectures not supporting it (i.e. c-sky and riscv).    
> > > 
> > > I believe that the only 32-bit architecture without
> > > __NR_clock_settime64 is x32.   
> > 
> > Ok, I see. 
> > 
> > Please correct me - would it be feasible to just #undef
> > __ASSYME_TIME64_SYSCALLS for x32 ?  
> 
> You'll need to know whether to use __NR_clock_settime64 or
> __NR_clock_settime in cases where __TIMESIZE == 64 and
> __WORDSIZE == 32.
> 
> One way would be by defining __ASSUME_TIME64_SYSCALLS unconditionally
> on x32 and then defining __NR_clock_settime64 to __NR_clock_settime
> when __ASSUME_TIME64_SYSCALLS is defined while __NR_clock_settime64
> isn't.
> 

I see. Thanks for the hint.

> > > While newer 32-bit architectures like
> > > riscv do not have __NR_clock_settime:
> > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d4c08b9776b392e20efc6198ebe1bc8ec1911d9b  
> > 
> > Then it shall use clock_settime64 from the outset if support
> > added.  
> 
> It probably should have __TIMESIZE == 64 though.


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 3/7] y2038: Provide conversion helpers for struct __timespec64
  2019-05-02 11:56     ` Stepan Golosunov
@ 2019-05-02 14:17       ` Lukasz Majewski
  2019-05-02 15:59         ` Joseph Myers
  0 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-02 14:17 UTC (permalink / raw)
  To: Stepan Golosunov, Paul Eggert, Joseph Myers; +Cc: libc-alpha, Arnd Bergmann

[-- Attachment #1: Type: text/plain, Size: 1534 bytes --]

Hi Stepan,

> 29.04.2019 в 12:46:09 +0200 Lukasz Majewski написал:
> > +/* Set to zero the struct __timespec64's tv_pad.  */
> > +static inline void
> > +timespec64_clear_padding (const struct __timespec64 *tp)
> > +{
> > +  ((struct __timespec64*)tp)->tv_pad = 0;
> > +}  
> 
> Modification of const values isn't going to work.

This was added as a special precaution to avoid passing random data to
kernel syscalls for the Y2038 support use case on 32 bit systems (where
tv_nsec is 32 bit long) .

As we discussed in the other thread - kernel relies on "implementation
depended" behaviour from GCC (which is now to discard higher 32 bits
from tv_nsec [1]).

It is up to glibc community to decide if such precaution is necessary or
shall we only rely on kernel (and gcc) behaviour.


With this particular patch - the problem is with struct timespec's *tp
pointer being const for data being passed to the kernel (to avoid
creating explicit copy of struct timespec and pass it to kernel
syscall).


Note:

[1] - kernel/time/time.c -> get_timespec64: 
ts->tv_nsec = kts.tv_nsec;

(64 bit's kts.tv_nsec to 32 bit tv_nsec truncation).

Discussion:
https://patchwork.ozlabs.org/patch/1085397/
https://lkml.org/lkml/2019/4/26/600


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-04-30  9:05       ` Lukasz Majewski
  2019-04-30 21:47         ` Stepan Golosunov
@ 2019-05-02 15:04         ` Joseph Myers
  2019-05-05 14:10           ` Stepan Golosunov
  2019-05-06 14:56           ` Lukasz Majewski
  1 sibling, 2 replies; 111+ messages in thread
From: Joseph Myers @ 2019-05-02 15:04 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert

On Tue, 30 Apr 2019, Lukasz Majewski wrote:

>  - The need for explicit clearing padding when calling syscalls (as to
>    be better safe than sorry in the future - there was related
>    discussion started by Stepan).

This really isn't a difficult question.  What it comes down to is whether 
the Linux kernel, in the first release version with these syscalls (we 
don't care about old -rc versions; what matters is the actual 5.1 
release), ignores the padding.

If 5.1 *release* ignores the padding, that is part of the kernel/userspace 
ABI, in accordance with the kernel principle of not breaking userspace.  
Thus, it is something userspace can rely on, now and in the future.

If 5.1 release does not ignore the padding, syscall presence does not mean 
the padding is ignored by the kernel and so glibc needs to clear padding.  
Of course, it needs to clear padding in a *copy* of the value provided by 
the user unless the glibc API in question requires the timespec value in 
question to be in writable memory.

So, which is (or will be) the case in 5.1 release?  Padding ignored or 
not?  If more complicated (ignored for some architectures / ABIs but not 
for others, or depending on whether compat syscalls are in use), then say 
so - give a precise description of the exact circumstances under which the 
padding around a 32-bit tv_nsec will or will not be ignored by the kernel 
on input from userspace.

(x32 is a separate matter, as it already has 64-bit times, and a 
non-POSIX-conforming tv_nsec, so this patch series just needs to avoid 
breaking anything that currently works there.  Any fix for bug 16437 would 
need to involve clearing padding in userspace, unless not only the kernel 
changes to ignore that padding but all kernel versions without such a 
change cease to be supported by glibc for x32.)

> You are right here - the 
> 
> #if __TIMESIZE != 64
> # if __LINUX_KERNEL_VERSION >= 0x050100
> #  define __ASSUME_64BIT_TIME 1
> # endif
> #endif
> 
> would do the trick.

But that wouldn't be right for *future* configurations where the kernel 
"long" is 32-bit but only 64-bit time is supported in the kernel and glibc 
(so __TIMESIZE is 64, and only the new syscalls and not the old ones are 
supported).  That is, the right abstraction here is not really __TIMESIZE.

It's possible it's __SYSCALL_WORDSIZE, except that's only defined for 
x86_64, so would need to be made more generally available if it's to be 
used here.  And if made more generally available, it would need a careful 
comment explaining exactly what it means.

> 1. The __ASSUME_64BIT_TIME is _never_ defined for 64 bit native systems
> 
> 2. It is defined by default in:
> sysdeps/unix/sysv/linux/kernel-features.h for 32 bit systems (and the

It would be best to avoid descriptions such as "64 bit native systems" and 
"32 bit systems" when defining the relevant abstractions, because they are 
simply too ambiguous in this context, where one of the key thing to do is 
to make the semantics obvious in cases that have some attributes of 32-bit 
systems and other attributes of 64-bit systems.

We have configurations such as x32 and MIPS n32 which have 64-bit 
registers but 32-bit "long" and pointers.  Are those 64-bit or 32-bit?  As 
far as glibc's definition of __WORDSIZE is concerned, they are 32-bit; 
__WORDSIZE is the size in bits of long and pointers.  As far as optimized 
code working one word at a time is concerned (libm functions, string 
functions, etc.), they are best considered 64-bit, because of the 64-bit 
registers.  For the present issue, they are *different* from each other: 
x32 does not have the new syscalls (it already had 64-bit times), n32 does 
have the new syscalls (it previously had 32-bit times).

Again, I think the size of __syscall_slong_t is probably what's relevant.  
Note that "size of long for syscalls" (which is 64-bit for x32 but 32-bit 
for n32) is *not* the same thing as "size passed in a single register for 
syscalls" (n32 passes 64-bits values in a single register to syscalls, on 
the principle of keeping the ABI for those similar to that for normal 
function calls; but there have been more recent suggestions in the kernel 
context - I don't know the conclusion from them - of whether future such 
ILP32 ABIs with 64-bit registers should be more similar to the ABIs using 
32-bit registers, to allow compat syscall code to be used for them more 
consistently).

> As those syscalls are provided on almost every 32 bit system now
> (5.1-rc6):
> git grep -n "clock_settime64"
> 
> gives support for: arm, arm64 (compat mode), m68k, microblaze, mips,
> parisc, powerpc, s390, sh, sparc, x86, xtensa
> 
> So it would be reasonable to just add this __ASSUME definition code to
> sysdeps/unix/sysv/linux/kernel-features.h and #undef it for
> architectures not supporting it (i.e. c-sky and riscv).

No, that's not accurate.  Newer architectures (such as csky and riscv) use 
the asm-generic syscall table and so get these syscalls automatically if 
__BITS_PER_LONG == 32.  So it would be wrong to #undef in those cases.

When checking each glibc architecture / ABI combination, to see if the 
syscalls are present in the kernel, you need to allow for some 
architectures using asm-generic (which means that for such architectures 
you only need to check the generic logic, then look at any compat syscall 
tables, such as for arm on arm64).  For architectures not using 
asm-generic you need to check the per-architecture syscalls tables for 
each relevant ABI.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 3/7] y2038: Provide conversion helpers for struct __timespec64
  2019-05-02 14:17       ` Lukasz Majewski
@ 2019-05-02 15:59         ` Joseph Myers
  2019-05-02 16:19           ` Lukasz Majewski
  0 siblings, 1 reply; 111+ messages in thread
From: Joseph Myers @ 2019-05-02 15:59 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: Stepan Golosunov, Paul Eggert, libc-alpha, Arnd Bergmann

On Thu, 2 May 2019, Lukasz Majewski wrote:

> As we discussed in the other thread - kernel relies on "implementation
> depended" behaviour from GCC (which is now to discard higher 32 bits
> from tv_nsec [1]).

The kernel and glibc use a common-usage profile of C, which defines 
conversion of integer types to narrower integer types as modulo.  We do 
not need to be concerned about strange implementations making other 
choices for such conversions; they are not relevant for building the 
kernel.  (This is a separate matter from undefined behavior for signed 
arithmetic overflow.)

In the current draft of the next C++ standard revision, this is required 
for C++, and it's entirely plausible that C will follow at some point.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 3/7] y2038: Provide conversion helpers for struct __timespec64
  2019-05-02 15:59         ` Joseph Myers
@ 2019-05-02 16:19           ` Lukasz Majewski
  0 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-02 16:19 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Stepan Golosunov, Paul Eggert, libc-alpha, Arnd Bergmann

[-- Attachment #1: Type: text/plain, Size: 1321 bytes --]

Hi Joseph,

> On Thu, 2 May 2019, Lukasz Majewski wrote:
> 
> > As we discussed in the other thread - kernel relies on
> > "implementation depended" behaviour from GCC (which is now to
> > discard higher 32 bits from tv_nsec [1]).  
> 
> The kernel and glibc use a common-usage profile of C, which defines 
> conversion of integer types to narrower integer types as modulo.  We
> do not need to be concerned about strange implementations making
> other choices for such conversions; they are not relevant for
> building the kernel.  (This is a separate matter from undefined
> behavior for signed arithmetic overflow.)
> 
> In the current draft of the next C++ standard revision, this is
> required for C++, and it's entirely plausible that C will follow at
> some point.
> 

Thank you for a detailed explanation.

As Arnd in the other mail [1] confirmed that the intention of the
kernel is to ignore padding - zero'ing padding can be safely removed
from this glibc patch series.


Note:

[1] - https://lkml.org/lkml/2019/4/22/824

Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-02 15:04         ` Joseph Myers
@ 2019-05-05 14:10           ` Stepan Golosunov
  2019-05-05 20:46             ` Lukasz Majewski
  2019-05-06 14:56           ` Lukasz Majewski
  1 sibling, 1 reply; 111+ messages in thread
From: Stepan Golosunov @ 2019-05-05 14:10 UTC (permalink / raw)
  To: Joseph Myers, Linus Torvalds
  Cc: Thomas Gleixner, linux-kernel, Lukasz Majewski, libc-alpha,
	Arnd Bergmann, Paul Eggert

02.05.2019 в 15:04:18 +0000 Joseph Myers написал:
> On Tue, 30 Apr 2019, Lukasz Majewski wrote:
> 
> >  - The need for explicit clearing padding when calling syscalls (as to
> >    be better safe than sorry in the future - there was related
> >    discussion started by Stepan).
> 
> This really isn't a difficult question.  What it comes down to is whether 
> the Linux kernel, in the first release version with these syscalls (we 
> don't care about old -rc versions; what matters is the actual 5.1 
> release), ignores the padding.
> 
> If 5.1 *release* ignores the padding, that is part of the kernel/userspace 
> ABI, in accordance with the kernel principle of not breaking userspace.  
> Thus, it is something userspace can rely on, now and in the future.
> 
> If 5.1 release does not ignore the padding, syscall presence does not mean 
> the padding is ignored by the kernel and so glibc needs to clear padding.  
> Of course, it needs to clear padding in a *copy* of the value provided by 
> the user unless the glibc API in question requires the timespec value in 
> question to be in writable memory.
> 
> So, which is (or will be) the case in 5.1 release?  Padding ignored or 
> not?  If more complicated (ignored for some architectures / ABIs but not 
> for others, or depending on whether compat syscalls are in use), then say 
> so - give a precise description of the exact circumstances under which the 
> padding around a 32-bit tv_nsec will or will not be ignored by the kernel 
> on input from userspace.

In current linux git it looks like padding is correctly ignored in
32-bit kernels (because kernel itself has 32-bit tv_nsec there) but
the code to clear it on compat syscalls in 64-bit kernels seems to be
broken.

The patch to fix this is at

https://lore.kernel.org/lkml/20190429131951.471701-1-arnd@arndb.de/

but it doesn't seem like it has reached Linus yet.


(Hmm.  I think that old ipc and socketcall syscalls in 32-bit kernels
are broken without that patch too.  They would try to read
__kernel_timespec when callers are passing old_timespec32.)

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-05 14:10           ` Stepan Golosunov
@ 2019-05-05 20:46             ` Lukasz Majewski
  0 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-05 20:46 UTC (permalink / raw)
  To: Stepan Golosunov
  Cc: Joseph Myers, Linus Torvalds, Thomas Gleixner, linux-kernel,
	libc-alpha, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 2903 bytes --]

On Sun, 5 May 2019 18:10:54 +0400
Stepan Golosunov <stepan@golosunov.pp.ru> wrote:

> 02.05.2019 в 15:04:18 +0000 Joseph Myers написал:
> > On Tue, 30 Apr 2019, Lukasz Majewski wrote:
> >   
> > >  - The need for explicit clearing padding when calling syscalls
> > > (as to be better safe than sorry in the future - there was related
> > >    discussion started by Stepan).  
> > 
> > This really isn't a difficult question.  What it comes down to is
> > whether the Linux kernel, in the first release version with these
> > syscalls (we don't care about old -rc versions; what matters is the
> > actual 5.1 release), ignores the padding.
> > 
> > If 5.1 *release* ignores the padding, that is part of the
> > kernel/userspace ABI, in accordance with the kernel principle of
> > not breaking userspace. Thus, it is something userspace can rely
> > on, now and in the future.
> > 
> > If 5.1 release does not ignore the padding, syscall presence does
> > not mean the padding is ignored by the kernel and so glibc needs to
> > clear padding. Of course, it needs to clear padding in a *copy* of
> > the value provided by the user unless the glibc API in question
> > requires the timespec value in question to be in writable memory.
> > 
> > So, which is (or will be) the case in 5.1 release?  Padding ignored
> > or not?  If more complicated (ignored for some architectures / ABIs
> > but not for others, or depending on whether compat syscalls are in
> > use), then say so - give a precise description of the exact
> > circumstances under which the padding around a 32-bit tv_nsec will
> > or will not be ignored by the kernel on input from userspace.  
> 
> In current linux git it looks like padding is correctly ignored in
> 32-bit kernels (because kernel itself has 32-bit tv_nsec there) but
> the code to clear it on compat syscalls in 64-bit kernels seems to be
> broken.
> 
> The patch to fix this is at
> 
> https://lore.kernel.org/lkml/20190429131951.471701-1-arnd@arndb.de/
> 
> but it doesn't seem like it has reached Linus yet.
> 

I hope that this patch will be pulled soon (before final cut) - for that
reason we can assume that the padding is ignored by the kernel and
hence do not explicitly clear it in glibc (as it was done in sent
patches)

> 
> (Hmm.  I think that old ipc and socketcall syscalls in 32-bit kernels
> are broken without that patch too.  They would try to read
> __kernel_timespec when callers are passing old_timespec32.)

Please correct me if I'm wrong, but this problem is related to x32
machines (and not to ARM 32 bit ones with Y2038).


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-02 13:55               ` Lukasz Majewski
@ 2019-05-06 13:38                 ` Lukasz Majewski
  2019-05-06 14:26                   ` Lukasz Majewski
  0 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-06 13:38 UTC (permalink / raw)
  To: Stepan Golosunov; +Cc: Joseph Myers, libc-alpha, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 4198 bytes --]

Hi Stepan,

> Hi Stepan,
> 
> > 02.05.2019 в 10:51:08 +0200 Lukasz Majewski написал:  
> > > Hi Stepan,
> > >     
> > > > 30.04.2019 в 11:05:05 +0200 Lukasz Majewski написал:    
> > > > > IMHO, the abstraction would be:
> > > > > 
> > > > > 1. The __ASSUME_64BIT_TIME is _never_ defined for 64 bit
> > > > > native systems
> > > > > 
> > > > > 2. It is defined by default in:
> > > > > sysdeps/unix/sysv/linux/kernel-features.h for 32 bit systems
> > > > > (and the actual presence of the syscall is decided upon
> > > > > definitions of __NR_xxx* (i.e. # ifdef
> > > > > __NR_clock_settime64).      
> > > > 
> > > > I think that __NR_clock_settime64 should be used unconditionally
> > > > when __ASSUME_64BIT_TIME is defined.    
> > > 
> > > Could you clarify it a bit?    
> > 
> > I meant something like this:
> > 
> > int
> > __clock_settime64 (clockid_t clock_id, const struct __timespec64
> > *tp) {
> > #ifdef __ASSUME_64BIT_TIME
> >   return INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
> > #else
> > …
> > 
> > But I see now that most of the existing code would just miscompile
> > in cases where __ASSUME_* is defined while corresponding __NR_* is
> > not. 
> > > In the code as proposed in:
> > > https://patchwork.ozlabs.org/patch/1092583/
> > > 
> > > The call to clock_settime64 is protected with # ifdef
> > > __NR_clock_settime64 - otherwise we do a fallback to (32 bit)
> > > clock_settime.
> > > 
> > > Moreover, the # ifdef __ASSUME_64BIT_TIME provides a fallback path
> > > if kernel version is older than 5.1.    
> > 
> > The fallback would be wrong in cases where __NR_clock_settime is not
> > defined or is not 32-bit.
> >   
> > > > > As those syscalls are provided on almost every 32 bit system
> > > > > now (5.1-rc6):
> > > > > git grep -n "clock_settime64"
> > > > > 
> > > > > gives support for: arm, arm64 (compat mode), m68k, microblaze,
> > > > > mips, parisc, powerpc, s390, sh, sparc, x86, xtensa
> > > > > 
> > > > > So it would be reasonable to just add this __ASSUME definition
> > > > > code to sysdeps/unix/sysv/linux/kernel-features.h and #undef
> > > > > it for architectures not supporting it (i.e. c-sky and
> > > > > riscv).      
> > > > 
> > > > I believe that the only 32-bit architecture without
> > > > __NR_clock_settime64 is x32.     
> > > 
> > > Ok, I see. 
> > > 
> > > Please correct me - would it be feasible to just #undef
> > > __ASSYME_TIME64_SYSCALLS for x32 ?    
> > 
> > You'll need to know whether to use __NR_clock_settime64 or
> > __NR_clock_settime in cases where __TIMESIZE == 64 and
> > __WORDSIZE == 32.

Please correct me, but I do have some doubts here.

As x32 now uses 64 bit time (and has TIMESIZE==64) - it uses the
clock_settime call (with in-kernel broken tv_nsec padding clearing -
but for this the fix is in its way to upstream).

Why does it need to also support clock_settime64 ? 

> > 
> > One way would be by defining __ASSUME_TIME64_SYSCALLS
> > unconditionally on x32 and then defining __NR_clock_settime64 to
> > __NR_clock_settime when __ASSUME_TIME64_SYSCALLS is defined while
> > __NR_clock_settime64 isn't.
> >   
> 
> I see. Thanks for the hint.
> 
> > > > While newer 32-bit architectures like
> > > > riscv do not have __NR_clock_settime:
> > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d4c08b9776b392e20efc6198ebe1bc8ec1911d9b    
> > > 
> > > Then it shall use clock_settime64 from the outset if support
> > > added.    
> > 
> > It probably should have __TIMESIZE == 64 though.  
> 
> 
> Best regards,
> 
> Lukasz Majewski
> 
> --
> 
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email:
> lukma@denx.de




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-06 13:38                 ` Lukasz Majewski
@ 2019-05-06 14:26                   ` Lukasz Majewski
  2019-05-06 19:36                     ` Stepan Golosunov
  0 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-06 14:26 UTC (permalink / raw)
  To: Stepan Golosunov; +Cc: Joseph Myers, libc-alpha, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 5196 bytes --]

Hi Stepan,

> Hi Stepan,
> 
> > Hi Stepan,
> >   
> > > 02.05.2019 в 10:51:08 +0200 Lukasz Majewski написал:    
> > > > Hi Stepan,
> > > >       
> > > > > 30.04.2019 в 11:05:05 +0200 Lukasz Majewski написал:      
> > > > > > IMHO, the abstraction would be:
> > > > > > 
> > > > > > 1. The __ASSUME_64BIT_TIME is _never_ defined for 64 bit
> > > > > > native systems
> > > > > > 
> > > > > > 2. It is defined by default in:
> > > > > > sysdeps/unix/sysv/linux/kernel-features.h for 32 bit systems
> > > > > > (and the actual presence of the syscall is decided upon
> > > > > > definitions of __NR_xxx* (i.e. # ifdef
> > > > > > __NR_clock_settime64).        
> > > > > 
> > > > > I think that __NR_clock_settime64 should be used
> > > > > unconditionally when __ASSUME_64BIT_TIME is defined.      
> > > > 
> > > > Could you clarify it a bit?      
> > > 
> > > I meant something like this:
> > > 
> > > int
> > > __clock_settime64 (clockid_t clock_id, const struct __timespec64
> > > *tp) {
> > > #ifdef __ASSUME_64BIT_TIME
> > >   return INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
> > > #else
> > > …
> > > 
> > > But I see now that most of the existing code would just miscompile
> > > in cases where __ASSUME_* is defined while corresponding __NR_* is
> > > not.   
> > > > In the code as proposed in:
> > > > https://patchwork.ozlabs.org/patch/1092583/
> > > > 
> > > > The call to clock_settime64 is protected with # ifdef
> > > > __NR_clock_settime64 - otherwise we do a fallback to (32 bit)
> > > > clock_settime.
> > > > 
> > > > Moreover, the # ifdef __ASSUME_64BIT_TIME provides a fallback
> > > > path if kernel version is older than 5.1.      
> > > 
> > > The fallback would be wrong in cases where __NR_clock_settime is
> > > not defined or is not 32-bit.
> > >     
> > > > > > As those syscalls are provided on almost every 32 bit system
> > > > > > now (5.1-rc6):
> > > > > > git grep -n "clock_settime64"
> > > > > > 
> > > > > > gives support for: arm, arm64 (compat mode), m68k,
> > > > > > microblaze, mips, parisc, powerpc, s390, sh, sparc, x86,
> > > > > > xtensa
> > > > > > 
> > > > > > So it would be reasonable to just add this __ASSUME
> > > > > > definition code to
> > > > > > sysdeps/unix/sysv/linux/kernel-features.h and #undef it for
> > > > > > architectures not supporting it (i.e. c-sky and
> > > > > > riscv).        
> > > > > 
> > > > > I believe that the only 32-bit architecture without
> > > > > __NR_clock_settime64 is x32.       
> > > > 
> > > > Ok, I see. 
> > > > 
> > > > Please correct me - would it be feasible to just #undef
> > > > __ASSYME_TIME64_SYSCALLS for x32 ?      
> > > 
> > > You'll need to know whether to use __NR_clock_settime64 or
> > > __NR_clock_settime in cases where __TIMESIZE == 64 and
> > > __WORDSIZE == 32.  
> 
> Please correct me, but I do have some doubts here.
> 
> As x32 now uses 64 bit time (and has TIMESIZE==64) - it uses the
> clock_settime call (with in-kernel broken tv_nsec padding clearing -
> but for this the fix is in its way to upstream).
> 
> Why does it need to also support clock_settime64 ? 

I was too eager to send the mail.

It is connected with your proposition to use __WORDSIZE for #ifdef on
__ASSUME_TIME64_SYSCALLS. 

As x32 has __WORDSIZE=32 (but __TIMESIZE=64), it would fall into
"category" of archs using explicit 64 bit calls (i.e. clock_settime64).

However, for it - those shall be replaced with syscalls used up till now
(i.e. clock_settime).

Am I right here ?

> 
> > > 
> > > One way would be by defining __ASSUME_TIME64_SYSCALLS
> > > unconditionally on x32 and then defining __NR_clock_settime64 to
> > > __NR_clock_settime when __ASSUME_TIME64_SYSCALLS is defined while
> > > __NR_clock_settime64 isn't.
> > >     
> > 
> > I see. Thanks for the hint.
> >   
> > > > > While newer 32-bit architectures like
> > > > > riscv do not have __NR_clock_settime:
> > > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d4c08b9776b392e20efc6198ebe1bc8ec1911d9b      
> > > > 
> > > > Then it shall use clock_settime64 from the outset if support
> > > > added.      
> > > 
> > > It probably should have __TIMESIZE == 64 though.    
> > 
> > 
> > Best regards,
> > 
> > Lukasz Majewski
> > 
> > --
> > 
> > DENX Software Engineering GmbH,      Managing Director: Wolfgang
> > Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell,
> > Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email:
> > lukma@denx.de  
> 
> 
> 
> 
> Best regards,
> 
> Lukasz Majewski
> 
> --
> 
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email:
> lukma@denx.de




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-02 15:04         ` Joseph Myers
  2019-05-05 14:10           ` Stepan Golosunov
@ 2019-05-06 14:56           ` Lukasz Majewski
  2019-05-07 15:35             ` Joseph Myers
  1 sibling, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-06 14:56 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 7298 bytes --]

Hi Joseph,

> On Tue, 30 Apr 2019, Lukasz Majewski wrote:
> 
> >  - The need for explicit clearing padding when calling syscalls (as
> > to be better safe than sorry in the future - there was related
> >    discussion started by Stepan).  
> 
> This really isn't a difficult question.  What it comes down to is
> whether the Linux kernel, in the first release version with these
> syscalls (we don't care about old -rc versions; what matters is the
> actual 5.1 release), ignores the padding.
> 
> If 5.1 *release* ignores the padding, that is part of the
> kernel/userspace ABI, in accordance with the kernel principle of not
> breaking userspace. Thus, it is something userspace can rely on, now
> and in the future.
> 
> If 5.1 release does not ignore the padding, syscall presence does not
> mean the padding is ignored by the kernel and so glibc needs to clear
> padding. Of course, it needs to clear padding in a *copy* of the
> value provided by the user unless the glibc API in question requires
> the timespec value in question to be in writable memory.
> 
> So, which is (or will be) the case in 5.1 release?  Padding ignored
> or not?

As confirmed in the other mail - the padding is ignored in Linux kernel
(and the fix patch for x32 is up its way to be pulled).

>  If more complicated (ignored for some architectures / ABIs
> but not for others, or depending on whether compat syscalls are in
> use), then say so - give a precise description of the exact
> circumstances under which the padding around a 32-bit tv_nsec will or
> will not be ignored by the kernel on input from userspace.
> 
> (x32 is a separate matter, as it already has 64-bit times, and a 
> non-POSIX-conforming tv_nsec, so this patch series just needs to
> avoid breaking anything that currently works there.  Any fix for bug
> 16437 would need to involve clearing padding in userspace, unless not
> only the kernel changes to ignore that padding but all kernel
> versions without such a change cease to be supported by glibc for
> x32.)
> 
> > You are right here - the 
> > 
> > #if __TIMESIZE != 64
> > # if __LINUX_KERNEL_VERSION >= 0x050100
> > #  define __ASSUME_64BIT_TIME 1
> > # endif
> > #endif
> > 
> > would do the trick.  
> 
> But that wouldn't be right for *future* configurations where the
> kernel "long" is 32-bit but only 64-bit time is supported in the
> kernel and glibc (so __TIMESIZE is 64, and only the new syscalls and
> not the old ones are supported).  That is, the right abstraction here
> is not really __TIMESIZE.
> 
> It's possible it's __SYSCALL_WORDSIZE, except that's only defined for 
> x86_64, so would need to be made more generally available if it's to
> be used here.  And if made more generally available, it would need a
> careful comment explaining exactly what it means.

Cannot we just use __WORDSIZE != 64  as proposed by Stepan?
(for x32 we would have it defined by default)

#if __WORDSIZE != 64
# if __LINUX_KERNEL_VERSION >= 0x050100
#  define __ASSUME_TIME64_SYSCALLS 1
# endif
#endif  

Such approach would allow us to avoid introducing new abstraction
(__SYSCALL_WORDSIZE).

As of now only x32 has __WORDSIZE=32 and __TIMESIZE=64 and would be
treated as a special case with solution proposed by Stepan in the
other mail:

---->8-----
One way would be by defining __ASSUME_TIME64_SYSCALLS unconditionally
on x32 and then defining __NR_clock_settime64 to __NR_clock_settime
when __ASSUME_TIME64_SYSCALLS is defined while __NR_clock_settime64
isn't.
----8<-----

Or even simpler:
#undef __ASSUME_TIME64_SYSCALLS for x32 (with proper comment)

x32 is special here - if (unlikely) some other arch with __WORDSIZE=32
and __TIMESIZE=64 emerge - it shall follow the same pattern




For __WORDSIZE/__TIMESIZE=32 and __WORDSIZE/__TIMESIZE=64 archs we
would have a clear situation.


> 
> > 1. The __ASSUME_64BIT_TIME is _never_ defined for 64 bit native
> > systems
> > 
> > 2. It is defined by default in:
> > sysdeps/unix/sysv/linux/kernel-features.h for 32 bit systems (and
> > the  
> 
> It would be best to avoid descriptions such as "64 bit native
> systems" and "32 bit systems" when defining the relevant
> abstractions, because they are simply too ambiguous in this context,
> where one of the key thing to do is to make the semantics obvious in
> cases that have some attributes of 32-bit systems and other
> attributes of 64-bit systems.
> 
> We have configurations such as x32 and MIPS n32 which have 64-bit 
> registers but 32-bit "long" and pointers.  Are those 64-bit or
> 32-bit?  As far as glibc's definition of __WORDSIZE is concerned,
> they are 32-bit; __WORDSIZE is the size in bits of long and
> pointers.  As far as optimized code working one word at a time is
> concerned (libm functions, string functions, etc.), they are best
> considered 64-bit, because of the 64-bit registers.  For the present
> issue, they are *different* from each other: x32 does not have the
> new syscalls (it already had 64-bit times), n32 does have the new
> syscalls (it previously had 32-bit times).
> 
> Again, I think the size of __syscall_slong_t is probably what's
> relevant. Note that "size of long for syscalls" (which is 64-bit for
> x32 but 32-bit for n32) is *not* the same thing as "size passed in a
> single register for syscalls" (n32 passes 64-bits values in a single
> register to syscalls, on the principle of keeping the ABI for those
> similar to that for normal function calls; but there have been more
> recent suggestions in the kernel context - I don't know the
> conclusion from them - of whether future such ILP32 ABIs with 64-bit
> registers should be more similar to the ABIs using 32-bit registers,
> to allow compat syscall code to be used for them more consistently).
> 
> > As those syscalls are provided on almost every 32 bit system now
> > (5.1-rc6):
> > git grep -n "clock_settime64"
> > 
> > gives support for: arm, arm64 (compat mode), m68k, microblaze, mips,
> > parisc, powerpc, s390, sh, sparc, x86, xtensa
> > 
> > So it would be reasonable to just add this __ASSUME definition code
> > to sysdeps/unix/sysv/linux/kernel-features.h and #undef it for
> > architectures not supporting it (i.e. c-sky and riscv).  
> 
> No, that's not accurate.  Newer architectures (such as csky and
> riscv) use the asm-generic syscall table and so get these syscalls
> automatically if __BITS_PER_LONG == 32.  So it would be wrong to
> #undef in those cases.
> 
> When checking each glibc architecture / ABI combination, to see if
> the syscalls are present in the kernel, you need to allow for some 
> architectures using asm-generic (which means that for such
> architectures you only need to check the generic logic, then look at
> any compat syscall tables, such as for arm on arm64).  For
> architectures not using asm-generic you need to check the
> per-architecture syscalls tables for each relevant ABI.
> 




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-06 14:26                   ` Lukasz Majewski
@ 2019-05-06 19:36                     ` Stepan Golosunov
  2019-05-06 21:14                       ` Lukasz Majewski
  2019-05-07 15:43                       ` Joseph Myers
  0 siblings, 2 replies; 111+ messages in thread
From: Stepan Golosunov @ 2019-05-06 19:36 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: Joseph Myers, libc-alpha, Arnd Bergmann, Paul Eggert

06.05.2019 в 16:26:59 +0200 Lukasz Majewski написал:

> > > > > > I believe that the only 32-bit architecture without
> > > > > > __NR_clock_settime64 is x32.       
> > > > > 
> > > > > Ok, I see. 
> > > > > 
> > > > > Please correct me - would it be feasible to just #undef
> > > > > __ASSYME_TIME64_SYSCALLS for x32 ?      
> > > > 
> > > > You'll need to know whether to use __NR_clock_settime64 or
> > > > __NR_clock_settime in cases where __TIMESIZE == 64 and
> > > > __WORDSIZE == 32.  
> > 
> > Please correct me, but I do have some doubts here.
> > 
> > As x32 now uses 64 bit time (and has TIMESIZE==64) - it uses the
> > clock_settime call (with in-kernel broken tv_nsec padding clearing -
> > but for this the fix is in its way to upstream).
> > 
> > Why does it need to also support clock_settime64 ? 
> 
> I was too eager to send the mail.
> 
> It is connected with your proposition to use __WORDSIZE for #ifdef on
> __ASSUME_TIME64_SYSCALLS. 
> 
> As x32 has __WORDSIZE=32 (but __TIMESIZE=64), it would fall into
> "category" of archs using explicit 64 bit calls (i.e. clock_settime64).
> 
> However, for it - those shall be replaced with syscalls used up till now
> (i.e. clock_settime).
> 
> Am I right here ?

x32 has __WORDSIZE==32 and __TIMESIZE==64.  Future 32-bit
architectures should have __WORDSIZE==32 and __TIMESIZE==64 too.  And
the only difference in implementation of clock_settime64 function there
should be name of syscall (ignoring possible padding clearing
issues).

> > > > One way would be by defining __ASSUME_TIME64_SYSCALLS
> > > > unconditionally on x32 and then defining __NR_clock_settime64 to
> > > > __NR_clock_settime when __ASSUME_TIME64_SYSCALLS is defined while
> > > > __NR_clock_settime64 isn't.

I think now that with this scheme __ASSUME_TIME64_SYSCALLS should be
defined unconditionally for the __WORDSIZE==64 case too.  With this
there will be no need to use __TIMESIZE inside clock_settime64
function.  __TIMESIZE describes interfaces provided by glibc, and has
no relation with kernel interfaces used by glibc.

#ifdef __ASSUME_TIME64_SYSCALLS
  call __NR_clock_settime64 (possibly defined to __NR_clock_settime)
#else
  call __NR_clock_settime64 with fallback to __NR_clock_settime on ENOSYS
#endif

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-06 19:36                     ` Stepan Golosunov
@ 2019-05-06 21:14                       ` Lukasz Majewski
  2019-05-07 20:03                         ` Stepan Golosunov
  2019-05-07 15:43                       ` Joseph Myers
  1 sibling, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-06 21:14 UTC (permalink / raw)
  To: Stepan Golosunov; +Cc: Joseph Myers, libc-alpha, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 3740 bytes --]

Hi Stepan,

> 06.05.2019 в 16:26:59 +0200 Lukasz Majewski написал:
> 
> > > > > > > I believe that the only 32-bit architecture without
> > > > > > > __NR_clock_settime64 is x32.         
> > > > > > 
> > > > > > Ok, I see. 
> > > > > > 
> > > > > > Please correct me - would it be feasible to just #undef
> > > > > > __ASSYME_TIME64_SYSCALLS for x32 ?        
> > > > > 
> > > > > You'll need to know whether to use __NR_clock_settime64 or
> > > > > __NR_clock_settime in cases where __TIMESIZE == 64 and
> > > > > __WORDSIZE == 32.    
> > > 
> > > Please correct me, but I do have some doubts here.
> > > 
> > > As x32 now uses 64 bit time (and has TIMESIZE==64) - it uses the
> > > clock_settime call (with in-kernel broken tv_nsec padding
> > > clearing - but for this the fix is in its way to upstream).
> > > 
> > > Why does it need to also support clock_settime64 ?   
> > 
> > I was too eager to send the mail.
> > 
> > It is connected with your proposition to use __WORDSIZE for #ifdef
> > on __ASSUME_TIME64_SYSCALLS. 
> > 
> > As x32 has __WORDSIZE=32 (but __TIMESIZE=64), it would fall into
> > "category" of archs using explicit 64 bit calls (i.e.
> > clock_settime64).
> > 
> > However, for it - those shall be replaced with syscalls used up
> > till now (i.e. clock_settime).
> > 
> > Am I right here ?  
> 
> x32 has __WORDSIZE==32 and __TIMESIZE==64.  Future 32-bit
> architectures should have __WORDSIZE==32 and __TIMESIZE==64 too.  And
> the only difference in implementation of clock_settime64 function
> there should be name of syscall (ignoring possible padding clearing
> issues).

For ARM, x86 there shall be call to clock_settime64 syscall

For x32 there shall be call to clock_settime syscall (which is
supporting 64 bit anyway - despite the ignoring possible padding
clearing issue).

> 
> > > > > One way would be by defining __ASSUME_TIME64_SYSCALLS
> > > > > unconditionally on x32 and then defining __NR_clock_settime64
> > > > > to __NR_clock_settime when __ASSUME_TIME64_SYSCALLS is
> > > > > defined while __NR_clock_settime64 isn't.  
> 
> I think now that with this scheme __ASSUME_TIME64_SYSCALLS should be
> defined unconditionally for the __WORDSIZE==64 case too.  With this
> there will be no need to use __TIMESIZE inside clock_settime64
> function.  __TIMESIZE describes interfaces provided by glibc, and has
> no relation with kernel interfaces used by glibc.
> 
> #ifdef __ASSUME_TIME64_SYSCALLS
>   call __NR_clock_settime64 (possibly defined to __NR_clock_settime)
> #else
>   call __NR_clock_settime64 with fallback to __NR_clock_settime on
> ENOSYS #endif

I rather thought about something like:

__clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
{
  <overflow check>

#ifdef __ASSUME_TIME64_SYSCALLS
# ifdef __NR_clock_settime64
  int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
  if (ret == 0 || errno != ENOSYS)
	return ret;
# endif
  /* Fall back to syscall supporting 32bit struct timespec.  */
  struct timespec ts32;
  valid_timespec64_to_timespec (tp, &ts32);
  return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);
#else
  /* 64 bit machines + x32 */
  return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp);
#endif
}

In the above pseudo code we assume that __ASSUME_TIME64_SYSCALLS is
#undef'ed for x32 (so it is treated as a 'special case' - in the same
way as x86_64).



Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time
  2019-04-14 22:08 [PATCH 0/6] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
                   ` (6 preceding siblings ...)
  2019-04-29 10:46 ` [PATCH v2 0/7] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
@ 2019-05-07 13:18 ` Lukasz Majewski
  2019-05-07 13:18   ` [PATCH v3 1/5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define Lukasz Majewski
                     ` (10 more replies)
  2019-05-08 15:56 ` [PATCH] y2038: Introduce __ASSUME_TIME64_SYSCALLS define Lukasz Majewski
                   ` (2 subsequent siblings)
  10 siblings, 11 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-07 13:18 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This patch set introduces the conversion of __clock_settime to explicit
64 bit struct __timespec64 arguments. As a result this function is now
Y2038 safe.

To achieve the above goal - new, internal to glibc,
struct __timespec64 has been also introduced as well as
helper functions to handle time conversions on 32 bit systems.

The code from this patch set uses new clock_settime64 syscall (explicit
64 bits) from Linux kernel (5.1+).

In glibc new __ASSUME_TIME64_SYSCALLS define has been introduced to
indicate if above syscall is provided by the kernel.

This work is (loosely) based on a previous development/patches:
https://libc-alpha.sourceware.narkive.com/zniMOWui/rfc-patch-00-52-make-glibc-y2038-proof#post68

Github branch (including the y2038 conversion example):
https://github.com/lmajewski/y2038_glibc/commits/Y2038-2.29-glibc-__clock-internal-struct-timespec-v3

Those patches have been applied on top of master branch:
SHA1: 32e902a94e24fc5a00168d0df3301098704c61fb

Shall be used with provided meta-y2038 for development and testing:
https://github.com/lmajewski/meta-y2038

I've used guidelines from:
https://www.gnu.org/software/libc/manual/html_mono/libc.html
"D.2.1 64-bit time symbol handling in the GNU C Library"
to convert *clock_settime*.

and most notably from:
https://sourceware.org/glibc/wiki/Y2038ProofnessDesign#clock_gettime.28.29

Feedback and comments are more than welcome.


Lukasz Majewski (5):
  y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  y2038: Introduce internal for glibc struct __timespec64
  y2038: Provide conversion helpers for struct __timespec64
  y2038: linux: Provide __clock_settime64 implementation
  y2038: Support for Y2038 safe time on 32 bit systems

 include/features.h                               |  19 ++++
 include/time.h                                   | 121 +++++++++++++++++++++++
 manual/creature.texi                             |  28 ++++++
 sysdeps/unix/sysv/linux/clock_settime.c          |  53 +++++++++-
 sysdeps/unix/sysv/linux/kernel-features.h        |  38 +++++++
 sysdeps/unix/sysv/linux/x86_64/kernel-features.h |   9 ++
 time/Versions                                    |   3 +
 time/bits/types/struct_timespec.h                |  15 ++-
 time/bits/types/time_t.h                         |   4 +
 time/time.h                                      |   9 ++
 10 files changed, 294 insertions(+), 5 deletions(-)

-- 
2.11.0


^ permalink raw reply	[flat|nested] 111+ messages in thread

* [PATCH v3 1/5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-07 13:18 ` [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time Lukasz Majewski
@ 2019-05-07 13:18   ` Lukasz Majewski
  2019-05-07 16:04     ` Joseph Myers
  2019-05-07 13:18   ` [PATCH v3 2/5] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
                     ` (9 subsequent siblings)
  10 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-07 13:18 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This define indicates if the Linux kernel (5.1+) provides 64 bit versions
of time related syscalls (e.g. clock_settime64).

Those syscalls are now (starting from Linux 5.1) available on actively
supported Linux architectures: arm, arm64 (compat mode), m68k, microblaze,
mips, parisc, powerpc, s390, sh, sparc, x86, xtensa.

For x32 this flag is explicitly undefined as this architecture uses time
related syscalls from x86_64 (as if it were __WORDSIZE==64 && __TIMESIZE==64).


* sysdeps/unix/sysv/linux/kernel-features.h: (__ASSUME_TIME64_SYSCALLS):
[__LINUX_KERNEL_VERSION >= 0x050100]: Define.
* sysdeps/unix/sysv/linux/x86_64/kernel-features.h (__ASSUME_TIME64_SYSCALLS):
#undef the __ASSUME_TIME64_SYSCALLS for x32 architecture

---
Changes for v3:
- Provide more detailed and verbose description
- Change name to __ASSUME_TIME64_SYSCALLS
- Undefine __ASSUME_TIME64_SYSCALLS on x32

Changes for v2:
- New patch
---
 sysdeps/unix/sysv/linux/kernel-features.h        | 38 ++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/x86_64/kernel-features.h |  9 ++++++
 2 files changed, 47 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
index bc5c959f58..d2ed6f5679 100644
--- a/sysdeps/unix/sysv/linux/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/kernel-features.h
@@ -143,3 +143,41 @@
    */
 
 #define __ASSUME_CLONE_DEFAULT 1
+
+#include <bits/wordsize.h>
+#if __WORDSIZE != 64
+/* Support for 64 bit version of time related Linux syscalls.
+
+   1. Architectures with __WORDSIZE==64 && __TIMESIZE==64 (e.g. x86_64,
+      aarch64) - this flag is never defined (as those already use 64 bit
+      syscalls to handle time).
+
+   2. Architectures with __WORDSIZE==32 && __TIMESIZE==32 (e.g. arm, x86)
+   2a. With Y2038 support - userspace must be compiled with
+       -D_TIME_BITS == 64 and as a result __USE_TIME_BITS64 defined
+       (time_t is an alias to time64_t in glibc's exported headers)
+
+       Those systems would use 64 bit Linux system calls to provide 64 bit
+       time support.
+
+   2b. Without Y2038 support (-D_TIME_BITS not defined or not equal to 64)
+       Such systems would use internally (in glibc) calls to 64 bit syscalls
+       with returning overflow errors after Y2038.
+
+   3. Architectures with __WORDSIZE==32 && __TIMESIZE==64
+   3a. __TIMESIZE==64 due to architecture design (for now it is only 'x32')
+       This is a special case as 'x32' architecture has 64 bit size of
+       registers but longs and pointers are 32 bit.
+       It shall use the same time related syscalls as x86_64, so the flag
+       shall be explicitly undefined.
+   3b. __TIMESIZE==64 imposed by software development (in both cases discussed
+         below the __USE_TIME_BITS64 is defined by default):
+       - For new 32 bit architectures glibc support with 64 bit time support
+         from the outset (which beforehand requires proper syscalls from
+         kernel)
+       - After the 64 bit time support conversion is finished (i.e. arm with
+         Y2038 support).  */
+# if __LINUX_KERNEL_VERSION >= 0x050100
+#  define __ASSUME_TIME64_SYSCALLS 1
+# endif
+#endif
diff --git a/sysdeps/unix/sysv/linux/x86_64/kernel-features.h b/sysdeps/unix/sysv/linux/x86_64/kernel-features.h
index 26280f57ec..e1e923f497 100644
--- a/sysdeps/unix/sysv/linux/x86_64/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/x86_64/kernel-features.h
@@ -24,3 +24,12 @@
 #endif
 
 #include_next <kernel-features.h>
+
+/* For x32, which is a special case in respect to 64 bit time support,
+   the __ASSUME_TIME64_SYSCALLS define needs to be explicitly undefined.
+
+   It uses Linux time related syscalls for x86_64 (in compatibility
+   mode).  */
+#ifdef __ILP32__
+# undef __ASSUME_TIME64_SYSCALLS
+#endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH v3 2/5] y2038: Introduce internal for glibc struct __timespec64
  2019-05-07 13:18 ` [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time Lukasz Majewski
  2019-05-07 13:18   ` [PATCH v3 1/5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define Lukasz Majewski
@ 2019-05-07 13:18   ` Lukasz Majewski
  2019-05-07 13:30     ` Andreas Schwab
  2019-05-07 13:18   ` [PATCH v3 3/5] y2038: Provide conversion helpers for " Lukasz Majewski
                     ` (8 subsequent siblings)
  10 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-07 13:18 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This type is a glibc's type similar to struct timespec
but whose tv_sec field is a __time64_t rather than a time_t,
which makes it Y2038-proof and usable to pass between user
code and Y2038-proof kernel syscalls (e.g. clock_gettime()).

To support passing this structure to the kernel - the tv_pad,
32 bit padding field has been introduced. The placement of it
depends on endiannes of the SoC.

Tested on x86_64 and ARM.

* include/time.h: Add struct __timespec64 definition

---
Changes for v3:
- Replace __TIMESIZE with __WORDSIZE (as architectures with __TIMESIZE==64
  will need to use this struct with 32 bit tv_nsec field).
- Update in-code comment

Changes for v2:
- None
---
 include/time.h | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/include/time.h b/include/time.h
index ac3163c2a5..814e927645 100644
--- a/include/time.h
+++ b/include/time.h
@@ -5,6 +5,7 @@
 # include <bits/types/locale_t.h>
 # include <stdbool.h>
 # include <time/mktime-internal.h>
+# include <endian.h>
 
 extern __typeof (strftime_l) __strftime_l;
 libc_hidden_proto (__strftime_l)
@@ -51,6 +52,30 @@ extern void __tzset_parse_tz (const char *tz) attribute_hidden;
 extern void __tz_compute (__time64_t timer, struct tm *tm, int use_localtime)
   __THROW attribute_hidden;
 
+#if __WORDSIZE == 64
+# define __timespec64 timespec
+#else
+/* The glibc Y2038-proof struct __timespec64 structure for a time value.
+   To keep things Posix-ish, we keep the nanoseconds field a 32-bit
+   signed long, but since the Linux field is a 64-bit signed int, we
+   pad our tv_nsec with a 32-bit bitfield.
+
+   As a general rule the Linux kernel is ignoring upper 32 bits of
+   tv_nsec field. However, there are architectures with potential need
+   for clearing the padding (i.e. 'x32').  */
+struct __timespec64
+{
+  __time64_t tv_sec;         /* Seconds */
+# if BYTE_ORDER == BIG_ENDIAN
+  int tv_pad: 32;            /* Padding named for checking/setting */
+  __int32_t tv_nsec;         /* Nanoseconds */
+# else
+  __int32_t tv_nsec;         /* Nanoseconds */
+  int tv_pad: 32;            /* Padding named for checking/setting */
+# endif
+};
+#endif
+
 #if __TIMESIZE == 64
 # define __ctime64 ctime
 #else
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH v3 3/5] y2038: Provide conversion helpers for struct __timespec64
  2019-05-07 13:18 ` [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time Lukasz Majewski
  2019-05-07 13:18   ` [PATCH v3 1/5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define Lukasz Majewski
  2019-05-07 13:18   ` [PATCH v3 2/5] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
@ 2019-05-07 13:18   ` Lukasz Majewski
  2019-05-07 13:18   ` [PATCH v3 4/5] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
                     ` (7 subsequent siblings)
  10 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-07 13:18 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

Those functions allow easy conversion between Y2038 safe struct
__timespec64 and other time related data structures (like struct timeval).

Moreover, those functions are NOT compiled when 64 bit time support is
enabled (__TIMESIZE == 64) and are used only for 32 bit wrappers (like
e.g. __clock_settime).

* include/time.h (valid_timeval_to_timespec64): Add.
* include/time.h (valid_timespec_to_timespec64): Likewise.
* include/time.h (valid_timespec64_to_timespec): Likewise.
* include/time.h (valid_timespec64_to_timeval): Likewise.
* include/time.h (IS_VALID_NANOSECONDS): Likewise.
* include/time.h (timespec_to_timespec64): Likewise.
* include/time.h (timespec64_to_timespec): Likewise.
* include/time.h (timespec64_to_timeval): Likewise.

---
Changes for v3:
- Remove timespec64_clear_padding function - as kernel ignores upper 32
bits of tv_nsec when passed via syscall to the Linux kernel

Changes for v2:
- Add timespec64_clear_padding function
---
 include/time.h | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/include/time.h b/include/time.h
index 814e927645..18587fdd8b 100644
--- a/include/time.h
+++ b/include/time.h
@@ -181,5 +181,92 @@ in_time_t_range (__time64_t t)
   return s == t;
 }
 
+# if __TIMESIZE != 64
+/* Convert a known valid struct timeval into a struct __timespec64.  */
+static inline void
+valid_timeval_to_timespec64 (const struct timeval *tv32,
+			     struct __timespec64 *ts64)
+{
+  ts64->tv_sec = tv32->tv_sec;
+  ts64->tv_nsec = tv32->tv_usec * 1000;
+}
+
+/* Convert a known valid struct timespec into a struct __timespec64.  */
+static inline void
+valid_timespec_to_timespec64 (const struct timespec *ts32,
+			      struct __timespec64 *ts64)
+{
+  ts64->tv_sec = ts32->tv_sec;
+  ts64->tv_nsec = ts32->tv_nsec;
+  /* We only need to zero ts64->tv_pad if we pass it to the kernel.  */
+}
+
+/* Convert a known valid struct __timespec64 into a struct timespec.  */
+static inline void
+valid_timespec64_to_timespec (const struct __timespec64 *ts64,
+			      struct timespec *ts32)
+{
+  ts32->tv_sec = (time_t) ts64->tv_sec;
+  ts32->tv_nsec = ts64->tv_nsec;
+}
+
+/* Convert a known valid struct __timespec64 into a struct timeval.  */
+static inline void
+valid_timespec64_to_timeval (const struct __timespec64 *ts64,
+			     struct timeval *tv32)
+{
+  tv32->tv_sec = (time_t) ts64->tv_sec;
+  tv32->tv_usec = ts64->tv_nsec / 1000;
+}
+
+/* Check if a value lies with the valid nanoseconds range.  */
+#define IS_VALID_NANOSECONDS(ns) ((ns) >= 0 && (ns) <= 999999999)
+
+/* Check and convert a struct timespec into a struct __timespec64.  */
+static inline bool
+timespec_to_timespec64 (const struct timespec *ts32,
+                        struct __timespec64 *ts64)
+{
+  /* Check that ts32 holds a valid count of nanoseconds.  */
+  if (! IS_VALID_NANOSECONDS (ts32->tv_nsec))
+    return false;
+  /* All ts32 fields can fit in ts64, so copy them.  */
+  valid_timespec_to_timespec64 (ts32, ts64);
+  /* We only need to zero ts64->tv_pad if we pass it to the kernel.  */
+  return true;
+}
+
+/* Check and convert a struct __timespec64 into a struct timespec.  */
+static inline bool
+timespec64_to_timespec (const struct __timespec64 *ts64,
+                        struct timespec *ts32)
+{
+  /* Check that tv_nsec holds a valid count of nanoseconds.  */
+  if (! IS_VALID_NANOSECONDS (ts64->tv_nsec))
+    return false;
+  /* Check that tv_sec can fit in a __time_t.  */
+  if (! in_time_t_range (ts64->tv_sec))
+    return false;
+  /* All ts64 fields can fit in ts32, so copy them.  */
+  valid_timespec64_to_timespec (ts64, ts32);
+  return true;
+}
+
+/* Check and convert a struct __timespec64 into a struct timeval.  */
+static inline bool
+timespec64_to_timeval (const struct __timespec64 *ts64,
+                       struct timeval *tv32)
+{
+  /* Check that tv_nsec holds a valid count of nanoseconds.  */
+  if (! IS_VALID_NANOSECONDS (ts64->tv_nsec))
+    return false;
+  /* Check that tv_sec can fit in a __time_t.  */
+  if (! in_time_t_range (ts64->tv_sec))
+    return false;
+  /* All ts64 fields can fit in tv32, so copy them.  */
+  valid_timespec64_to_timeval (ts64, tv32);
+  return true;
+}
+# endif
 #endif
 #endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH v3 4/5] y2038: linux: Provide __clock_settime64 implementation
  2019-05-07 13:18 ` [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time Lukasz Majewski
                     ` (2 preceding siblings ...)
  2019-05-07 13:18   ` [PATCH v3 3/5] y2038: Provide conversion helpers for " Lukasz Majewski
@ 2019-05-07 13:18   ` Lukasz Majewski
  2019-05-07 16:40     ` Joseph Myers
  2019-05-07 13:18   ` [PATCH v3 5/5] y2038: Support for Y2038 safe time on 32 bit systems Lukasz Majewski
                     ` (6 subsequent siblings)
  10 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-07 13:18 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This patch provides new __clock_settime64 explicit 64 bit function for
setting the time. Moreover, a 32 bit version - __clock_settime has been
refactored to internally use __clock_settime64.

The __clock_settime is now supposed to be used on systems still supporting
32 bit time - hence the necessary checks and conversion to 64 bit type.
After this change it is intrinsically Y2038 safe.

The new 64 bit syscall (clock_settime64) available from Linux
5.1+ has been used when applicable on 32 bit systems.

The __ASSUME_TIME64_SYSCALLS flag indicates if the Linux kernel provides
64 bit version of clock_settime (i.e. clock_settime64). If this syscall is
not provided by the kernel - the 32 bit version of it is executed instead.

When working on 32 bit systems without Y2038 time support the clock_settime
returns error when one wants to set time with wrong (overflowed) tv_sec
value. Moreover, the correctness of tv_nsec is checked.

In this patch the internal padding (tv_pad) of struct __timespec64 is
left untouched (on 32 bit systems) as Linux kernel ignores upper 32 bits
of tv_nsec.

The execution path on 64 bit systems has not been changed or affected in
any way.

Tests:
- The code has been tested with x86_64/x86 (native compilation):
make PARALLELMFLAGS="-j8" && make xcheck PARALLELMFLAGS="-j8"

- Run specific tests on ARM/x86 32bit systems (qemu):
https://github.com/lmajewski/meta-y2038
and run tests:
https://github.com/lmajewski/y2038-tests/commits/master
on kernels with and without 64 bit time support.

No regressions were observed.

* include/time.h (__clock_settime64):
  Add __clock_settime alias according to __TIMESIZE define
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime):
  Refactor this function to be used only on 32 bit machines as a wrapper
  on __clock_settime64.
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime64): Add
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime64):
  Use clock_settime64 kernel syscall (available from 5.1-rc1+ Linux) by
  32 bit Y2038 safe systems

---
Changes for v3:
- Rename __ASSUME_64BIT_TIME to __ASSUME_TIME64_SYSCALLS
- Refactor in-code comment (add information regarding Linux kernel ignorance
  of padding
- Do not use __TIMESIZE to select main execution path (for Y2038 systems
  __TIMESIZE would be changed from 32 to 64 bits at some point to indicate
  full Y2038 support

Changes for v2:
- Add support for __ASSUME_64BIT_TIME flag when Linux kernel provides syscalls
  supporting 64 bit time on 32 bit systems
- Provide fallback to 32 bit version of clock_settime when clock_settime64
  is not available
- Do not copy *tp to timespec - this seems like an overkill as in clock_settime()
  the 32 bit struct timespec is copied to internal 64 bit struct __timespec64
---
 include/time.h                          |  8 +++++
 sysdeps/unix/sysv/linux/clock_settime.c | 53 +++++++++++++++++++++++++++++++--
 2 files changed, 58 insertions(+), 3 deletions(-)

diff --git a/include/time.h b/include/time.h
index 18587fdd8b..670226df0c 100644
--- a/include/time.h
+++ b/include/time.h
@@ -127,6 +127,14 @@ extern __time64_t __timegm64 (struct tm *__tp) __THROW;
 libc_hidden_proto (__timegm64)
 #endif
 
+#if __TIMESIZE == 64
+# define __clock_settime64 __clock_settime
+#else
+extern int __clock_settime64 (clockid_t clock_id,
+                              const struct __timespec64 *tp);
+libc_hidden_proto (__clock_settime64)
+#endif
+
 /* Compute the `struct tm' representation of T,
    offset OFFSET seconds east of UTC,
    and store year, yday, mon, mday, wday, hour, min, sec into *TP.
diff --git a/sysdeps/unix/sysv/linux/clock_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c
index d837e3019c..084edeaa61 100644
--- a/sysdeps/unix/sysv/linux/clock_settime.c
+++ b/sysdeps/unix/sysv/linux/clock_settime.c
@@ -19,11 +19,9 @@
 #include <sysdep.h>
 #include <time.h>
 
-#include "kernel-posix-cpu-timers.h"
-
 /* Set CLOCK to value TP.  */
 int
-__clock_settime (clockid_t clock_id, const struct timespec *tp)
+__clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
 {
   /* Make sure the time cvalue is OK.  */
   if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
@@ -32,6 +30,55 @@ __clock_settime (clockid_t clock_id, const struct timespec *tp)
       return -1;
     }
 
+#ifdef __ASSUME_TIME64_SYSCALLS
+# ifdef __NR_clock_settime64
+  /* For Y2038 safe systems with __WORDSIZE==32 and __TIMESIZE==64
+     (x86, arm) the glibc exported struct timespec has 64 bit tv_sec,
+     32 bit tv_nsec (to be still POSIX compliant -> long tv_nsec )
+     and 32 bits of unnamed padding.
+
+     It may happen that due to dynamic allocation the tv_pad, which
+     corresponds to upper 32 bits of kernel's 64 bit tv_nsec accepted
+     by syscalls, may not be zero.
+
+     However, the Linux kernel is ignoring those 32 bits (to be more
+     precise - as of 5.1 - it casts 64 bit tv_nsec to internal's 32 bit
+     representation) and hence the padding clearing is not needed.  */
+  int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
+  if (ret == 0 || errno != ENOSYS)
+    return ret;
+# endif
+#endif
+
+/* For systems supporting 32 bit time only __WORDSIZE==32 and
+   __TIMESIZE==32 (!=64) the passed struct __timespec64 must be
+   converted to 32 bit one before invoking Linux syscall.  */
+#if __WORDSIZE == 32 && __TIMESIZE != 64
+  /* Fall back to syscall supporting 32bit struct timespec.  */
+  struct timespec ts32;
+  valid_timespec64_to_timespec (tp, &ts32);
+  return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);
+#else
+/* Systems with __WORDSIZE==64 (i.e. x86_64, aarch64) or
+   __WORDSIZE==32 && __TIMESIZE == 64 (i.e. x32 - special case).  */
   return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp);
+#endif
 }
 weak_alias (__clock_settime, clock_settime)
+
+#if __TIMESIZE != 64
+int
+__clock_settime (clockid_t clock_id, const struct timespec *tp)
+{
+  struct __timespec64 ts64;
+
+  if (! in_time_t_range (tp->tv_sec))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  valid_timespec_to_timespec64 (tp, &ts64);
+  return __clock_settime64 (clock_id, &ts64);
+}
+#endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH v3 5/5] y2038: Support for Y2038 safe time on 32 bit systems
  2019-05-07 13:18 ` [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time Lukasz Majewski
                     ` (3 preceding siblings ...)
  2019-05-07 13:18   ` [PATCH v3 4/5] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
@ 2019-05-07 13:18   ` Lukasz Majewski
  2019-05-07 16:37     ` Joseph Myers
  2019-05-07 13:18   ` [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time Lukasz Majewski
                     ` (5 subsequent siblings)
  10 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-07 13:18 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

The time_t type is now Y2038 safe, which means that it is aliased to
__time64_t when __USE_TIME_BITS64 is defined or __time_t otherwise.

On the contrary the __time_t for 32 bit systems is only 32 bit, so for
Y2038 safe system it must be 64 bit (as is time_t)

This patch introduces the Y2038 specific code to make clock_settime/
__clock_settime64 Y2038 safe on 32 bit systems.
This goal is achieved by using aliasing to clock_settime names when
__USE_TIME_BITS64 is defined.
As a result user programs call 64 bit versions of functions (i.e.
__clock_settime64 instead of __clock_settime), which must have been
globally visible for this purpose - for non Y2038 safe code those are
hidden in glibc.


* include/features.h:
  Add logic to set __USE_TIME_BITS64 according to passed (when building
  userspace Y2038 safe program on 32 bit system) _TIME_BITS and
  _FILE_OFFSET_BITS
* manual/creature.texi: Add description of _TIME_BITS
* time/bits/types/time_t.h:
  Use __time64_t as time_t when __USE_TIME_BITS64 is defined
* time/bits/types/struct_timespec.h:
  Replace tv_sec's __time_t type to Y2038 safe time_t
* include/time.h:
  Remove libc_hidden_proto (__clock_settime64) - make the __clock_settime64
  publicly available for Y2038 safe system
* time/time.h: Redirect clock_settime call to __clock_settime64 on 32 bit
  Y2038 safe systems
* time/Versions (GLIBC_PRIVATE):
  Export __clock_settime64 function as glibc private one, to be accessible from
  user programs when y2038 support is enabled
* time/bits/types/struct_timespec.h:
  Add unnamed padding around tv_nsec when __USE_TIME_BITS64 is defined

---
Changes for v3:
- Only support clock_settime conversion to be Y2038 (use it as an example
  conversion code)

Changes for v2:
- Introduce unnamed padding in the struct timespec exported by glibc
  (to the /usr/include)
---
 include/features.h                | 19 +++++++++++++++++++
 include/time.h                    |  3 ++-
 manual/creature.texi              | 28 ++++++++++++++++++++++++++++
 time/Versions                     |  3 +++
 time/bits/types/struct_timespec.h | 15 +++++++++++++--
 time/bits/types/time_t.h          |  4 ++++
 time/time.h                       |  9 +++++++++
 7 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/include/features.h b/include/features.h
index e016b3e5c7..153c6320f0 100644
--- a/include/features.h
+++ b/include/features.h
@@ -365,6 +365,25 @@
 # define __USE_FILE_OFFSET64	1
 #endif
 
+/* We need to know the word size in order to check the time size.  */
+#include <bits/wordsize.h>
+
+#if defined _TIME_BITS
+# if _TIME_BITS == 64
+#  if ! defined (_FILE_OFFSET_BITS) || _FILE_OFFSET_BITS != 64
+#   error _TIME_BITS==64 is allowed only when _FILE_OFFSET_BITS==64
+#  elif __WORDSIZE == 32
+#   define __USE_TIME_BITS64	1
+#  endif
+# elif _TIME_BITS == 32
+#  if __WORDSIZE > 32
+#   error _TIME_BITS=32 is not compatible with __WORDSIZE > 32
+#  endif
+# else
+#  error Invalid _TIME_BITS value (can only be 32 or 64)
+# endif
+#endif
+
 #if defined _DEFAULT_SOURCE
 # define __USE_MISC	1
 #endif
diff --git a/include/time.h b/include/time.h
index 670226df0c..d4b11cb1a9 100644
--- a/include/time.h
+++ b/include/time.h
@@ -132,7 +132,8 @@ libc_hidden_proto (__timegm64)
 #else
 extern int __clock_settime64 (clockid_t clock_id,
                               const struct __timespec64 *tp);
-libc_hidden_proto (__clock_settime64)
+/* For Y2038 safe system the __clock_settime64 needs to be a visible
+   symbol as a replacement for Y2038 unsafe clock_settime.  */
 #endif
 
 /* Compute the `struct tm' representation of T,
diff --git a/manual/creature.texi b/manual/creature.texi
index 8876b2ab77..10b7111043 100644
--- a/manual/creature.texi
+++ b/manual/creature.texi
@@ -165,6 +165,34 @@ This macro was introduced as part of the Large File Support extension
 (LFS).
 @end defvr
 
+@defvr Macro _TIME_BITS
+This macro determines the bit size of @code{time_t} (and therefore the
+bit size of all @code{time_t} derived types and the prototypes of all
+related functions). If @code{_TIME_BITS} is undefined, the bit size of
+time_t equals the bit size of the architecture.
+
+If @code{_TIME_BITS} is undefined, or if @code{_TIME_BITS} is defined
+to the value @code{32} and @code{__WORDSIZE} is defined to the value
+@code{32}, or or if @code{_TIME_BITS} is defined to the value @code{64}
+and @code{__WORDSIZE} is defined to the value @code{64}, nothing changes.
+
+If @code{_TIME_BITS} is defined to the value @code{64} and if
+@code{__WORDSIZE} is defined to the value @code{32}, then the @w{64 bit}
+time API and implementation are used even though the architecture word
+size is @code{32}. Also, if the kernel provides @w{64 bit} time support,
+it is used; otherwise, the @w{32 bit} kernel time support is used (with
+no provision to address kernel Y2038 shortcomings).
+
+If @code{_TIME_BITS} is defined to the value @code{32} and if
+@code{__WORDSIZE} is defined to the value @code{64}, then a compile-time
+error is emitted.
+
+If @code{_TIME_BITS} is defined to a value different from both @code{32}
+and @code{64}, then a compile-time error is emitted.
+
+This macro was introduced as part of the Y2038 support.
+@end defvr
+
 @defvr Macro _ISOC99_SOURCE
 @standards{GNU, (none)}
 If this macro is defined, features from ISO C99 are included.  Since
diff --git a/time/Versions b/time/Versions
index fd838181e4..5109c45ce2 100644
--- a/time/Versions
+++ b/time/Versions
@@ -1,4 +1,7 @@
 libc {
+  GLIBC_PRIVATE {
+    __clock_settime64;
+  }
   GLIBC_2.0 {
     # global variables
     __daylight; __timezone; __tzname;
diff --git a/time/bits/types/struct_timespec.h b/time/bits/types/struct_timespec.h
index 5b77c52b4f..f34df0a18c 100644
--- a/time/bits/types/struct_timespec.h
+++ b/time/bits/types/struct_timespec.h
@@ -3,13 +3,24 @@
 #define _STRUCT_TIMESPEC 1
 
 #include <bits/types.h>
+#include <bits/types/time_t.h>
 
 /* POSIX.1b structure for a time value.  This is like a `struct timeval' but
    has nanoseconds instead of microseconds.  */
 struct timespec
 {
-  __time_t tv_sec;		/* Seconds.  */
-  __syscall_slong_t tv_nsec;	/* Nanoseconds.  */
+  time_t tv_sec;		/* Seconds.  */
+# ifdef __USE_TIME_BITS64
+#  if __BYTE_ORDER == __BIG_ENDIAN
+  int : 32;
+  __syscall_slong_t tv_nsec; /* Nanoseconds.  */
+#  else
+  __syscall_slong_t tv_nsec; /* Nanoseconds.  */
+  int : 32;
+#  endif
+# else
+  __syscall_slong_t tv_nsec; /* Nanoseconds.  */
+# endif
 };
 
 #endif
diff --git a/time/bits/types/time_t.h b/time/bits/types/time_t.h
index ab8287c6fe..84d67f6ac3 100644
--- a/time/bits/types/time_t.h
+++ b/time/bits/types/time_t.h
@@ -4,6 +4,10 @@
 #include <bits/types.h>
 
 /* Returned by `time'.  */
+#ifdef __USE_TIME_BITS64
+typedef __time64_t time_t;
+#else
 typedef __time_t time_t;
+#endif
 
 #endif
diff --git a/time/time.h b/time/time.h
index cba6d15260..0bfd1de925 100644
--- a/time/time.h
+++ b/time/time.h
@@ -222,6 +222,15 @@ extern int clock_gettime (clockid_t __clock_id, struct timespec *__tp) __THROW;
 extern int clock_settime (clockid_t __clock_id, const struct timespec *__tp)
      __THROW;
 
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (clock_settime, (clockid_t __clock_id, const struct
+                                       timespec *__tp), __clock_settime64) __THROW;
+# else
+# define clock_settime __clock_settime64
+# endif
+#endif
+
 # ifdef __USE_XOPEN2K
 /* High-resolution sleep with the specified clock.
 
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time
  2019-05-07 13:18 ` [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time Lukasz Majewski
                     ` (4 preceding siblings ...)
  2019-05-07 13:18   ` [PATCH v3 5/5] y2038: Support for Y2038 safe time on 32 bit systems Lukasz Majewski
@ 2019-05-07 13:18   ` Lukasz Majewski
  2019-05-07 13:18   ` [PATCH v3 1/5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define Lukasz Majewski
                     ` (4 subsequent siblings)
  10 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-07 13:18 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This patch set introduces the conversion of __clock_settime to explicit
64 bit struct __timespec64 arguments. As a result this function is now
Y2038 safe.

To achieve the above goal - new, internal to glibc,
struct __timespec64 has been also introduced as well as
helper functions to handle time conversions on 32 bit systems.

The code from this patch set uses new clock_settime64 syscall (explicit
64 bits) from Linux kernel (5.1+).

In glibc new __ASSUME_TIME64_SYSCALLS define has been introduced to
indicate if above syscall is provided by the kernel.

This work is (loosely) based on a previous development/patches:
https://libc-alpha.sourceware.narkive.com/zniMOWui/rfc-patch-00-52-make-glibc-y2038-proof#post68

Github branch (including the y2038 conversion example):
https://github.com/lmajewski/y2038_glibc/commits/Y2038-2.29-glibc-__clock-internal-struct-timespec-v3

Those patches have been applied on top of master branch:
SHA1: 32e902a94e24fc5a00168d0df3301098704c61fb

Shall be used with provided meta-y2038 for development and testing:
https://github.com/lmajewski/meta-y2038

I've used guidelines from:
https://www.gnu.org/software/libc/manual/html_mono/libc.html
"D.2.1 64-bit time symbol handling in the GNU C Library"
to convert *clock_settime*.

and most notably from:
https://sourceware.org/glibc/wiki/Y2038ProofnessDesign#clock_gettime.28.29

Feedback and comments are more than welcome.


Lukasz Majewski (5):
  y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  y2038: Introduce internal for glibc struct __timespec64
  y2038: Provide conversion helpers for struct __timespec64
  y2038: linux: Provide __clock_settime64 implementation
  y2038: Support for Y2038 safe time on 32 bit systems

 include/features.h                               |  19 ++++
 include/time.h                                   | 121 +++++++++++++++++++++++
 manual/creature.texi                             |  28 ++++++
 sysdeps/unix/sysv/linux/clock_settime.c          |  53 +++++++++-
 sysdeps/unix/sysv/linux/kernel-features.h        |  38 +++++++
 sysdeps/unix/sysv/linux/x86_64/kernel-features.h |   9 ++
 time/Versions                                    |   3 +
 time/bits/types/struct_timespec.h                |  15 ++-
 time/bits/types/time_t.h                         |   4 +
 time/time.h                                      |   9 ++
 10 files changed, 294 insertions(+), 5 deletions(-)

-- 
2.11.0


^ permalink raw reply	[flat|nested] 111+ messages in thread

* [PATCH v3 1/5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-07 13:18 ` [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time Lukasz Majewski
                     ` (5 preceding siblings ...)
  2019-05-07 13:18   ` [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time Lukasz Majewski
@ 2019-05-07 13:18   ` Lukasz Majewski
  2019-05-07 13:18   ` [PATCH v3 2/5] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
                     ` (3 subsequent siblings)
  10 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-07 13:18 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This define indicates if the Linux kernel (5.1+) provides 64 bit versions
of time related syscalls (e.g. clock_settime64).

Those syscalls are now (starting from Linux 5.1) available on actively
supported Linux architectures: arm, arm64 (compat mode), m68k, microblaze,
mips, parisc, powerpc, s390, sh, sparc, x86, xtensa.

For x32 this flag is explicitly undefined as this architecture uses time
related syscalls from x86_64 (as if it were __WORDSIZE==64 && __TIMESIZE==64).


* sysdeps/unix/sysv/linux/kernel-features.h: (__ASSUME_TIME64_SYSCALLS):
[__LINUX_KERNEL_VERSION >= 0x050100]: Define.
* sysdeps/unix/sysv/linux/x86_64/kernel-features.h (__ASSUME_TIME64_SYSCALLS):
#undef the __ASSUME_TIME64_SYSCALLS for x32 architecture

---
Changes for v3:
- Provide more detailed and verbose description
- Change name to __ASSUME_TIME64_SYSCALLS
- Undefine __ASSUME_TIME64_SYSCALLS on x32

Changes for v2:
- New patch
---
 sysdeps/unix/sysv/linux/kernel-features.h        | 38 ++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/x86_64/kernel-features.h |  9 ++++++
 2 files changed, 47 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
index bc5c959f58..d2ed6f5679 100644
--- a/sysdeps/unix/sysv/linux/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/kernel-features.h
@@ -143,3 +143,41 @@
    */
 
 #define __ASSUME_CLONE_DEFAULT 1
+
+#include <bits/wordsize.h>
+#if __WORDSIZE != 64
+/* Support for 64 bit version of time related Linux syscalls.
+
+   1. Architectures with __WORDSIZE==64 && __TIMESIZE==64 (e.g. x86_64,
+      aarch64) - this flag is never defined (as those already use 64 bit
+      syscalls to handle time).
+
+   2. Architectures with __WORDSIZE==32 && __TIMESIZE==32 (e.g. arm, x86)
+   2a. With Y2038 support - userspace must be compiled with
+       -D_TIME_BITS == 64 and as a result __USE_TIME_BITS64 defined
+       (time_t is an alias to time64_t in glibc's exported headers)
+
+       Those systems would use 64 bit Linux system calls to provide 64 bit
+       time support.
+
+   2b. Without Y2038 support (-D_TIME_BITS not defined or not equal to 64)
+       Such systems would use internally (in glibc) calls to 64 bit syscalls
+       with returning overflow errors after Y2038.
+
+   3. Architectures with __WORDSIZE==32 && __TIMESIZE==64
+   3a. __TIMESIZE==64 due to architecture design (for now it is only 'x32')
+       This is a special case as 'x32' architecture has 64 bit size of
+       registers but longs and pointers are 32 bit.
+       It shall use the same time related syscalls as x86_64, so the flag
+       shall be explicitly undefined.
+   3b. __TIMESIZE==64 imposed by software development (in both cases discussed
+         below the __USE_TIME_BITS64 is defined by default):
+       - For new 32 bit architectures glibc support with 64 bit time support
+         from the outset (which beforehand requires proper syscalls from
+         kernel)
+       - After the 64 bit time support conversion is finished (i.e. arm with
+         Y2038 support).  */
+# if __LINUX_KERNEL_VERSION >= 0x050100
+#  define __ASSUME_TIME64_SYSCALLS 1
+# endif
+#endif
diff --git a/sysdeps/unix/sysv/linux/x86_64/kernel-features.h b/sysdeps/unix/sysv/linux/x86_64/kernel-features.h
index 26280f57ec..e1e923f497 100644
--- a/sysdeps/unix/sysv/linux/x86_64/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/x86_64/kernel-features.h
@@ -24,3 +24,12 @@
 #endif
 
 #include_next <kernel-features.h>
+
+/* For x32, which is a special case in respect to 64 bit time support,
+   the __ASSUME_TIME64_SYSCALLS define needs to be explicitly undefined.
+
+   It uses Linux time related syscalls for x86_64 (in compatibility
+   mode).  */
+#ifdef __ILP32__
+# undef __ASSUME_TIME64_SYSCALLS
+#endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH v3 2/5] y2038: Introduce internal for glibc struct __timespec64
  2019-05-07 13:18 ` [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time Lukasz Majewski
                     ` (6 preceding siblings ...)
  2019-05-07 13:18   ` [PATCH v3 1/5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define Lukasz Majewski
@ 2019-05-07 13:18   ` Lukasz Majewski
  2019-05-07 13:18   ` [PATCH v3 3/5] y2038: Provide conversion helpers for " Lukasz Majewski
                     ` (2 subsequent siblings)
  10 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-07 13:18 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This type is a glibc's type similar to struct timespec
but whose tv_sec field is a __time64_t rather than a time_t,
which makes it Y2038-proof and usable to pass between user
code and Y2038-proof kernel syscalls (e.g. clock_gettime()).

To support passing this structure to the kernel - the tv_pad,
32 bit padding field has been introduced. The placement of it
depends on endiannes of the SoC.

Tested on x86_64 and ARM.

* include/time.h: Add struct __timespec64 definition

---
Changes for v3:
- Replace __TIMESIZE with __WORDSIZE (as architectures with __TIMESIZE==64
  will need to use this struct with 32 bit tv_nsec field).
- Update in-code comment

Changes for v2:
- None
---
 include/time.h | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/include/time.h b/include/time.h
index ac3163c2a5..814e927645 100644
--- a/include/time.h
+++ b/include/time.h
@@ -5,6 +5,7 @@
 # include <bits/types/locale_t.h>
 # include <stdbool.h>
 # include <time/mktime-internal.h>
+# include <endian.h>
 
 extern __typeof (strftime_l) __strftime_l;
 libc_hidden_proto (__strftime_l)
@@ -51,6 +52,30 @@ extern void __tzset_parse_tz (const char *tz) attribute_hidden;
 extern void __tz_compute (__time64_t timer, struct tm *tm, int use_localtime)
   __THROW attribute_hidden;
 
+#if __WORDSIZE == 64
+# define __timespec64 timespec
+#else
+/* The glibc Y2038-proof struct __timespec64 structure for a time value.
+   To keep things Posix-ish, we keep the nanoseconds field a 32-bit
+   signed long, but since the Linux field is a 64-bit signed int, we
+   pad our tv_nsec with a 32-bit bitfield.
+
+   As a general rule the Linux kernel is ignoring upper 32 bits of
+   tv_nsec field. However, there are architectures with potential need
+   for clearing the padding (i.e. 'x32').  */
+struct __timespec64
+{
+  __time64_t tv_sec;         /* Seconds */
+# if BYTE_ORDER == BIG_ENDIAN
+  int tv_pad: 32;            /* Padding named for checking/setting */
+  __int32_t tv_nsec;         /* Nanoseconds */
+# else
+  __int32_t tv_nsec;         /* Nanoseconds */
+  int tv_pad: 32;            /* Padding named for checking/setting */
+# endif
+};
+#endif
+
 #if __TIMESIZE == 64
 # define __ctime64 ctime
 #else
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH v3 3/5] y2038: Provide conversion helpers for struct __timespec64
  2019-05-07 13:18 ` [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time Lukasz Majewski
                     ` (7 preceding siblings ...)
  2019-05-07 13:18   ` [PATCH v3 2/5] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
@ 2019-05-07 13:18   ` Lukasz Majewski
  2019-05-07 13:18   ` [PATCH v3 4/5] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
  2019-05-07 13:18   ` [PATCH v3 5/5] y2038: Support for Y2038 safe time on 32 bit systems Lukasz Majewski
  10 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-07 13:18 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

Those functions allow easy conversion between Y2038 safe struct
__timespec64 and other time related data structures (like struct timeval).

Moreover, those functions are NOT compiled when 64 bit time support is
enabled (__TIMESIZE == 64) and are used only for 32 bit wrappers (like
e.g. __clock_settime).

* include/time.h (valid_timeval_to_timespec64): Add.
* include/time.h (valid_timespec_to_timespec64): Likewise.
* include/time.h (valid_timespec64_to_timespec): Likewise.
* include/time.h (valid_timespec64_to_timeval): Likewise.
* include/time.h (IS_VALID_NANOSECONDS): Likewise.
* include/time.h (timespec_to_timespec64): Likewise.
* include/time.h (timespec64_to_timespec): Likewise.
* include/time.h (timespec64_to_timeval): Likewise.

---
Changes for v3:
- Remove timespec64_clear_padding function - as kernel ignores upper 32
bits of tv_nsec when passed via syscall to the Linux kernel

Changes for v2:
- Add timespec64_clear_padding function
---
 include/time.h | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/include/time.h b/include/time.h
index 814e927645..18587fdd8b 100644
--- a/include/time.h
+++ b/include/time.h
@@ -181,5 +181,92 @@ in_time_t_range (__time64_t t)
   return s == t;
 }
 
+# if __TIMESIZE != 64
+/* Convert a known valid struct timeval into a struct __timespec64.  */
+static inline void
+valid_timeval_to_timespec64 (const struct timeval *tv32,
+			     struct __timespec64 *ts64)
+{
+  ts64->tv_sec = tv32->tv_sec;
+  ts64->tv_nsec = tv32->tv_usec * 1000;
+}
+
+/* Convert a known valid struct timespec into a struct __timespec64.  */
+static inline void
+valid_timespec_to_timespec64 (const struct timespec *ts32,
+			      struct __timespec64 *ts64)
+{
+  ts64->tv_sec = ts32->tv_sec;
+  ts64->tv_nsec = ts32->tv_nsec;
+  /* We only need to zero ts64->tv_pad if we pass it to the kernel.  */
+}
+
+/* Convert a known valid struct __timespec64 into a struct timespec.  */
+static inline void
+valid_timespec64_to_timespec (const struct __timespec64 *ts64,
+			      struct timespec *ts32)
+{
+  ts32->tv_sec = (time_t) ts64->tv_sec;
+  ts32->tv_nsec = ts64->tv_nsec;
+}
+
+/* Convert a known valid struct __timespec64 into a struct timeval.  */
+static inline void
+valid_timespec64_to_timeval (const struct __timespec64 *ts64,
+			     struct timeval *tv32)
+{
+  tv32->tv_sec = (time_t) ts64->tv_sec;
+  tv32->tv_usec = ts64->tv_nsec / 1000;
+}
+
+/* Check if a value lies with the valid nanoseconds range.  */
+#define IS_VALID_NANOSECONDS(ns) ((ns) >= 0 && (ns) <= 999999999)
+
+/* Check and convert a struct timespec into a struct __timespec64.  */
+static inline bool
+timespec_to_timespec64 (const struct timespec *ts32,
+                        struct __timespec64 *ts64)
+{
+  /* Check that ts32 holds a valid count of nanoseconds.  */
+  if (! IS_VALID_NANOSECONDS (ts32->tv_nsec))
+    return false;
+  /* All ts32 fields can fit in ts64, so copy them.  */
+  valid_timespec_to_timespec64 (ts32, ts64);
+  /* We only need to zero ts64->tv_pad if we pass it to the kernel.  */
+  return true;
+}
+
+/* Check and convert a struct __timespec64 into a struct timespec.  */
+static inline bool
+timespec64_to_timespec (const struct __timespec64 *ts64,
+                        struct timespec *ts32)
+{
+  /* Check that tv_nsec holds a valid count of nanoseconds.  */
+  if (! IS_VALID_NANOSECONDS (ts64->tv_nsec))
+    return false;
+  /* Check that tv_sec can fit in a __time_t.  */
+  if (! in_time_t_range (ts64->tv_sec))
+    return false;
+  /* All ts64 fields can fit in ts32, so copy them.  */
+  valid_timespec64_to_timespec (ts64, ts32);
+  return true;
+}
+
+/* Check and convert a struct __timespec64 into a struct timeval.  */
+static inline bool
+timespec64_to_timeval (const struct __timespec64 *ts64,
+                       struct timeval *tv32)
+{
+  /* Check that tv_nsec holds a valid count of nanoseconds.  */
+  if (! IS_VALID_NANOSECONDS (ts64->tv_nsec))
+    return false;
+  /* Check that tv_sec can fit in a __time_t.  */
+  if (! in_time_t_range (ts64->tv_sec))
+    return false;
+  /* All ts64 fields can fit in tv32, so copy them.  */
+  valid_timespec64_to_timeval (ts64, tv32);
+  return true;
+}
+# endif
 #endif
 #endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH v3 4/5] y2038: linux: Provide __clock_settime64 implementation
  2019-05-07 13:18 ` [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time Lukasz Majewski
                     ` (8 preceding siblings ...)
  2019-05-07 13:18   ` [PATCH v3 3/5] y2038: Provide conversion helpers for " Lukasz Majewski
@ 2019-05-07 13:18   ` Lukasz Majewski
  2019-05-07 13:18   ` [PATCH v3 5/5] y2038: Support for Y2038 safe time on 32 bit systems Lukasz Majewski
  10 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-07 13:18 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This patch provides new __clock_settime64 explicit 64 bit function for
setting the time. Moreover, a 32 bit version - __clock_settime has been
refactored to internally use __clock_settime64.

The __clock_settime is now supposed to be used on systems still supporting
32 bit time - hence the necessary checks and conversion to 64 bit type.
After this change it is intrinsically Y2038 safe.

The new 64 bit syscall (clock_settime64) available from Linux
5.1+ has been used when applicable on 32 bit systems.

The __ASSUME_TIME64_SYSCALLS flag indicates if the Linux kernel provides
64 bit version of clock_settime (i.e. clock_settime64). If this syscall is
not provided by the kernel - the 32 bit version of it is executed instead.

When working on 32 bit systems without Y2038 time support the clock_settime
returns error when one wants to set time with wrong (overflowed) tv_sec
value. Moreover, the correctness of tv_nsec is checked.

In this patch the internal padding (tv_pad) of struct __timespec64 is
left untouched (on 32 bit systems) as Linux kernel ignores upper 32 bits
of tv_nsec.

The execution path on 64 bit systems has not been changed or affected in
any way.

Tests:
- The code has been tested with x86_64/x86 (native compilation):
make PARALLELMFLAGS="-j8" && make xcheck PARALLELMFLAGS="-j8"

- Run specific tests on ARM/x86 32bit systems (qemu):
https://github.com/lmajewski/meta-y2038
and run tests:
https://github.com/lmajewski/y2038-tests/commits/master
on kernels with and without 64 bit time support.

No regressions were observed.

* include/time.h (__clock_settime64):
  Add __clock_settime alias according to __TIMESIZE define
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime):
  Refactor this function to be used only on 32 bit machines as a wrapper
  on __clock_settime64.
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime64): Add
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime64):
  Use clock_settime64 kernel syscall (available from 5.1-rc1+ Linux) by
  32 bit Y2038 safe systems

---
Changes for v3:
- Rename __ASSUME_64BIT_TIME to __ASSUME_TIME64_SYSCALLS
- Refactor in-code comment (add information regarding Linux kernel ignorance
  of padding
- Do not use __TIMESIZE to select main execution path (for Y2038 systems
  __TIMESIZE would be changed from 32 to 64 bits at some point to indicate
  full Y2038 support

Changes for v2:
- Add support for __ASSUME_64BIT_TIME flag when Linux kernel provides syscalls
  supporting 64 bit time on 32 bit systems
- Provide fallback to 32 bit version of clock_settime when clock_settime64
  is not available
- Do not copy *tp to timespec - this seems like an overkill as in clock_settime()
  the 32 bit struct timespec is copied to internal 64 bit struct __timespec64
---
 include/time.h                          |  8 +++++
 sysdeps/unix/sysv/linux/clock_settime.c | 53 +++++++++++++++++++++++++++++++--
 2 files changed, 58 insertions(+), 3 deletions(-)

diff --git a/include/time.h b/include/time.h
index 18587fdd8b..670226df0c 100644
--- a/include/time.h
+++ b/include/time.h
@@ -127,6 +127,14 @@ extern __time64_t __timegm64 (struct tm *__tp) __THROW;
 libc_hidden_proto (__timegm64)
 #endif
 
+#if __TIMESIZE == 64
+# define __clock_settime64 __clock_settime
+#else
+extern int __clock_settime64 (clockid_t clock_id,
+                              const struct __timespec64 *tp);
+libc_hidden_proto (__clock_settime64)
+#endif
+
 /* Compute the `struct tm' representation of T,
    offset OFFSET seconds east of UTC,
    and store year, yday, mon, mday, wday, hour, min, sec into *TP.
diff --git a/sysdeps/unix/sysv/linux/clock_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c
index d837e3019c..084edeaa61 100644
--- a/sysdeps/unix/sysv/linux/clock_settime.c
+++ b/sysdeps/unix/sysv/linux/clock_settime.c
@@ -19,11 +19,9 @@
 #include <sysdep.h>
 #include <time.h>
 
-#include "kernel-posix-cpu-timers.h"
-
 /* Set CLOCK to value TP.  */
 int
-__clock_settime (clockid_t clock_id, const struct timespec *tp)
+__clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
 {
   /* Make sure the time cvalue is OK.  */
   if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
@@ -32,6 +30,55 @@ __clock_settime (clockid_t clock_id, const struct timespec *tp)
       return -1;
     }
 
+#ifdef __ASSUME_TIME64_SYSCALLS
+# ifdef __NR_clock_settime64
+  /* For Y2038 safe systems with __WORDSIZE==32 and __TIMESIZE==64
+     (x86, arm) the glibc exported struct timespec has 64 bit tv_sec,
+     32 bit tv_nsec (to be still POSIX compliant -> long tv_nsec )
+     and 32 bits of unnamed padding.
+
+     It may happen that due to dynamic allocation the tv_pad, which
+     corresponds to upper 32 bits of kernel's 64 bit tv_nsec accepted
+     by syscalls, may not be zero.
+
+     However, the Linux kernel is ignoring those 32 bits (to be more
+     precise - as of 5.1 - it casts 64 bit tv_nsec to internal's 32 bit
+     representation) and hence the padding clearing is not needed.  */
+  int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
+  if (ret == 0 || errno != ENOSYS)
+    return ret;
+# endif
+#endif
+
+/* For systems supporting 32 bit time only __WORDSIZE==32 and
+   __TIMESIZE==32 (!=64) the passed struct __timespec64 must be
+   converted to 32 bit one before invoking Linux syscall.  */
+#if __WORDSIZE == 32 && __TIMESIZE != 64
+  /* Fall back to syscall supporting 32bit struct timespec.  */
+  struct timespec ts32;
+  valid_timespec64_to_timespec (tp, &ts32);
+  return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);
+#else
+/* Systems with __WORDSIZE==64 (i.e. x86_64, aarch64) or
+   __WORDSIZE==32 && __TIMESIZE == 64 (i.e. x32 - special case).  */
   return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp);
+#endif
 }
 weak_alias (__clock_settime, clock_settime)
+
+#if __TIMESIZE != 64
+int
+__clock_settime (clockid_t clock_id, const struct timespec *tp)
+{
+  struct __timespec64 ts64;
+
+  if (! in_time_t_range (tp->tv_sec))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  valid_timespec_to_timespec64 (tp, &ts64);
+  return __clock_settime64 (clock_id, &ts64);
+}
+#endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH v3 5/5] y2038: Support for Y2038 safe time on 32 bit systems
  2019-05-07 13:18 ` [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time Lukasz Majewski
                     ` (9 preceding siblings ...)
  2019-05-07 13:18   ` [PATCH v3 4/5] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
@ 2019-05-07 13:18   ` Lukasz Majewski
  2019-05-07 13:34     ` Andreas Schwab
  10 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-07 13:18 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

The time_t type is now Y2038 safe, which means that it is aliased to
__time64_t when __USE_TIME_BITS64 is defined or __time_t otherwise.

On the contrary the __time_t for 32 bit systems is only 32 bit, so for
Y2038 safe system it must be 64 bit (as is time_t)

This patch introduces the Y2038 specific code to make clock_settime/
__clock_settime64 Y2038 safe on 32 bit systems.
This goal is achieved by using aliasing to clock_settime names when
__USE_TIME_BITS64 is defined.
As a result user programs call 64 bit versions of functions (i.e.
__clock_settime64 instead of __clock_settime), which must have been
globally visible for this purpose - for non Y2038 safe code those are
hidden in glibc.


* include/features.h:
  Add logic to set __USE_TIME_BITS64 according to passed (when building
  userspace Y2038 safe program on 32 bit system) _TIME_BITS and
  _FILE_OFFSET_BITS
* manual/creature.texi: Add description of _TIME_BITS
* time/bits/types/time_t.h:
  Use __time64_t as time_t when __USE_TIME_BITS64 is defined
* time/bits/types/struct_timespec.h:
  Replace tv_sec's __time_t type to Y2038 safe time_t
* include/time.h:
  Remove libc_hidden_proto (__clock_settime64) - make the __clock_settime64
  publicly available for Y2038 safe system
* time/time.h: Redirect clock_settime call to __clock_settime64 on 32 bit
  Y2038 safe systems
* time/Versions (GLIBC_PRIVATE):
  Export __clock_settime64 function as glibc private one, to be accessible from
  user programs when y2038 support is enabled
* time/bits/types/struct_timespec.h:
  Add unnamed padding around tv_nsec when __USE_TIME_BITS64 is defined

---
Changes for v3:
- Only support clock_settime conversion to be Y2038 (use it as an example
  conversion code)

Changes for v2:
- Introduce unnamed padding in the struct timespec exported by glibc
  (to the /usr/include)
---
 include/features.h                | 19 +++++++++++++++++++
 include/time.h                    |  3 ++-
 manual/creature.texi              | 28 ++++++++++++++++++++++++++++
 time/Versions                     |  3 +++
 time/bits/types/struct_timespec.h | 15 +++++++++++++--
 time/bits/types/time_t.h          |  4 ++++
 time/time.h                       |  9 +++++++++
 7 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/include/features.h b/include/features.h
index e016b3e5c7..153c6320f0 100644
--- a/include/features.h
+++ b/include/features.h
@@ -365,6 +365,25 @@
 # define __USE_FILE_OFFSET64	1
 #endif
 
+/* We need to know the word size in order to check the time size.  */
+#include <bits/wordsize.h>
+
+#if defined _TIME_BITS
+# if _TIME_BITS == 64
+#  if ! defined (_FILE_OFFSET_BITS) || _FILE_OFFSET_BITS != 64
+#   error _TIME_BITS==64 is allowed only when _FILE_OFFSET_BITS==64
+#  elif __WORDSIZE == 32
+#   define __USE_TIME_BITS64	1
+#  endif
+# elif _TIME_BITS == 32
+#  if __WORDSIZE > 32
+#   error _TIME_BITS=32 is not compatible with __WORDSIZE > 32
+#  endif
+# else
+#  error Invalid _TIME_BITS value (can only be 32 or 64)
+# endif
+#endif
+
 #if defined _DEFAULT_SOURCE
 # define __USE_MISC	1
 #endif
diff --git a/include/time.h b/include/time.h
index 670226df0c..d4b11cb1a9 100644
--- a/include/time.h
+++ b/include/time.h
@@ -132,7 +132,8 @@ libc_hidden_proto (__timegm64)
 #else
 extern int __clock_settime64 (clockid_t clock_id,
                               const struct __timespec64 *tp);
-libc_hidden_proto (__clock_settime64)
+/* For Y2038 safe system the __clock_settime64 needs to be a visible
+   symbol as a replacement for Y2038 unsafe clock_settime.  */
 #endif
 
 /* Compute the `struct tm' representation of T,
diff --git a/manual/creature.texi b/manual/creature.texi
index 8876b2ab77..10b7111043 100644
--- a/manual/creature.texi
+++ b/manual/creature.texi
@@ -165,6 +165,34 @@ This macro was introduced as part of the Large File Support extension
 (LFS).
 @end defvr
 
+@defvr Macro _TIME_BITS
+This macro determines the bit size of @code{time_t} (and therefore the
+bit size of all @code{time_t} derived types and the prototypes of all
+related functions). If @code{_TIME_BITS} is undefined, the bit size of
+time_t equals the bit size of the architecture.
+
+If @code{_TIME_BITS} is undefined, or if @code{_TIME_BITS} is defined
+to the value @code{32} and @code{__WORDSIZE} is defined to the value
+@code{32}, or or if @code{_TIME_BITS} is defined to the value @code{64}
+and @code{__WORDSIZE} is defined to the value @code{64}, nothing changes.
+
+If @code{_TIME_BITS} is defined to the value @code{64} and if
+@code{__WORDSIZE} is defined to the value @code{32}, then the @w{64 bit}
+time API and implementation are used even though the architecture word
+size is @code{32}. Also, if the kernel provides @w{64 bit} time support,
+it is used; otherwise, the @w{32 bit} kernel time support is used (with
+no provision to address kernel Y2038 shortcomings).
+
+If @code{_TIME_BITS} is defined to the value @code{32} and if
+@code{__WORDSIZE} is defined to the value @code{64}, then a compile-time
+error is emitted.
+
+If @code{_TIME_BITS} is defined to a value different from both @code{32}
+and @code{64}, then a compile-time error is emitted.
+
+This macro was introduced as part of the Y2038 support.
+@end defvr
+
 @defvr Macro _ISOC99_SOURCE
 @standards{GNU, (none)}
 If this macro is defined, features from ISO C99 are included.  Since
diff --git a/time/Versions b/time/Versions
index fd838181e4..5109c45ce2 100644
--- a/time/Versions
+++ b/time/Versions
@@ -1,4 +1,7 @@
 libc {
+  GLIBC_PRIVATE {
+    __clock_settime64;
+  }
   GLIBC_2.0 {
     # global variables
     __daylight; __timezone; __tzname;
diff --git a/time/bits/types/struct_timespec.h b/time/bits/types/struct_timespec.h
index 5b77c52b4f..f34df0a18c 100644
--- a/time/bits/types/struct_timespec.h
+++ b/time/bits/types/struct_timespec.h
@@ -3,13 +3,24 @@
 #define _STRUCT_TIMESPEC 1
 
 #include <bits/types.h>
+#include <bits/types/time_t.h>
 
 /* POSIX.1b structure for a time value.  This is like a `struct timeval' but
    has nanoseconds instead of microseconds.  */
 struct timespec
 {
-  __time_t tv_sec;		/* Seconds.  */
-  __syscall_slong_t tv_nsec;	/* Nanoseconds.  */
+  time_t tv_sec;		/* Seconds.  */
+# ifdef __USE_TIME_BITS64
+#  if __BYTE_ORDER == __BIG_ENDIAN
+  int : 32;
+  __syscall_slong_t tv_nsec; /* Nanoseconds.  */
+#  else
+  __syscall_slong_t tv_nsec; /* Nanoseconds.  */
+  int : 32;
+#  endif
+# else
+  __syscall_slong_t tv_nsec; /* Nanoseconds.  */
+# endif
 };
 
 #endif
diff --git a/time/bits/types/time_t.h b/time/bits/types/time_t.h
index ab8287c6fe..84d67f6ac3 100644
--- a/time/bits/types/time_t.h
+++ b/time/bits/types/time_t.h
@@ -4,6 +4,10 @@
 #include <bits/types.h>
 
 /* Returned by `time'.  */
+#ifdef __USE_TIME_BITS64
+typedef __time64_t time_t;
+#else
 typedef __time_t time_t;
+#endif
 
 #endif
diff --git a/time/time.h b/time/time.h
index cba6d15260..0bfd1de925 100644
--- a/time/time.h
+++ b/time/time.h
@@ -222,6 +222,15 @@ extern int clock_gettime (clockid_t __clock_id, struct timespec *__tp) __THROW;
 extern int clock_settime (clockid_t __clock_id, const struct timespec *__tp)
      __THROW;
 
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (clock_settime, (clockid_t __clock_id, const struct
+                                       timespec *__tp), __clock_settime64) __THROW;
+# else
+# define clock_settime __clock_settime64
+# endif
+#endif
+
 # ifdef __USE_XOPEN2K
 /* High-resolution sleep with the specified clock.
 
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* Re: [PATCH v3 2/5] y2038: Introduce internal for glibc struct __timespec64
  2019-05-07 13:18   ` [PATCH v3 2/5] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
@ 2019-05-07 13:30     ` Andreas Schwab
  2019-05-07 14:07       ` Lukasz Majewski
  0 siblings, 1 reply; 111+ messages in thread
From: Andreas Schwab @ 2019-05-07 13:30 UTC (permalink / raw)
  To: Lukasz Majewski
  Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert,
	Joseph Myers

On Mai 07 2019, Lukasz Majewski <lukma@denx.de> wrote:

> +struct __timespec64
> +{
> +  __time64_t tv_sec;         /* Seconds */
> +# if BYTE_ORDER == BIG_ENDIAN
> +  int tv_pad: 32;            /* Padding named for checking/setting */
> +  __int32_t tv_nsec;         /* Nanoseconds */
> +# else
> +  __int32_t tv_nsec;         /* Nanoseconds */
> +  int tv_pad: 32;            /* Padding named for checking/setting */
> +# endif

No need to use a bitfield, since the padding is not fractional.

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v3 5/5] y2038: Support for Y2038 safe time on 32 bit systems
  2019-05-07 13:18   ` [PATCH v3 5/5] y2038: Support for Y2038 safe time on 32 bit systems Lukasz Majewski
@ 2019-05-07 13:34     ` Andreas Schwab
  0 siblings, 0 replies; 111+ messages in thread
From: Andreas Schwab @ 2019-05-07 13:34 UTC (permalink / raw)
  To: Lukasz Majewski
  Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert,
	Joseph Myers

On Mai 07 2019, Lukasz Majewski <lukma@denx.de> wrote:

> diff --git a/include/features.h b/include/features.h
> index e016b3e5c7..153c6320f0 100644
> --- a/include/features.h
> +++ b/include/features.h
> @@ -365,6 +365,25 @@
>  # define __USE_FILE_OFFSET64	1
>  #endif
>  
> +/* We need to know the word size in order to check the time size.  */
> +#include <bits/wordsize.h>
> +
> +#if defined _TIME_BITS
> +# if _TIME_BITS == 64
> +#  if ! defined (_FILE_OFFSET_BITS) || _FILE_OFFSET_BITS != 64
> +#   error _TIME_BITS==64 is allowed only when _FILE_OFFSET_BITS==64

Perhaps:

#   error _TIME_BITS=64 is allowed only with _FILE_OFFSET_BITS=64

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v3 2/5] y2038: Introduce internal for glibc struct __timespec64
  2019-05-07 13:30     ` Andreas Schwab
@ 2019-05-07 14:07       ` Lukasz Majewski
  2019-05-07 14:13         ` Andreas Schwab
  0 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-07 14:07 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert,
	Joseph Myers

[-- Attachment #1: Type: text/plain, Size: 1280 bytes --]

Hi Andreas,

> On Mai 07 2019, Lukasz Majewski <lukma@denx.de> wrote:
> 
> > +struct __timespec64
> > +{
> > +  __time64_t tv_sec;         /* Seconds */
> > +# if BYTE_ORDER == BIG_ENDIAN
> > +  int tv_pad: 32;            /* Padding named for checking/setting
> > */
> > +  __int32_t tv_nsec;         /* Nanoseconds */
> > +# else
> > +  __int32_t tv_nsec;         /* Nanoseconds */
> > +  int tv_pad: 32;            /* Padding named for checking/setting
> > */ +# endif  
> 
> No need to use a bitfield, since the padding is not fractional.

That bitfield is for following reasons:

1. Have a backup plan in the case if we need to copy and clear the
padding anyway before passing this structure to the kernel in the future
(as recently we discovered that for example x32 has a kernel bug with
clearing it).

2. Kernel syscalls (e.g. clock_settime64) expects on those systems two
values - each 8 bytes. To avoid any nasty surprises the explicit
padding was added.

> 
> Andreas.
> 




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v3 2/5] y2038: Introduce internal for glibc struct __timespec64
  2019-05-07 14:07       ` Lukasz Majewski
@ 2019-05-07 14:13         ` Andreas Schwab
  2019-05-08  8:32           ` Lukasz Majewski
  0 siblings, 1 reply; 111+ messages in thread
From: Andreas Schwab @ 2019-05-07 14:13 UTC (permalink / raw)
  To: Lukasz Majewski
  Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert,
	Joseph Myers

On Mai 07 2019, Lukasz Majewski <lukma@denx.de> wrote:

> Hi Andreas,
>
>> On Mai 07 2019, Lukasz Majewski <lukma@denx.de> wrote:
>> 
>> > +struct __timespec64
>> > +{
>> > +  __time64_t tv_sec;         /* Seconds */
>> > +# if BYTE_ORDER == BIG_ENDIAN
>> > +  int tv_pad: 32;            /* Padding named for checking/setting
>> > */
>> > +  __int32_t tv_nsec;         /* Nanoseconds */
>> > +# else
>> > +  __int32_t tv_nsec;         /* Nanoseconds */
>> > +  int tv_pad: 32;            /* Padding named for checking/setting
>> > */ +# endif  
>> 
>> No need to use a bitfield, since the padding is not fractional.
>
> That bitfield is for following reasons:
>
> 1. Have a backup plan in the case if we need to copy and clear the
> padding anyway before passing this structure to the kernel in the future
> (as recently we discovered that for example x32 has a kernel bug with
> clearing it).
>
> 2. Kernel syscalls (e.g. clock_settime64) expects on those systems two
> values - each 8 bytes. To avoid any nasty surprises the explicit
> padding was added.

None of that requires a bitfield.

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-06 14:56           ` Lukasz Majewski
@ 2019-05-07 15:35             ` Joseph Myers
  2019-05-08 10:18               ` Lukasz Majewski
  0 siblings, 1 reply; 111+ messages in thread
From: Joseph Myers @ 2019-05-07 15:35 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert

On Mon, 6 May 2019, Lukasz Majewski wrote:

> > So, which is (or will be) the case in 5.1 release?  Padding ignored
> > or not?
> 
> As confirmed in the other mail - the padding is ignored in Linux kernel
> (and the fix patch for x32 is up its way to be pulled).

Did the patch to ignore padding (for compat syscalls under 64-bit kernels, 
non-x32) make it into the final 5.1 release?

> > It's possible it's __SYSCALL_WORDSIZE, except that's only defined for 
> > x86_64, so would need to be made more generally available if it's to
> > be used here.  And if made more generally available, it would need a
> > careful comment explaining exactly what it means.
> 
> Cannot we just use __WORDSIZE != 64  as proposed by Stepan?
> (for x32 we would have it defined by default)
> 
> #if __WORDSIZE != 64
> # if __LINUX_KERNEL_VERSION >= 0x050100
> #  define __ASSUME_TIME64_SYSCALLS 1
> # endif
> #endif  
> 
> Such approach would allow us to avoid introducing new abstraction
> (__SYSCALL_WORDSIZE).

There are lots of implementation possibilities, including using 
__WORDSIZE and undefining for x32, or using __WORDSIZE and defining the 
__NR_* macros locally for x32.

At the present stage of review, I'm not really concerned with such 
implementation details.  Rather, I'm reviewing things at the level of 
concepts and abstractions, and how we document those concepts and 
abstractions.  The things we need to define here are:

* What are the sets of syscalls related to 64-bit time, with the property 
that, in any given kernel, either all the syscalls in such a set are 
present, or all the syscalls in such a set are absent?

Right now, maybe there's only one such set, and the subset of it being 
used in glibc can be defined by listing the syscalls.  In future, there 
may well be more than one such set - for example, if syscalls that 
currently only have versions using timeval get new versions using timespec 
that are added even on architectures where the pre-5.1 kernel syscall 
interface already uses 64-bit time.

* For each set of syscalls, what is the *best* logical description of the 
set of kernel configurations that has those syscalls?  There may be many 
equivalent descriptions of the current set of such configurations; we need 
to find one that is correct, unambiguous, succinct, close to the actual 
logic in the kernel that determines whether those syscalls are present, 
and has the least chance of being inaccurate for future kernel 
configurations.

Once we have those concepts clearly defined, we can then look at how to 
translate them into code.

Since (a) future architectures all use asm-generic and (b) the asm-generic 
code uses __BITS_PER_LONG == 32, that suggests something in terms of the 
size of "long" is the right way to describe the condition for the presence 
of the syscalls - at which point you then need to discuss how the size of 
"long" can vary between ABIs, and how in the x32 case the size of "long" 
in the syscall interface is not the same as the normal size of that C 
type.

Within glibc, __WORDSIZE corresponds to the size of "long", so that in 
turn suggests an implementation approach based on __WORDSIZE in some way, 
if you have an exception for x32.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-06 19:36                     ` Stepan Golosunov
  2019-05-06 21:14                       ` Lukasz Majewski
@ 2019-05-07 15:43                       ` Joseph Myers
  1 sibling, 0 replies; 111+ messages in thread
From: Joseph Myers @ 2019-05-07 15:43 UTC (permalink / raw)
  To: Stepan Golosunov; +Cc: Lukasz Majewski, libc-alpha, Arnd Bergmann, Paul Eggert

On Mon, 6 May 2019, Stepan Golosunov wrote:

> > > > > One way would be by defining __ASSUME_TIME64_SYSCALLS
> > > > > unconditionally on x32 and then defining __NR_clock_settime64 to
> > > > > __NR_clock_settime when __ASSUME_TIME64_SYSCALLS is defined while
> > > > > __NR_clock_settime64 isn't.
> 
> I think now that with this scheme __ASSUME_TIME64_SYSCALLS should be
> defined unconditionally for the __WORDSIZE==64 case too.  With this

That's certainly one possibility for how to implement things - define all 
the __NR_*64 to the older __NR_* in the case where the older __NR_* 
already handle 64-bit time.

If that approach is used, the comment on __ASSUME_TIME64_SYSCALLS then 
needs to describe *two* different concepts very carefully, without 
conflating them: the set of syscall ABIs with the new syscalls, and the 
set of syscall ABIs which have 64-bit time functionality for a given set 
of interfaces, with the __NR_*64 names for those interfaces being 
available within glibc (but where it might be either old or new syscalls 
behind those names in glibc).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v3 1/5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-07 13:18   ` [PATCH v3 1/5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define Lukasz Majewski
@ 2019-05-07 16:04     ` Joseph Myers
  0 siblings, 0 replies; 111+ messages in thread
From: Joseph Myers @ 2019-05-07 16:04 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert

On Tue, 7 May 2019, Lukasz Majewski wrote:

> +/* Support for 64 bit version of time related Linux syscalls.

There are several issues with this comment.

(a) It's no longer listing or more precisely describing the syscalls in 
question.  "64 bit version of time related Linux syscalls" is not adequate 
because of the likelihood of having more than one such set in future, with 
different conditions for being present in the kernel.

(b) The several variants described in the comment are variants at the 
wrong logical level for describing __ASSUME_TIME64_SYSCALLS - they are 
different kinds of glibc configurations (with regard to all aspects of how 
time is handled in glibc), not different kinds of syscall ABI.  
__ASSUME_TIME64_SYSCALLS is a property of the Linux kernel syscall ABI.  
The comment should describe its semantics in those terms (in terms of the 
syscall ABI's "long"), without confusing it with other related concepts.

If these variants are described anywhere in glibc, it should be in the 
internals section of the manual.

(c) The comment should not refer to the user-level interface _TIME_BITS 
either, as that's also confusing features at different levels.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v3 5/5] y2038: Support for Y2038 safe time on 32 bit systems
  2019-05-07 13:18   ` [PATCH v3 5/5] y2038: Support for Y2038 safe time on 32 bit systems Lukasz Majewski
@ 2019-05-07 16:37     ` Joseph Myers
  2019-05-08 10:27       ` Lukasz Majewski
  0 siblings, 1 reply; 111+ messages in thread
From: Joseph Myers @ 2019-05-07 16:37 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert

_TIME_BITS support should not be added to public headers until it's 
complete.  Incomplete support is very unhelpful to users, as it would mean 
lots of functions get declared to take the 64-bit time_t type when in fact 
their ABI takes a 32-bit time_t argument (so code built with _TIME_BITS=64 
wouldn't work at all in a state where it's only partly supported).

When the support *is* added to the public headers, it should come with 
tests added to the glibc testsuite that _TIME_BTIS=64 works as expected 
for all interfaces for which this can readily be tested.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v3 4/5] y2038: linux: Provide __clock_settime64 implementation
  2019-05-07 13:18   ` [PATCH v3 4/5] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
@ 2019-05-07 16:40     ` Joseph Myers
  0 siblings, 0 replies; 111+ messages in thread
From: Joseph Myers @ 2019-05-07 16:40 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert

On Tue, 7 May 2019, Lukasz Majewski wrote:

> +#ifdef __ASSUME_TIME64_SYSCALLS
> +# ifdef __NR_clock_settime64
> +  /* For Y2038 safe systems with __WORDSIZE==32 and __TIMESIZE==64
> +     (x86, arm) the glibc exported struct timespec has 64 bit tv_sec,
> +     32 bit tv_nsec (to be still POSIX compliant -> long tv_nsec )
> +     and 32 bits of unnamed padding.
> +
> +     It may happen that due to dynamic allocation the tv_pad, which
> +     corresponds to upper 32 bits of kernel's 64 bit tv_nsec accepted
> +     by syscalls, may not be zero.
> +
> +     However, the Linux kernel is ignoring those 32 bits (to be more
> +     precise - as of 5.1 - it casts 64 bit tv_nsec to internal's 32 bit
> +     representation) and hence the padding clearing is not needed.  */
> +  int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
> +  if (ret == 0 || errno != ENOSYS)
> +    return ret;
> +# endif

This logic is wrong.  If __ASSUME_TIME64_SYSCALLS is defined, then:

(a) There should be no special ENOSYS check, as the syscall is guaranteed 
to be present; just return its return value.

(b) There is no need for a check of whether __NR_clock_settime64 is 
defined, because the kernel headers are always at least as new as the 
minimum runtime kernel version; a build failure if __NR_clock_settime64 is 
somehow not defined, despite __ASSUME_TIME64_SYSCALLS being defined, is 
entirely appropriate.

Tests of __NR_clock_settime64 being defined are entirely appropriate 
if __ASSUME_TIME64_SYSCALLS is *not* defined; likewise runtime tests for 
an ENOSYS return to determine whether in fact the syscall existed or 
whether a fallback to the older syscalls is needed.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-06 21:14                       ` Lukasz Majewski
@ 2019-05-07 20:03                         ` Stepan Golosunov
  2019-05-07 20:44                           ` Joseph Myers
  2019-05-08  7:51                           ` Lukasz Majewski
  0 siblings, 2 replies; 111+ messages in thread
From: Stepan Golosunov @ 2019-05-07 20:03 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: Joseph Myers, libc-alpha, Arnd Bergmann, Paul Eggert

06.05.2019 в 23:14:44 +0200 Lukasz Majewski написал:
> For ARM, x86 there shall be call to clock_settime64 syscall
> 
> For x32 there shall be call to clock_settime syscall (which is
> supporting 64 bit anyway - despite the ignoring possible padding
> clearing issue).

> I rather thought about something like:
> 
> __clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
> {
>   <overflow check>
> 
> #ifdef __ASSUME_TIME64_SYSCALLS
> # ifdef __NR_clock_settime64
>   int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
>   if (ret == 0 || errno != ENOSYS)
> 	return ret;
> # endif
>   /* Fall back to syscall supporting 32bit struct timespec.  */
>   struct timespec ts32;
>   valid_timespec64_to_timespec (tp, &ts32);
>   return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);
> #else
>   /* 64 bit machines + x32 */
>   return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp);
> #endif
> }
> 
> In the above pseudo code we assume that __ASSUME_TIME64_SYSCALLS is
> #undef'ed for x32 (so it is treated as a 'special case' - in the same
> way as x86_64).

Usually the point of __ASSUME_* macros is to avoid compiling old
compatibility code when it's not needed.  That means there should be
no fallback to 32-bit clock_settime when __ASSUME_TIME64_SYSCALLS is
defined.  Even when it's defined on 32-bit arm or x86.

And with your current use of __ASSUME_TIME64_SYSCALLS
__NR_clock_settime64 won't be used on any existing architecture.
Because __ASSUME_TIME64_SYSCALLS won't be defined until Linux 5.0 is
no longer supported.

If you replace

#ifdef __ASSUME_TIME64_SYSCALLS

with

#ifdef __NR_clock_settime64

result would make more sense than what you have now.

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-07 20:03                         ` Stepan Golosunov
@ 2019-05-07 20:44                           ` Joseph Myers
  2019-05-08  7:51                           ` Lukasz Majewski
  1 sibling, 0 replies; 111+ messages in thread
From: Joseph Myers @ 2019-05-07 20:44 UTC (permalink / raw)
  To: Stepan Golosunov; +Cc: Lukasz Majewski, libc-alpha, Arnd Bergmann, Paul Eggert

On Wed, 8 May 2019, Stepan Golosunov wrote:

> If you replace
> 
> #ifdef __ASSUME_TIME64_SYSCALLS
> 
> with
> 
> #ifdef __NR_clock_settime64
> 
> result would make more sense than what you have now.

Actually I'd expect it to start something more like

#ifdef __ASSUME_TIME64_SYSCALLS
  return INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
#elif defined __NR_clock_settime64

to behave as expected for both __ASSUME_TIME64_SYSCALLS, and the case 
where __NR_clock_settime64 is defined but __ASSUME_TIME64_SYSCALLS is not.  
(The correct fallback when __NR_clock_settime64 is not defined depends on 
the size of time_t as used in the old syscalls.  Note that you *cannot* 
assume that 5.1 kernel headers are in use, so __NR_clock_settime64 
undefined might means a system where the syscall ABI already uses 64-bit 
times with clock_settime, or it might mean one where the syscall ABI uses 
32-bit times with clock_settime but old kernel headers are in use.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-07 20:03                         ` Stepan Golosunov
  2019-05-07 20:44                           ` Joseph Myers
@ 2019-05-08  7:51                           ` Lukasz Majewski
  2019-05-08 19:48                             ` Stepan Golosunov
  1 sibling, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-08  7:51 UTC (permalink / raw)
  To: Stepan Golosunov; +Cc: Joseph Myers, libc-alpha, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 2299 bytes --]

Hi Stepan,

> 06.05.2019 в 23:14:44 +0200 Lukasz Majewski написал:
> > For ARM, x86 there shall be call to clock_settime64 syscall
> > 
> > For x32 there shall be call to clock_settime syscall (which is
> > supporting 64 bit anyway - despite the ignoring possible padding
> > clearing issue).  
> 
> > I rather thought about something like:
> > 
> > __clock_settime64 (clockid_t clock_id, const struct __timespec64
> > *tp) {
> >   <overflow check>
> > 
> > #ifdef __ASSUME_TIME64_SYSCALLS
> > # ifdef __NR_clock_settime64
> >   int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
> >   if (ret == 0 || errno != ENOSYS)
> > 	return ret;
> > # endif
> >   /* Fall back to syscall supporting 32bit struct timespec.  */
> >   struct timespec ts32;
> >   valid_timespec64_to_timespec (tp, &ts32);
> >   return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);
> > #else
> >   /* 64 bit machines + x32 */
> >   return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp);
> > #endif
> > }
> > 
> > In the above pseudo code we assume that __ASSUME_TIME64_SYSCALLS is
> > #undef'ed for x32 (so it is treated as a 'special case' - in the
> > same way as x86_64).  
> 
> Usually the point of __ASSUME_* macros is to avoid compiling old
> compatibility code when it's not needed.  That means there should be
> no fallback to 32-bit clock_settime when __ASSUME_TIME64_SYSCALLS is
> defined.  Even when it's defined on 32-bit arm or x86.
> 
> And with your current use of __ASSUME_TIME64_SYSCALLS
> __NR_clock_settime64 won't be used on any existing architecture.
> Because __ASSUME_TIME64_SYSCALLS won't be defined until Linux 5.0 is
> no longer supported.

It will be used when the minimal supported kernel reaches 5.1. (now it
is 3.2.)

For testing I do use --enable-kernel="5.1.0" passed to configure.

> 
> If you replace
> 
> #ifdef __ASSUME_TIME64_SYSCALLS
> 
> with
> 
> #ifdef __NR_clock_settime64
> 
> result would make more sense than what you have now.




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v3 2/5] y2038: Introduce internal for glibc struct __timespec64
  2019-05-07 14:13         ` Andreas Schwab
@ 2019-05-08  8:32           ` Lukasz Majewski
  2019-05-08  8:38             ` Andreas Schwab
  0 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-08  8:32 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert,
	Joseph Myers

[-- Attachment #1: Type: text/plain, Size: 2234 bytes --]

Hi Andreas,

> On Mai 07 2019, Lukasz Majewski <lukma@denx.de> wrote:
> 
> > Hi Andreas,
> >  
> >> On Mai 07 2019, Lukasz Majewski <lukma@denx.de> wrote:
> >>   
> >> > +struct __timespec64
> >> > +{
> >> > +  __time64_t tv_sec;         /* Seconds */
> >> > +# if BYTE_ORDER == BIG_ENDIAN
> >> > +  int tv_pad: 32;            /* Padding named for
> >> > checking/setting */
> >> > +  __int32_t tv_nsec;         /* Nanoseconds */
> >> > +# else
> >> > +  __int32_t tv_nsec;         /* Nanoseconds */
> >> > +  int tv_pad: 32;            /* Padding named for
> >> > checking/setting */ +# endif    
> >> 
> >> No need to use a bitfield, since the padding is not fractional.  
> >
> > That bitfield is for following reasons:
> >
> > 1. Have a backup plan in the case if we need to copy and clear the
> > padding anyway before passing this structure to the kernel in the
> > future (as recently we discovered that for example x32 has a kernel
> > bug with clearing it).
> >
> > 2. Kernel syscalls (e.g. clock_settime64) expects on those systems
> > two values - each 8 bytes. To avoid any nasty surprises the explicit
> > padding was added.  
> 
> None of that requires a bitfield.

For 32 bit systems with 64 bit time_t we would have following
situation:

struct timespec:
	-> tv_sec (8 B)
	-> tv_nsec (4 B -> must be long as of POSIX) [*]

This would have 16B size (sizeof() would return 16B [1])


My point is if we do need at any point in time to clear this padding
(due to e.g. kernel bug when passing data to syscalls [2] or solve issue
as presented in [*]).


Note:

[*] - the x32 ABI of x86_64 has long 8B and there are some issues with
POSIX compliance
https://sourceware.org/bugzilla/show_bug.cgi?id=16437

[1] - as discussed:
http://www.catb.org/esr/structure-packing/#_structure_alignment_and_padding

[2] -
https://lore.kernel.org/lkml/20190429131951.471701-1-arnd@arndb.de/

> 
> Andreas.
> 




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v3 2/5] y2038: Introduce internal for glibc struct __timespec64
  2019-05-08  8:32           ` Lukasz Majewski
@ 2019-05-08  8:38             ` Andreas Schwab
  2019-05-08  9:10               ` Lukasz Majewski
  0 siblings, 1 reply; 111+ messages in thread
From: Andreas Schwab @ 2019-05-08  8:38 UTC (permalink / raw)
  To: Lukasz Majewski
  Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert,
	Joseph Myers

On Mai 08 2019, Lukasz Majewski <lukma@denx.de> wrote:

> My point is if we do need at any point in time to clear this padding
> (due to e.g. kernel bug when passing data to syscalls [2] or solve issue
> as presented in [*]).

Yes, but you don't need to use a *bitfield*.

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v3 2/5] y2038: Introduce internal for glibc struct __timespec64
  2019-05-08  8:38             ` Andreas Schwab
@ 2019-05-08  9:10               ` Lukasz Majewski
  2019-05-08  9:12                 ` Andreas Schwab
  0 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-08  9:10 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert,
	Joseph Myers

[-- Attachment #1: Type: text/plain, Size: 993 bytes --]

On Wed, 08 May 2019 10:38:20 +0200
Andreas Schwab <schwab@suse.de> wrote:

> On Mai 08 2019, Lukasz Majewski <lukma@denx.de> wrote:
> 
> > My point is if we do need at any point in time to clear this padding
> > (due to e.g. kernel bug when passing data to syscalls [2] or solve
> > issue as presented in [*]).  
> 
> Yes, but you don't need to use a *bitfield*.

Could you share your opinion about the type to use to replace the
bitfield?

The other option would be to use __int32_t tv_pad.


Another question - shall we use __int32_t for tv_nsec or
__syscall_slong_t for internal representation?

We would end up with the same type in the end, but I don't know what is
preferable.

> 
> Andreas.
> 




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v3 2/5] y2038: Introduce internal for glibc struct __timespec64
  2019-05-08  9:10               ` Lukasz Majewski
@ 2019-05-08  9:12                 ` Andreas Schwab
  2019-05-08  9:37                   ` Lukasz Majewski
  0 siblings, 1 reply; 111+ messages in thread
From: Andreas Schwab @ 2019-05-08  9:12 UTC (permalink / raw)
  To: Lukasz Majewski
  Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert,
	Joseph Myers

On Mai 08 2019, Lukasz Majewski <lukma@denx.de> wrote:

> On Wed, 08 May 2019 10:38:20 +0200
> Andreas Schwab <schwab@suse.de> wrote:
>
>> On Mai 08 2019, Lukasz Majewski <lukma@denx.de> wrote:
>> 
>> > My point is if we do need at any point in time to clear this padding
>> > (due to e.g. kernel bug when passing data to syscalls [2] or solve
>> > issue as presented in [*]).  
>> 
>> Yes, but you don't need to use a *bitfield*.
>
> Could you share your opinion about the type to use to replace the
> bitfield?

Anything that fits, but not a bitfield.

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v3 2/5] y2038: Introduce internal for glibc struct __timespec64
  2019-05-08  9:12                 ` Andreas Schwab
@ 2019-05-08  9:37                   ` Lukasz Majewski
  0 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-08  9:37 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert,
	Joseph Myers

[-- Attachment #1: Type: text/plain, Size: 991 bytes --]

On Wed, 08 May 2019 11:12:27 +0200
Andreas Schwab <schwab@suse.de> wrote:

> On Mai 08 2019, Lukasz Majewski <lukma@denx.de> wrote:
> 
> > On Wed, 08 May 2019 10:38:20 +0200
> > Andreas Schwab <schwab@suse.de> wrote:
> >  
> >> On Mai 08 2019, Lukasz Majewski <lukma@denx.de> wrote:
> >>   
> >> > My point is if we do need at any point in time to clear this
> >> > padding (due to e.g. kernel bug when passing data to syscalls
> >> > [2] or solve issue as presented in [*]).    
> >> 
> >> Yes, but you don't need to use a *bitfield*.  
> >
> > Could you share your opinion about the type to use to replace the
> > bitfield?  
> 
> Anything that fits, but not a bitfield.

Ok :-)

> 
> Andreas.
> 




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-07 15:35             ` Joseph Myers
@ 2019-05-08 10:18               ` Lukasz Majewski
  2019-05-09 15:46                 ` Joseph Myers
  2019-05-31 11:37                 ` Stepan Golosunov
  0 siblings, 2 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-08 10:18 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 5076 bytes --]

Hi Joseph,

> On Mon, 6 May 2019, Lukasz Majewski wrote:
> 
> > > So, which is (or will be) the case in 5.1 release?  Padding
> > > ignored or not?  
> > 
> > As confirmed in the other mail - the padding is ignored in Linux
> > kernel (and the fix patch for x32 is up its way to be pulled).  
> 
> Did the patch to ignore padding (for compat syscalls under 64-bit
> kernels, non-x32) make it into the final 5.1 release?

As fair as I can tell, it was not pulled to 5.1.

> 
> > > It's possible it's __SYSCALL_WORDSIZE, except that's only defined
> > > for x86_64, so would need to be made more generally available if
> > > it's to be used here.  And if made more generally available, it
> > > would need a careful comment explaining exactly what it means.  
> > 
> > Cannot we just use __WORDSIZE != 64  as proposed by Stepan?
> > (for x32 we would have it defined by default)
> > 
> > #if __WORDSIZE != 64
> > # if __LINUX_KERNEL_VERSION >= 0x050100
> > #  define __ASSUME_TIME64_SYSCALLS 1
> > # endif
> > #endif  
> > 
> > Such approach would allow us to avoid introducing new abstraction
> > (__SYSCALL_WORDSIZE).  
> 
> There are lots of implementation possibilities, including using 
> __WORDSIZE and undefining for x32, or using __WORDSIZE and defining
> the __NR_* macros locally for x32.
> 
> At the present stage of review, I'm not really concerned with such 
> implementation details.  Rather, I'm reviewing things at the level of 
> concepts and abstractions, and how we document those concepts and 
> abstractions.  The things we need to define here are:
> 
> * What are the sets of syscalls related to 64-bit time, with the
> property that, in any given kernel, either all the syscalls in such a
> set are present, or all the syscalls in such a set are absent?

The 64 bit versions of syscalls (like clock_settime64 or
clock_gettime64) are available since 5.1 kernel (as you posted already
the following patch: "Update syscall-names.list for Linux 5.1" .

I've now only focused on clock_settime(64) to make the discussion more
concrete.

> 
> Right now, maybe there's only one such set, and the subset of it
> being used in glibc can be defined by listing the syscalls.  In
> future, there may well be more than one such set - for example, if
> syscalls that currently only have versions using timeval get new
> versions using timespec that are added even on architectures where
> the pre-5.1 kernel syscall interface already uses 64-bit time.

This may also happen, yes.

> 
> * For each set of syscalls, what is the *best* logical description of
> the set of kernel configurations that has those syscalls? 

IMHO, the description is as follows:

"Time related syscalls with explicit 64 bit time support to be run on
archs with 32 bit pointer/long (__WORDSIZE==32)"

Hence the __ASSUME_TIME64_SYSCALLS seems to be a descriptive name (as
even in the kernel some syscalls end with _time64 suffix - i.e.
sched_rr_get_interval_time64) .

> There may
> be many equivalent descriptions of the current set of such
> configurations; we need to find one that is correct, unambiguous,
> succinct, close to the actual logic in the kernel that determines
> whether those syscalls are present, and has the least chance of being
> inaccurate for future kernel configurations.
> 

As stated above - those syscalls are supposed to be used on systems
with __WORDSIZE==32 [*] to provide support for 64 bit time (Y2038 safe).

> Once we have those concepts clearly defined, we can then look at how
> to translate them into code.
> 
> Since (a) future architectures all use asm-generic and (b) the
> asm-generic code uses __BITS_PER_LONG == 32, that suggests something
> in terms of the size of "long" is the right way to describe the
> condition for the presence of the syscalls - at which point you then
> need to discuss how the size of "long" can vary between ABIs, and how
> in the x32 case the size of "long" in the syscall interface is not
> the same as the normal size of that C type.
> 
> Within glibc, __WORDSIZE corresponds to the size of "long", so that
> in turn suggests an implementation approach based on __WORDSIZE in
> some way,

That was the approach took in v3 of the patch set [1] (I do send patches
to show the big picture about the idea and most of all - IMHO it is
easier to discuss the concept with some code available)

>  if you have an exception for x32.
> 

Yes, x32 is special :-) (I'm wondering though what is the percentage of
glibc users, who use this particular ABI...)

Note:

[*] - x32 is a special case and (as proposed in the v3 patch set) shall
#undef the __ASSUME_TIME64_SYSCALLS as it uses syscalls from x86_64

[1] - https://patchwork.ozlabs.org/patch/1096343/

Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v3 5/5] y2038: Support for Y2038 safe time on 32 bit systems
  2019-05-07 16:37     ` Joseph Myers
@ 2019-05-08 10:27       ` Lukasz Majewski
  0 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-08 10:27 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 1099 bytes --]

Hi Joseph,

> _TIME_BITS support should not be added to public headers until it's 
> complete.  Incomplete support is very unhelpful to users, as it would
> mean lots of functions get declared to take the 64-bit time_t type
> when in fact their ABI takes a 32-bit time_t argument (so code built
> with _TIME_BITS=64 wouldn't work at all in a state where it's only
> partly supported).

This patch is supposed to show and possible allow some
testing of Y2038 code (64 bit time support in general).

For next version of this patch set - I will mark it as "PATCH DO NOT
APPLY" or such to make it clear.

> 
> When the support *is* added to the public headers, it should come
> with tests added to the glibc testsuite that _TIME_BTIS=64 works as
> expected for all interfaces for which this can readily be tested.
> 




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* [PATCH] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-04-14 22:08 [PATCH 0/6] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
                   ` (7 preceding siblings ...)
  2019-05-07 13:18 ` [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time Lukasz Majewski
@ 2019-05-08 15:56 ` Lukasz Majewski
  2019-05-09 15:58   ` Joseph Myers
  2019-05-15 14:27 ` [PATCH v5] " Lukasz Majewski
  2019-05-20 10:27 ` [PATCH v4 0/3] y2038: Linux: Provide __clock_settime64 function supporting 64 bit time Lukasz Majewski
  10 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-08 15:56 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This define indicates if the Linux kernel (5.1+) provides syscalls supporting
64 bit versions of struct timespec and timeval.

For architectures with __WORDSIZE==64 && __TIMESIZE==64 (e.g. x86_64, aarch64
this flag is never defined (as those already use 64 bit versions of struct
timespec and timeval).

The __ASSUME_TIME64_SYSCALLS shall be only defined on systems with
__WORDSIZE==32.

For x32 this flag is explicitly undefined as this architecture has
64 bit registers but only 32 bit longs and pointers. Moreover, it uses
syscalls from x86_64.

* sysdeps/unix/sysv/linux/kernel-features.h: (__ASSUME_TIME64_SYSCALLS):
[__LINUX_KERNEL_VERSION >= 0x050100]: Define.
* sysdeps/unix/sysv/linux/x86_64/kernel-features.h (__ASSUME_TIME64_SYSCALLS):
#undef the __ASSUME_TIME64_SYSCALLS for x32 architecture

---
Changes for v4:
- Exclude this patch from the clock_settime64 patch series
- Rewrite the in-code comment
- Change patch description

Changes for v3:
- Provide more detailed and verbose description
- Change name to __ASSUME_TIME64_SYSCALLS
- Undefine __ASSUME_TIME64_SYSCALLS on x32

Changes for v2:
- New patch
---
 sysdeps/unix/sysv/linux/kernel-features.h        | 38 ++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/x86_64/kernel-features.h |  9 ++++++
 2 files changed, 47 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
index bc5c959f58..30e77dd213 100644
--- a/sysdeps/unix/sysv/linux/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/kernel-features.h
@@ -143,3 +143,41 @@
    */
 
 #define __ASSUME_CLONE_DEFAULT 1
+
+#include <bits/wordsize.h>
+#if __WORDSIZE != 64
+/* Support for Linux kernel syscalls, which are able to handle 64 bit
+   time on 32 bit systems (with 'long' and __WORDSIZE equal to 32 bits).
+
+   Linux kernel, as of version 5.1, provides following set of syscalls,
+   which accept data based on struct timespec and timeval with 64 bit
+   tv_sec:
+
+   clock_gettime64
+   clock_settime64
+   clock_adjtime64
+   clock_getres_time64
+   clock_nanosleep_time64
+   timer_gettime64
+   timer_settime64
+   timerfd_gettime64
+   timerfd_settime64
+   utimensat_time64
+   pselect6_time64
+   ppoll_time64
+   io_pgetevents_time64
+   recvmmsg_time64
+   mq_timedsend_time64
+   mq_timedreceive_time64
+   semtimedop_time64
+   rt_sigtimedwait_time64
+   futex_time64
+   sched_rr_get_interval_time64
+
+   Above syscalls are supposed to replace legacy ones, which handle 32
+   bit version of struct timespec and timeval (i.e. without the '64'
+   suffix).  */
+# if __LINUX_KERNEL_VERSION >= 0x050100
+#  define __ASSUME_TIME64_SYSCALLS 1
+# endif
+#endif
diff --git a/sysdeps/unix/sysv/linux/x86_64/kernel-features.h b/sysdeps/unix/sysv/linux/x86_64/kernel-features.h
index 26280f57ec..e1e923f497 100644
--- a/sysdeps/unix/sysv/linux/x86_64/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/x86_64/kernel-features.h
@@ -24,3 +24,12 @@
 #endif
 
 #include_next <kernel-features.h>
+
+/* For x32, which is a special case in respect to 64 bit time support,
+   the __ASSUME_TIME64_SYSCALLS define needs to be explicitly undefined.
+
+   It uses Linux time related syscalls for x86_64 (in compatibility
+   mode).  */
+#ifdef __ILP32__
+# undef __ASSUME_TIME64_SYSCALLS
+#endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-08  7:51                           ` Lukasz Majewski
@ 2019-05-08 19:48                             ` Stepan Golosunov
  2019-05-09 16:12                               ` Joseph Myers
  2019-05-16  4:00                               ` Arnd Bergmann
  0 siblings, 2 replies; 111+ messages in thread
From: Stepan Golosunov @ 2019-05-08 19:48 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: Joseph Myers, libc-alpha, Arnd Bergmann, Paul Eggert

08.05.2019 в 09:51:23 +0200 Lukasz Majewski написал:
> > Usually the point of __ASSUME_* macros is to avoid compiling old
> > compatibility code when it's not needed.  That means there should be
> > no fallback to 32-bit clock_settime when __ASSUME_TIME64_SYSCALLS is
> > defined.  Even when it's defined on 32-bit arm or x86.
> > 
> > And with your current use of __ASSUME_TIME64_SYSCALLS
> > __NR_clock_settime64 won't be used on any existing architecture.
> > Because __ASSUME_TIME64_SYSCALLS won't be defined until Linux 5.0 is
> > no longer supported.
> 
> It will be used when the minimal supported kernel reaches 5.1. (now it
> is 3.2.)
> 
> For testing I do use --enable-kernel="5.1.0" passed to configure.

But __NR_clock_settime64 should be used even if minimal supported
kernel is 3.2.  If it was available in kernel headers and did not
return ENOSYS.

Otherwise glibc released, say, in 2025 still wouldn't be using
__NR_clock_settime64 on 32-bit x86 even when running on the latest
kernel.  Because minimal supported kernel version would be something
like 4.19 then.

Minimal supported kernel version, version of kernel headers used when
compiling glibc and version of kernel glibc is running on—are 3
different kernel versions normally.

What changes when minimal supported kernel becomes 5.1 is the fact
that __NR_clock_settime64 can no longer fail with ENOSYS and thus the
need for fallback to 32-bit __NR_clock_settime disappears.


You need to handle the following 4 cases:

1.  32-bit syscall should not be called (and may not even exist):
1.1.  __NR_clock_settime is 64 bit.
1.2.  __NR_clock_settime64 works in all supported kernels.

2.  __NR_clock_settime is 32-bit and __NR_clock_settime64 may be
unavailable.
2.1.  __NR_clock_settime64 is available in kernel headers, but may
fail with ENOSYS when called.  32-bit __NR_clock_settime should be
called if __NR_clock_settime64 is failing.
2.2.  __NR_clock_settime64 is not present in kernel headers.
32-bit __NR_clock_settime should be called.

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-08 10:18               ` Lukasz Majewski
@ 2019-05-09 15:46                 ` Joseph Myers
  2019-05-15 15:39                   ` Lukasz Majewski
  2019-05-31 11:37                 ` Stepan Golosunov
  1 sibling, 1 reply; 111+ messages in thread
From: Joseph Myers @ 2019-05-09 15:46 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert

On Wed, 8 May 2019, Lukasz Majewski wrote:

> The 64 bit versions of syscalls (like clock_settime64 or
> clock_gettime64) are available since 5.1 kernel (as you posted already
> the following patch: "Update syscall-names.list for Linux 5.1" .
> 
> I've now only focused on clock_settime(64) to make the discussion more
> concrete.

The following will be relevant for use of clock_gettime64, but is not 
immediately relevant for clock_settime64:

clock_gettime64 will complicate things because the present clock_gettime 
code uses the vDSO on some architectures.  Is clock_gettime64 available in 
the vDSO in 5.1 on all architectures where clock_gettime is?  If it is, 
with the same symbol version as used for existing vDSO symbols, or a 
different symbol version?  If not in the vDSO, are there any performance 
implications from using a clock_gettime64 syscall in place of a 
clock_gettime call to the vDSO?

(I think the code using the vDSO will automatically fall back to a 
corresponding syscall if the vDSO symbol isn't there, but answers to those 
questions will still be relevant for reviewing any patch for 
clock_gettime64 and understanding exactly what code paths it will use.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-08 15:56 ` [PATCH] y2038: Introduce __ASSUME_TIME64_SYSCALLS define Lukasz Majewski
@ 2019-05-09 15:58   ` Joseph Myers
  2019-05-09 16:18     ` Stepan Golosunov
  0 siblings, 1 reply; 111+ messages in thread
From: Joseph Myers @ 2019-05-09 15:58 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert

On Wed, 8 May 2019, Lukasz Majewski wrote:

> For x32 this flag is explicitly undefined as this architecture has
> 64 bit registers but only 32 bit longs and pointers. Moreover, it uses
> syscalls from x86_64.

The first sentence there is not an accurate description of the reason for 
undefining this for x32; other ILP32 configurations with 64-bit registers 
don't have this peculiarity.  "Moreover, it uses syscalls from x86_64." 
isn't a good description either; x86_64 has three syscall tables (for 
32-bit compat, x32 and the normal LP64 syscall interface).

> +   Linux kernel, as of version 5.1, provides following set of syscalls,
> +   which accept data based on struct timespec and timeval with 64 bit
> +   tv_sec:

Do any of these actually use timeval?  I thought the idea was that the new 
syscalls for 64-bit time would all use timespec, with it being the 
responsibility of libc to handle conversions to and from timeval as needed 
(e.g. for gettimeofday with _TIME_BITS=64).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-08 19:48                             ` Stepan Golosunov
@ 2019-05-09 16:12                               ` Joseph Myers
  2019-05-16  4:00                               ` Arnd Bergmann
  1 sibling, 0 replies; 111+ messages in thread
From: Joseph Myers @ 2019-05-09 16:12 UTC (permalink / raw)
  To: Stepan Golosunov; +Cc: Lukasz Majewski, libc-alpha, Arnd Bergmann, Paul Eggert

On Wed, 8 May 2019, Stepan Golosunov wrote:

> You need to handle the following 4 cases:

And, to be clear:

These cases are ones to think about when writing a patch in this area.

They are not cases that should be enumerated in comments in the code for 
any particular function, because they are completely standard for how 
these syscalls are handled across all such functions and comments in a 
function should be about things specific to that particular function - we 
don't want repetitive comments that all describe the same generic things.  
Most of this is also generic to *any* case in glibc where we have optional 
support for using a new syscall, with fallback code when the syscall can't 
be assumed to be supported.

If those general rules about optional support for new syscalls are to be 
documented anywhere in glibc, I think maint.texi would be the right place 
for such documentation.

If some function has a good reason for *not* following the generic pattern 
you described, *that* would be a case for having a comment in the function 
explaining why it's not implemented in the normal way.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-09 15:58   ` Joseph Myers
@ 2019-05-09 16:18     ` Stepan Golosunov
  0 siblings, 0 replies; 111+ messages in thread
From: Stepan Golosunov @ 2019-05-09 16:18 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Lukasz Majewski, libc-alpha, Arnd Bergmann, Paul Eggert

09.05.2019 в 15:58:38 +0000 Joseph Myers написал:
> On Wed, 8 May 2019, Lukasz Majewski wrote:
> > +   Linux kernel, as of version 5.1, provides following set of syscalls,
> > +   which accept data based on struct timespec and timeval with 64 bit
> > +   tv_sec:
> 
> Do any of these actually use timeval?  I thought the idea was that the new 
> syscalls for 64-bit time would all use timespec, with it being the 
> responsibility of libc to handle conversions to and from timeval as needed 
> (e.g. for gettimeofday with _TIME_BITS=64).

clock_adjtime uses __kernel_timex_timeval, as is explained in
https://lore.kernel.org/lkml/CAK8P3a0OBBEwU044jbe-YK2CmCnpNpUSiCA9uRo-8EwtcUva6g@mail.gmail.com/

^ permalink raw reply	[flat|nested] 111+ messages in thread

* [PATCH v5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-04-14 22:08 [PATCH 0/6] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
                   ` (8 preceding siblings ...)
  2019-05-08 15:56 ` [PATCH] y2038: Introduce __ASSUME_TIME64_SYSCALLS define Lukasz Majewski
@ 2019-05-15 14:27 ` Lukasz Majewski
  2019-05-21 15:15   ` Lukasz Majewski
  2019-05-23  7:34   ` Stepan Golosunov
  2019-05-20 10:27 ` [PATCH v4 0/3] y2038: Linux: Provide __clock_settime64 function supporting 64 bit time Lukasz Majewski
  10 siblings, 2 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-15 14:27 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This define indicates if the Linux kernel (5.1+) provides syscalls supporting
64 bit versions of struct timespec and timeval.

For architectures with __WORDSIZE==64 and __TIMESIZE==64 (e.g. x86_64, aarch64)
this flag is never defined (as those already use 64 bit versions of struct
timespec and timeval).

The __ASSUME_TIME64_SYSCALLS shall be only defined on systems with
__WORDSIZE==32.

For x32 this flag is explicitly undefined as this architecture has
__WORDSIZE==32 with __TIMESIZE==64. Despite having __WORDSIZE==32 the x32
has support for 64 bit time values and hence needs to undefine
__ASSUME_TIME64_SYSCALLS flag.


* sysdeps/unix/sysv/linux/kernel-features.h: (__ASSUME_TIME64_SYSCALLS):
[__LINUX_KERNEL_VERSION >= 0x050100]: Define.
* sysdeps/unix/sysv/linux/x86_64/kernel-features.h (__ASSUME_TIME64_SYSCALLS):
#undef the __ASSUME_TIME64_SYSCALLS for x32 architecture

---
Changes for v5:
- Rewrite the in-code comment (x32 description more precise)
- Change patch description (for x32)

Changes for v4:
- Exclude this patch from the clock_settime64 patch series
- Rewrite the in-code comment
- Change patch description

Changes for v3:
- Provide more detailed and verbose description
- Change name to __ASSUME_TIME64_SYSCALLS
- Undefine __ASSUME_TIME64_SYSCALLS on x32

Changes for v2:
- New patch
---
 sysdeps/unix/sysv/linux/kernel-features.h        | 38 ++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/x86_64/kernel-features.h |  7 +++++
 2 files changed, 45 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
index bc5c959f58..30e77dd213 100644
--- a/sysdeps/unix/sysv/linux/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/kernel-features.h
@@ -143,3 +143,41 @@
    */
 
 #define __ASSUME_CLONE_DEFAULT 1
+
+#include <bits/wordsize.h>
+#if __WORDSIZE != 64
+/* Support for Linux kernel syscalls, which are able to handle 64 bit
+   time on 32 bit systems (with 'long' and __WORDSIZE equal to 32 bits).
+
+   Linux kernel, as of version 5.1, provides following set of syscalls,
+   which accept data based on struct timespec and timeval with 64 bit
+   tv_sec:
+
+   clock_gettime64
+   clock_settime64
+   clock_adjtime64
+   clock_getres_time64
+   clock_nanosleep_time64
+   timer_gettime64
+   timer_settime64
+   timerfd_gettime64
+   timerfd_settime64
+   utimensat_time64
+   pselect6_time64
+   ppoll_time64
+   io_pgetevents_time64
+   recvmmsg_time64
+   mq_timedsend_time64
+   mq_timedreceive_time64
+   semtimedop_time64
+   rt_sigtimedwait_time64
+   futex_time64
+   sched_rr_get_interval_time64
+
+   Above syscalls are supposed to replace legacy ones, which handle 32
+   bit version of struct timespec and timeval (i.e. without the '64'
+   suffix).  */
+# if __LINUX_KERNEL_VERSION >= 0x050100
+#  define __ASSUME_TIME64_SYSCALLS 1
+# endif
+#endif
diff --git a/sysdeps/unix/sysv/linux/x86_64/kernel-features.h b/sysdeps/unix/sysv/linux/x86_64/kernel-features.h
index 26280f57ec..179a9ae932 100644
--- a/sysdeps/unix/sysv/linux/x86_64/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/x86_64/kernel-features.h
@@ -24,3 +24,10 @@
 #endif
 
 #include_next <kernel-features.h>
+
+/* For x32, which is a special case in respect to 64 bit time support
+   (it has __WORDSIZE==32 but __TIMESIZE==64), the
+   __ASSUME_TIME64_SYSCALLS flag needs to be explicitly undefined.  */
+#ifdef __ILP32__
+# undef __ASSUME_TIME64_SYSCALLS
+#endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-09 15:46                 ` Joseph Myers
@ 2019-05-15 15:39                   ` Lukasz Majewski
  2019-05-16  3:57                     ` Arnd Bergmann
  0 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-15 15:39 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha, Stepan Golosunov, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 2695 bytes --]

Hi Joseph,

> On Wed, 8 May 2019, Lukasz Majewski wrote:
> 
> > The 64 bit versions of syscalls (like clock_settime64 or
> > clock_gettime64) are available since 5.1 kernel (as you posted
> > already the following patch: "Update syscall-names.list for Linux
> > 5.1" .
> > 
> > I've now only focused on clock_settime(64) to make the discussion
> > more concrete.  
> 
> The following will be relevant for use of clock_gettime64, but is not 
> immediately relevant for clock_settime64:
> 
> clock_gettime64 will complicate things because the present
> clock_gettime code uses the vDSO on some architectures.

Yes, correct. There are vdso's(__vdso_clock_gettime and
__vdso_gettimeofday) for x64, arm, sparc to name a few.

>  Is
> clock_gettime64 available in the vDSO in 5.1 on all architectures
> where clock_gettime is? 

As fair as I can tell clock_gettime64 is not available as vdso in v5.1
Linux kernel. It is only exported to be used as a syscall.

The other issue with current vdso code (as in [1] or [2]) is that the
struct timespec's tv_sec is 'long', which would be 32 bit on 32 bit
systems (like arm).

> If it is, with the same symbol version as
> used for existing vDSO symbols, or a different symbol version?  If
> not in the vDSO, are there any performance implications from using a
> clock_gettime64 syscall in place of a clock_gettime call to the vDSO?
> 

This would need to be checked how severe is the performance regression
when one uses clock_gettime64 instead of dedicated __vdso_clock_gettime
(aliased to clock_gettime()).

It is also up to the Linux kernel community to decide if it is
acceptable to introduce vclock_gettime64.c file, which would provide
vdso for clock_gettime64.

Or maybe just convert [1], [2] to use struct timespec64 instead?

> (I think the code using the vDSO will automatically fall back to a 
> corresponding syscall if the vDSO symbol isn't there, but answers to
> those questions will still be relevant for reviewing any patch for 
> clock_gettime64 and understanding exactly what code paths it will
> use.)

Yes, correct as in [1], [2].

However, I do believe that on the beginning glibc shall support only
the syscall version of clock_gettime64 and make the switch for vdso
only when it is available from the Kernel.

> 


Note:

[1] - arch/x86/entry/vdso/vclock_gettime.c (5.1)
[2] - arch/arm/vdso/vgettimeofday.c

Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-15 15:39                   ` Lukasz Majewski
@ 2019-05-16  3:57                     ` Arnd Bergmann
  2019-05-16  6:58                       ` Lukasz Majewski
  0 siblings, 1 reply; 111+ messages in thread
From: Arnd Bergmann @ 2019-05-16  3:57 UTC (permalink / raw)
  To: Lukasz Majewski
  Cc: Joseph Myers, GNU C Library, Stepan Golosunov, Paul Eggert

On Wed, May 15, 2019 at 5:39 PM Lukasz Majewski <lukma@denx.de> wrote:
> > On Wed, 8 May 2019, Lukasz Majewski wrote:
> > If it is, with the same symbol version as
> > used for existing vDSO symbols, or a different symbol version?  If
> > not in the vDSO, are there any performance implications from using a
> > clock_gettime64 syscall in place of a clock_gettime call to the vDSO?
> >
>
> This would need to be checked how severe is the performance regression
> when one uses clock_gettime64 instead of dedicated __vdso_clock_gettime
> (aliased to clock_gettime()).
>
> It is also up to the Linux kernel community to decide if it is
> acceptable to introduce vclock_gettime64.c file, which would provide
> vdso for clock_gettime64.

The vdso code is undergoing a rewrite to use the same implementation
across all architectures, once that is complete, the added clock_gettime64
vdso support is added trivially.

We decided not to add the calls earlier since that would clash with the
rewrite, and not be easily testable across architectures.

> > (I think the code using the vDSO will automatically fall back to a
> > corresponding syscall if the vDSO symbol isn't there, but answers to
> > those questions will still be relevant for reviewing any patch for
> > clock_gettime64 and understanding exactly what code paths it will
> > use.)
>
> Yes, correct as in [1], [2].
>
> However, I do believe that on the beginning glibc shall support only
> the syscall version of clock_gettime64 and make the switch for vdso
> only when it is available from the Kernel.

I think you need to do that anyway, since not all 32-bit architectures
support a vdso at all. As I understood, all vdso support is optional,
so there is always a runtime fallback to deal with kernels lack
the vdso for some reason.

       Arnd

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-08 19:48                             ` Stepan Golosunov
  2019-05-09 16:12                               ` Joseph Myers
@ 2019-05-16  4:00                               ` Arnd Bergmann
  2019-05-16 19:54                                 ` Stepan Golosunov
  2019-05-16 19:59                                 ` Joseph Myers
  1 sibling, 2 replies; 111+ messages in thread
From: Arnd Bergmann @ 2019-05-16  4:00 UTC (permalink / raw)
  To: Stepan Golosunov
  Cc: Lukasz Majewski, Joseph Myers, GNU C Library, Paul Eggert

On Wed, May 8, 2019 at 9:48 PM Stepan Golosunov <stepan@golosunov.pp.ru> wrote:
> 08.05.2019 в 09:51:23 +0200 Lukasz Majewski написал:

> You need to handle the following 4 cases:
>
> 1.  32-bit syscall should not be called (and may not even exist):
> 1.1.  __NR_clock_settime is 64 bit.
> 1.2.  __NR_clock_settime64 works in all supported kernels.
>
> 2.  __NR_clock_settime is 32-bit and __NR_clock_settime64 may be
> unavailable.
> 2.1.  __NR_clock_settime64 is available in kernel headers, but may
> fail with ENOSYS when called.  32-bit __NR_clock_settime should be
> called if __NR_clock_settime64 is failing.
> 2.2.  __NR_clock_settime64 is not present in kernel headers.
> 32-bit __NR_clock_settime should be called.

Is there still a chance to revisit that last case? I had assumed that
glibc would have to require new kernel headers to support 64-bit
time_t since some of the macro definitions (ioctl commands,
socket options, ...) in the kernel have changed to deal with both
cases.

Building an application with 64-bit time_t using older headers is
likely to cause random problems.

       Arnd

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-16  3:57                     ` Arnd Bergmann
@ 2019-05-16  6:58                       ` Lukasz Majewski
  0 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-16  6:58 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Joseph Myers, GNU C Library, Stepan Golosunov, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 2323 bytes --]

Hi Arnd,

> On Wed, May 15, 2019 at 5:39 PM Lukasz Majewski <lukma@denx.de> wrote:
> > > On Wed, 8 May 2019, Lukasz Majewski wrote:
> > > If it is, with the same symbol version as
> > > used for existing vDSO symbols, or a different symbol version?  If
> > > not in the vDSO, are there any performance implications from
> > > using a clock_gettime64 syscall in place of a clock_gettime call
> > > to the vDSO? 
> >
> > This would need to be checked how severe is the performance
> > regression when one uses clock_gettime64 instead of dedicated
> > __vdso_clock_gettime (aliased to clock_gettime()).
> >
> > It is also up to the Linux kernel community to decide if it is
> > acceptable to introduce vclock_gettime64.c file, which would provide
> > vdso for clock_gettime64.  
> 
> The vdso code is undergoing a rewrite to use the same implementation
> across all architectures, once that is complete, the added
> clock_gettime64 vdso support is added trivially.
> 
> We decided not to add the calls earlier since that would clash with
> the rewrite, and not be easily testable across architectures.

Thanks for sharing the update.

> 
> > > (I think the code using the vDSO will automatically fall back to a
> > > corresponding syscall if the vDSO symbol isn't there, but answers
> > > to those questions will still be relevant for reviewing any patch
> > > for clock_gettime64 and understanding exactly what code paths it
> > > will use.)  
> >
> > Yes, correct as in [1], [2].
> >
> > However, I do believe that on the beginning glibc shall support only
> > the syscall version of clock_gettime64 and make the switch for vdso
> > only when it is available from the Kernel.  
> 
> I think you need to do that anyway, since not all 32-bit architectures
> support a vdso at all. As I understood, all vdso support is optional,
> so there is always a runtime fallback to deal with kernels lack
> the vdso for some reason.

Yes, correct - there is always a fallback when vsdo is not available.

> 
>        Arnd




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-16  4:00                               ` Arnd Bergmann
@ 2019-05-16 19:54                                 ` Stepan Golosunov
  2019-05-16 19:59                                 ` Joseph Myers
  1 sibling, 0 replies; 111+ messages in thread
From: Stepan Golosunov @ 2019-05-16 19:54 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Lukasz Majewski, Joseph Myers, GNU C Library, Paul Eggert

16.05.2019 в 06:00:56 +0200 Arnd Bergmann написал:
> On Wed, May 8, 2019 at 9:48 PM Stepan Golosunov <stepan@golosunov.pp.ru> wrote:
> > 08.05.2019 в 09:51:23 +0200 Lukasz Majewski написал:
> 
> > You need to handle the following 4 cases:
> >
> > 1.  32-bit syscall should not be called (and may not even exist):
> > 1.1.  __NR_clock_settime is 64 bit.
> > 1.2.  __NR_clock_settime64 works in all supported kernels.
> >
> > 2.  __NR_clock_settime is 32-bit and __NR_clock_settime64 may be
> > unavailable.
> > 2.1.  __NR_clock_settime64 is available in kernel headers, but may
> > fail with ENOSYS when called.  32-bit __NR_clock_settime should be
> > called if __NR_clock_settime64 is failing.
> > 2.2.  __NR_clock_settime64 is not present in kernel headers.
> > 32-bit __NR_clock_settime should be called.
> 
> Is there still a chance to revisit that last case? I had assumed that
> glibc would have to require new kernel headers to support 64-bit
> time_t since some of the macro definitions (ioctl commands,
> socket options, ...) in the kernel have changed to deal with both
> cases.

This is about building glibc itself, not applications that use it.
And time_t would be 32-bit in this case anyway.

> Building an application with 64-bit time_t using older headers is
> likely to cause random problems.

Then it might be a good idea to check for recent enough kernel headers
when building programs that define _TIME_BITS to 64.  (Though if those
programs use above-mentioned ioctls and socket options they will
likely need new enough kernel at runtime too.)

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-16  4:00                               ` Arnd Bergmann
  2019-05-16 19:54                                 ` Stepan Golosunov
@ 2019-05-16 19:59                                 ` Joseph Myers
  2019-05-17  7:23                                   ` Florian Weimer
  1 sibling, 1 reply; 111+ messages in thread
From: Joseph Myers @ 2019-05-16 19:59 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Stepan Golosunov, Lukasz Majewski, GNU C Library, Paul Eggert

On Thu, 16 May 2019, Arnd Bergmann wrote:

> > 2.2.  __NR_clock_settime64 is not present in kernel headers.
> > 32-bit __NR_clock_settime should be called.
> 
> Is there still a chance to revisit that last case? I had assumed that
> glibc would have to require new kernel headers to support 64-bit
> time_t since some of the macro definitions (ioctl commands,
> socket options, ...) in the kernel have changed to deal with both
> cases.

In general, we're wary of being too aggressive about requirements for 
building glibc (although the minimum kernel header version for building 
glibc may still be more recent than the minimum kernel version required by 
glibc at runtime).  If anyone building glibc on a distribution from the 
past couple of years does not need to install extra build requirements 
locally, that's convenient.

In this case, there is *no* released kernel with those __NR_* in its 
headers that is good for glibc testing, because of the fds_bits / val 
namespace issues in 5.1 (these sorts of changes are an example of exactly 
the kind of change for which the conform/ tests are most important because 
of the risk of accidentally introducing namespace issues, whether 
link-time or in the headers).  And even once some suitable kernel exists, 
it would be a while before it's ubiquitous for people building glibc.

I'd expect the only effects of allowing for not having __NR_* would 
generally be that the case where the syscalls are not assumed to be 
available at runtime also has an #ifdef on the __NR_* macro, so that if 
it's not defined it falls straight through into exactly the same fallback 
code as if the syscall had failed with ENOSYS.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-16 19:59                                 ` Joseph Myers
@ 2019-05-17  7:23                                   ` Florian Weimer
  2019-05-17  8:34                                     ` Arnd Bergmann
  0 siblings, 1 reply; 111+ messages in thread
From: Florian Weimer @ 2019-05-17  7:23 UTC (permalink / raw)
  To: Joseph Myers
  Cc: Arnd Bergmann, Stepan Golosunov, Lukasz Majewski, GNU C Library,
	Paul Eggert

* Joseph Myers:

> I'd expect the only effects of allowing for not having __NR_* would 
> generally be that the case where the syscalls are not assumed to be 
> available at runtime also has an #ifdef on the __NR_* macro, so that if 
> it's not defined it falls straight through into exactly the same fallback 
> code as if the syscall had failed with ENOSYS.

An alternative would be to ship all the system call constants in the
glibc source tree (and check that they match the installed kernel header
sources if available there).

Thanks,
Florian

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-17  7:23                                   ` Florian Weimer
@ 2019-05-17  8:34                                     ` Arnd Bergmann
  0 siblings, 0 replies; 111+ messages in thread
From: Arnd Bergmann @ 2019-05-17  8:34 UTC (permalink / raw)
  To: Florian Weimer
  Cc: Joseph Myers, Stepan Golosunov, Lukasz Majewski, GNU C Library,
	Paul Eggert

On Fri, May 17, 2019 at 9:23 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * Joseph Myers:
>
> > I'd expect the only effects of allowing for not having __NR_* would
> > generally be that the case where the syscalls are not assumed to be
> > available at runtime also has an #ifdef on the __NR_* macro, so that if
> > it's not defined it falls straight through into exactly the same fallback
> > code as if the syscall had failed with ENOSYS.
>
> An alternative would be to ship all the system call constants in the
> glibc source tree (and check that they match the installed kernel header
> sources if available there).

To clarify: I was not asking about the __NR_* constants, as those don't
ever change, and using older headers will not cause incorrect behavior
but just invoke the fallback.

The two classes of problems I'm interested in are:

- constants that depend on 'sizeof(time_t)', e.g. SO_TIMESTAMP
- structures that used time_t instead of a fixed-length type in older
  headers, e.g. 'struct input_event'

We have a number of those, and in each case, using the old
kernel headers will lead to an ABI mismatch between the application
and the kernel.

       Arnd

^ permalink raw reply	[flat|nested] 111+ messages in thread

* [PATCH v4 0/3] y2038: Linux: Provide __clock_settime64 function supporting 64 bit time
  2019-04-14 22:08 [PATCH 0/6] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
                   ` (9 preceding siblings ...)
  2019-05-15 14:27 ` [PATCH v5] " Lukasz Majewski
@ 2019-05-20 10:27 ` Lukasz Majewski
  2019-05-20 10:27   ` [PATCH v4 1/3] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
                     ` (2 more replies)
  10 siblings, 3 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-20 10:27 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This patch set introduces the conversion of __clock_settime to explicit
64 bit struct __timespec64 arguments. As a result this function is now
Y2038 safe.

To achieve the above goal - new, internal to glibc,
struct __timespec64 has been also introduced as well as
helper functions to handle time conversions on systems with
__TIMESIZE != 64.

The code from this patch set uses the new clock_settime64 syscall
from Linux kernel (5.1+).

This work is (loosely) based on a previous development/patches:
https://libc-alpha.sourceware.narkive.com/zniMOWui/rfc-patch-00-52-make-glibc-y2038-proof#post68

Github branch (including the y2038 conversion example):
https://github.com/lmajewski/y2038_glibc/commits/Y2038-2.29-glibc-__clock-internal-struct-timespec-v4

Those patches have been applied on top of master branch:
SHA1: 1f50f2ad854c84ead522bfc7331b46dbe6057d53

Shall be used with provided meta-y2038 for development and testing:
https://github.com/lmajewski/meta-y2038

I've used guidelines from:
https://www.gnu.org/software/libc/manual/html_mono/libc.html
"D.2.1 64-bit time symbol handling in the GNU C Library"
to convert *clock_settime*.

and most notably from:
https://sourceware.org/glibc/wiki/Y2038ProofnessDesign#clock_gettime.28.29

Dependency:
The patch adding __ASSUME_TIME64_SYSCALLS define:
"y2038: Introduce __ASSUME_TIME64_SYSCALLS define"
https://patchwork.ozlabs.org/patch/1100097/

Feedback and comments are more than welcome.

Lukasz Majewski (3):
  y2038: Introduce internal for glibc struct __timespec64
  y2038: Provide conversion helpers for struct __timespec64
  y2038: linux: Provide __clock_settime64 implementation

 include/time.h                          | 118 ++++++++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/clock_settime.c |  38 +++++++++-
 2 files changed, 153 insertions(+), 3 deletions(-)

-- 
2.11.0


^ permalink raw reply	[flat|nested] 111+ messages in thread

* [PATCH v4 1/3] y2038: Introduce internal for glibc struct __timespec64
  2019-05-20 10:27 ` [PATCH v4 0/3] y2038: Linux: Provide __clock_settime64 function supporting 64 bit time Lukasz Majewski
@ 2019-05-20 10:27   ` Lukasz Majewski
  2019-05-20 10:27   ` [PATCH v4 2/3] y2038: Provide conversion helpers for " Lukasz Majewski
  2019-05-20 10:27   ` [PATCH v4 3/3] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
  2 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-20 10:27 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This type is a glibc's type similar to struct timespec
but whose tv_sec field is a __time64_t rather than a time_t,
which makes it Y2038-proof and usable to pass between user
code and Y2038-proof kernel syscalls (e.g. clock_gettime()).

To support passing this structure to the kernel - the tv_pad,
32 bit int, has been introduced. The placement of it depends on
endianness of the SoC.

Tested on x86_64 and ARM.

* include/time.h: Add struct __timespec64 definition

---
Changes for v4:
- Change tv_pad's type from named bitfield to 32 bit int

Changes for v3:
- Replace __TIMESIZE with __WORDSIZE (as architectures with __TIMESIZE==64
  will need to use this struct with 32 bit tv_nsec field).
- Update in-code comment

Changes for v2:
- None
---
 include/time.h | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/include/time.h b/include/time.h
index ac3163c2a5..7dabb7a568 100644
--- a/include/time.h
+++ b/include/time.h
@@ -5,6 +5,7 @@
 # include <bits/types/locale_t.h>
 # include <stdbool.h>
 # include <time/mktime-internal.h>
+# include <endian.h>
 
 extern __typeof (strftime_l) __strftime_l;
 libc_hidden_proto (__strftime_l)
@@ -51,6 +52,30 @@ extern void __tzset_parse_tz (const char *tz) attribute_hidden;
 extern void __tz_compute (__time64_t timer, struct tm *tm, int use_localtime)
   __THROW attribute_hidden;
 
+#if __WORDSIZE == 64
+# define __timespec64 timespec
+#else
+/* The glibc Y2038-proof struct __timespec64 structure for a time value.
+   To keep things Posix-ish, we keep the nanoseconds field a 32-bit
+   signed long, but since the Linux field is a 64-bit signed int, we
+   pad our tv_nsec with a 32-bit int.
+
+   As a general rule the Linux kernel is ignoring upper 32 bits of
+   tv_nsec field. However, there are architectures with potential need
+   for clearing the padding (i.e. 'x32').  */
+struct __timespec64
+{
+  __time64_t tv_sec;         /* Seconds */
+# if BYTE_ORDER == BIG_ENDIAN
+  __int32_t tv_pad;          /* Padding */
+  __int32_t tv_nsec;         /* Nanoseconds */
+# else
+  __int32_t tv_nsec;         /* Nanoseconds */
+  __int32_t tv_pad;          /* Padding */
+# endif
+};
+#endif
+
 #if __TIMESIZE == 64
 # define __ctime64 ctime
 #else
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH v4 2/3] y2038: Provide conversion helpers for struct __timespec64
  2019-05-20 10:27 ` [PATCH v4 0/3] y2038: Linux: Provide __clock_settime64 function supporting 64 bit time Lukasz Majewski
  2019-05-20 10:27   ` [PATCH v4 1/3] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
@ 2019-05-20 10:27   ` Lukasz Majewski
  2019-05-20 10:27   ` [PATCH v4 3/3] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
  2 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-20 10:27 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

Those functions allow easy conversion between Y2038 safe struct
__timespec64 and other time related data structures (like struct timeval).

Moreover, those functions are NOT compiled when 64 bit time support is
enabled (__TIMESIZE == 64) and are used only for 32 bit wrappers (like
e.g. __clock_settime).

* include/time.h (valid_timeval_to_timespec64): Add.
* include/time.h (valid_timespec_to_timespec64): Likewise.
* include/time.h (valid_timespec64_to_timespec): Likewise.
* include/time.h (valid_timespec64_to_timeval): Likewise.
* include/time.h (IS_VALID_NANOSECONDS): Likewise.
* include/time.h (timespec_to_timespec64): Likewise.
* include/time.h (timespec64_to_timespec): Likewise.
* include/time.h (timespec64_to_timeval): Likewise.

---
Changes for v4:
- Remove misleading comments regarding clearing tv_pad values during
  conversion (as Linux kernel on its own ignores upper 32 bits of tv_nsec).

Changes for v3:
- Remove timespec64_clear_padding function - as kernel ignores upper 32
  bits of tv_nsec when passed via syscall to the Linux kernel

Changes for v2:
- Add timespec64_clear_padding function
---
 include/time.h | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)

diff --git a/include/time.h b/include/time.h
index 7dabb7a568..6ca4911235 100644
--- a/include/time.h
+++ b/include/time.h
@@ -181,5 +181,90 @@ in_time_t_range (__time64_t t)
   return s == t;
 }
 
+# if __TIMESIZE != 64
+/* Convert a known valid struct timeval into a struct __timespec64.  */
+static inline void
+valid_timeval_to_timespec64 (const struct timeval *tv32,
+			     struct __timespec64 *ts64)
+{
+  ts64->tv_sec = tv32->tv_sec;
+  ts64->tv_nsec = tv32->tv_usec * 1000;
+}
+
+/* Convert a known valid struct timespec into a struct __timespec64.  */
+static inline void
+valid_timespec_to_timespec64 (const struct timespec *ts32,
+			      struct __timespec64 *ts64)
+{
+  ts64->tv_sec = ts32->tv_sec;
+  ts64->tv_nsec = ts32->tv_nsec;
+}
+
+/* Convert a known valid struct __timespec64 into a struct timespec.  */
+static inline void
+valid_timespec64_to_timespec (const struct __timespec64 *ts64,
+			      struct timespec *ts32)
+{
+  ts32->tv_sec = (time_t) ts64->tv_sec;
+  ts32->tv_nsec = ts64->tv_nsec;
+}
+
+/* Convert a known valid struct __timespec64 into a struct timeval.  */
+static inline void
+valid_timespec64_to_timeval (const struct __timespec64 *ts64,
+			     struct timeval *tv32)
+{
+  tv32->tv_sec = (time_t) ts64->tv_sec;
+  tv32->tv_usec = ts64->tv_nsec / 1000;
+}
+
+/* Check if a value lies with the valid nanoseconds range.  */
+#define IS_VALID_NANOSECONDS(ns) ((ns) >= 0 && (ns) <= 999999999)
+
+/* Check and convert a struct timespec into a struct __timespec64.  */
+static inline bool
+timespec_to_timespec64 (const struct timespec *ts32,
+                        struct __timespec64 *ts64)
+{
+  /* Check that ts32 holds a valid count of nanoseconds.  */
+  if (! IS_VALID_NANOSECONDS (ts32->tv_nsec))
+    return false;
+  /* All ts32 fields can fit in ts64, so copy them.  */
+  valid_timespec_to_timespec64 (ts32, ts64);
+  return true;
+}
+
+/* Check and convert a struct __timespec64 into a struct timespec.  */
+static inline bool
+timespec64_to_timespec (const struct __timespec64 *ts64,
+                        struct timespec *ts32)
+{
+  /* Check that tv_nsec holds a valid count of nanoseconds.  */
+  if (! IS_VALID_NANOSECONDS (ts64->tv_nsec))
+    return false;
+  /* Check that tv_sec can fit in a __time_t.  */
+  if (! in_time_t_range (ts64->tv_sec))
+    return false;
+  /* All ts64 fields can fit in ts32, so copy them.  */
+  valid_timespec64_to_timespec (ts64, ts32);
+  return true;
+}
+
+/* Check and convert a struct __timespec64 into a struct timeval.  */
+static inline bool
+timespec64_to_timeval (const struct __timespec64 *ts64,
+                       struct timeval *tv32)
+{
+  /* Check that tv_nsec holds a valid count of nanoseconds.  */
+  if (! IS_VALID_NANOSECONDS (ts64->tv_nsec))
+    return false;
+  /* Check that tv_sec can fit in a __time_t.  */
+  if (! in_time_t_range (ts64->tv_sec))
+    return false;
+  /* All ts64 fields can fit in tv32, so copy them.  */
+  valid_timespec64_to_timeval (ts64, tv32);
+  return true;
+}
+# endif
 #endif
 #endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* [PATCH v4 3/3] y2038: linux: Provide __clock_settime64 implementation
  2019-05-20 10:27 ` [PATCH v4 0/3] y2038: Linux: Provide __clock_settime64 function supporting 64 bit time Lukasz Majewski
  2019-05-20 10:27   ` [PATCH v4 1/3] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
  2019-05-20 10:27   ` [PATCH v4 2/3] y2038: Provide conversion helpers for " Lukasz Majewski
@ 2019-05-20 10:27   ` Lukasz Majewski
  2019-05-23  7:08     ` Stepan Golosunov
  2 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-20 10:27 UTC (permalink / raw)
  To: libc-alpha
  Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers,
	Lukasz Majewski

This patch provides new __clock_settime64 explicit 64 bit function for
setting the time. Moreover, a 32 bit version - __clock_settime - has been
refactored to internally use __clock_settime64.

The __clock_settime is now supposed to be used on systems still supporting
32 bit time (__TIMESIZE != 64) - hence the necessary checks and conversion
to 64 bit struct timespec.
After this change it is intrinsically Y2038 safe.

The new clock_settime64 syscall available from Linux
5.1+ has been used, when applicable, on systems supporting ILP32 data
model.

The __ASSUME_TIME64_SYSCALLS flag indicates if the Linux kernel supports
64 bit version of clock_settime (i.e. clock_settime64).
For systems with __TIMESIZE != 64 as well as ones not supporting this call
(returning -ENOSYS) the fall back code, which supports 32 bit kernel
syscalls ABI (hence the check for __SYSCALL_WORDSIZE to exclude 'x32'), is
executed.

When working on 32 bit systems without Y2038 time support the clock_settime
returns error when one wants to set time with wrong (overflowed) tv_sec
value. Moreover, the correctness of tv_nsec is checked.

In this patch the internal padding (tv_pad) of struct __timespec64 is
left untouched (on 32 bit systems) as Linux kernel ignores upper 32 bits
of tv_nsec.

The execution path on 64 bit systems has not been changed or affected in
any way.

Tests:
- The code has been tested with x86_64/x86 (native compilation):
make PARALLELMFLAGS="-j8" && make xcheck PARALLELMFLAGS="-j8"

- Run specific tests on ARM/x86 32bit systems (qemu):
https://github.com/lmajewski/meta-y2038
and run tests:
https://github.com/lmajewski/y2038-tests/commits/master
on kernels with and without 64 bit time support.

No regressions were observed.

* include/time.h (__clock_settime64):
  Add __clock_settime alias according to __TIMESIZE define
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime):
  Refactor this function to be used only on 32 bit machines as a wrapper
  on __clock_settime64.
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime64): Add
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime64):
  Use clock_settime64 kernel syscall (available from 5.1-rc1+ Linux) by
  32 bit Y2038 safe systems

---
Changes for v4:
- __ASSUME_TIME64_SYSCALLS for fall back path
- Use __SYSCALL_WORDSIZE to exclude 'x32' from execution path (so it will
  use x86_64 syscall
- Rewrite the commit message

Changes for v3:
- Rename __ASSUME_64BIT_TIME to __ASSUME_TIME64_SYSCALLS
- Refactor in-code comment (add information regarding Linux kernel ignorance
  of padding
- Do not use __TIMESIZE to select main execution path (for Y2038 systems
  __TIMESIZE would be changed from 32 to 64 bits at some point to indicate
  full Y2038 support

Changes for v2:
- Add support for __ASSUME_64BIT_TIME flag when Linux kernel provides syscalls
  supporting 64 bit time on 32 bit systems
- Provide fallback to 32 bit version of clock_settime when clock_settime64
  is not available
- Do not copy *tp to timespec - this seems like an overkill as in clock_settime()
  the 32 bit struct timespec is copied to internal 64 bit struct __timespec64
---
 include/time.h                          |  8 +++++++
 sysdeps/unix/sysv/linux/clock_settime.c | 38 ++++++++++++++++++++++++++++++---
 2 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/include/time.h b/include/time.h
index 6ca4911235..88413d8031 100644
--- a/include/time.h
+++ b/include/time.h
@@ -127,6 +127,14 @@ extern __time64_t __timegm64 (struct tm *__tp) __THROW;
 libc_hidden_proto (__timegm64)
 #endif
 
+#if __TIMESIZE == 64
+# define __clock_settime64 __clock_settime
+#else
+extern int __clock_settime64 (clockid_t clock_id,
+                              const struct __timespec64 *tp);
+libc_hidden_proto (__clock_settime64)
+#endif
+
 /* Compute the `struct tm' representation of T,
    offset OFFSET seconds east of UTC,
    and store year, yday, mon, mday, wday, hour, min, sec into *TP.
diff --git a/sysdeps/unix/sysv/linux/clock_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c
index d837e3019c..19559d1e76 100644
--- a/sysdeps/unix/sysv/linux/clock_settime.c
+++ b/sysdeps/unix/sysv/linux/clock_settime.c
@@ -19,11 +19,9 @@
 #include <sysdep.h>
 #include <time.h>
 
-#include "kernel-posix-cpu-timers.h"
-
 /* Set CLOCK to value TP.  */
 int
-__clock_settime (clockid_t clock_id, const struct timespec *tp)
+__clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
 {
   /* Make sure the time cvalue is OK.  */
   if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
@@ -32,6 +30,40 @@ __clock_settime (clockid_t clock_id, const struct timespec *tp)
       return -1;
     }
 
+#if __WORDSIZE == 32
+# ifdef __NR_clock_settime64
+  int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
+#  ifdef __ASSUME_TIME64_SYSCALLS
+  return ret;
+#  else
+  if (ret == 0 || errno != ENOSYS)
+    return ret;
+#  endif
+# endif
+  /* Fall back to syscall supporting 32bit struct timespec.  */
+# if (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE != 64)
+  struct timespec ts32;
+  valid_timespec64_to_timespec (tp, &ts32);
+  return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);
+# endif
+#endif
   return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp);
 }
 weak_alias (__clock_settime, clock_settime)
+
+#if __TIMESIZE != 64
+int
+__clock_settime (clockid_t clock_id, const struct timespec *tp)
+{
+  struct __timespec64 ts64;
+
+  if (! in_time_t_range (tp->tv_sec))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  valid_timespec_to_timespec64 (tp, &ts64);
+  return __clock_settime64 (clock_id, &ts64);
+}
+#endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 111+ messages in thread

* Re: [PATCH v5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-15 14:27 ` [PATCH v5] " Lukasz Majewski
@ 2019-05-21 15:15   ` Lukasz Majewski
  2019-05-23  7:34   ` Stepan Golosunov
  1 sibling, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-21 15:15 UTC (permalink / raw)
  To: libc-alpha; +Cc: Stepan Golosunov, Arnd Bergmann, Paul Eggert, Joseph Myers

[-- Attachment #1: Type: text/plain, Size: 4097 bytes --]

Dear All,

> This define indicates if the Linux kernel (5.1+) provides syscalls
> supporting 64 bit versions of struct timespec and timeval.
> 
> For architectures with __WORDSIZE==64 and __TIMESIZE==64 (e.g.
> x86_64, aarch64) this flag is never defined (as those already use 64
> bit versions of struct timespec and timeval).
> 
> The __ASSUME_TIME64_SYSCALLS shall be only defined on systems with
> __WORDSIZE==32.
> 
> For x32 this flag is explicitly undefined as this architecture has
> __WORDSIZE==32 with __TIMESIZE==64. Despite having __WORDSIZE==32 the
> x32 has support for 64 bit time values and hence needs to undefine
> __ASSUME_TIME64_SYSCALLS flag.
> 
> 
> * sysdeps/unix/sysv/linux/kernel-features.h:
> (__ASSUME_TIME64_SYSCALLS): [__LINUX_KERNEL_VERSION >= 0x050100]:
> Define.
> * sysdeps/unix/sysv/linux/x86_64/kernel-features.h
> (__ASSUME_TIME64_SYSCALLS): #undef the __ASSUME_TIME64_SYSCALLS for
> x32 architecture

Gentle ping on this patch. Do you have any more comments?

> 
> ---
> Changes for v5:
> - Rewrite the in-code comment (x32 description more precise)
> - Change patch description (for x32)
> 
> Changes for v4:
> - Exclude this patch from the clock_settime64 patch series
> - Rewrite the in-code comment
> - Change patch description
> 
> Changes for v3:
> - Provide more detailed and verbose description
> - Change name to __ASSUME_TIME64_SYSCALLS
> - Undefine __ASSUME_TIME64_SYSCALLS on x32
> 
> Changes for v2:
> - New patch
> ---
>  sysdeps/unix/sysv/linux/kernel-features.h        | 38
> ++++++++++++++++++++++++
> sysdeps/unix/sysv/linux/x86_64/kernel-features.h |  7 +++++ 2 files
> changed, 45 insertions(+)
> 
> diff --git a/sysdeps/unix/sysv/linux/kernel-features.h
> b/sysdeps/unix/sysv/linux/kernel-features.h index
> bc5c959f58..30e77dd213 100644 ---
> a/sysdeps/unix/sysv/linux/kernel-features.h +++
> b/sysdeps/unix/sysv/linux/kernel-features.h @@ -143,3 +143,41 @@
>     */
>  
>  #define __ASSUME_CLONE_DEFAULT 1
> +
> +#include <bits/wordsize.h>
> +#if __WORDSIZE != 64
> +/* Support for Linux kernel syscalls, which are able to handle 64 bit
> +   time on 32 bit systems (with 'long' and __WORDSIZE equal to 32
> bits). +
> +   Linux kernel, as of version 5.1, provides following set of
> syscalls,
> +   which accept data based on struct timespec and timeval with 64 bit
> +   tv_sec:
> +
> +   clock_gettime64
> +   clock_settime64
> +   clock_adjtime64
> +   clock_getres_time64
> +   clock_nanosleep_time64
> +   timer_gettime64
> +   timer_settime64
> +   timerfd_gettime64
> +   timerfd_settime64
> +   utimensat_time64
> +   pselect6_time64
> +   ppoll_time64
> +   io_pgetevents_time64
> +   recvmmsg_time64
> +   mq_timedsend_time64
> +   mq_timedreceive_time64
> +   semtimedop_time64
> +   rt_sigtimedwait_time64
> +   futex_time64
> +   sched_rr_get_interval_time64
> +
> +   Above syscalls are supposed to replace legacy ones, which handle
> 32
> +   bit version of struct timespec and timeval (i.e. without the '64'
> +   suffix).  */
> +# if __LINUX_KERNEL_VERSION >= 0x050100
> +#  define __ASSUME_TIME64_SYSCALLS 1
> +# endif
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/x86_64/kernel-features.h
> b/sysdeps/unix/sysv/linux/x86_64/kernel-features.h index
> 26280f57ec..179a9ae932 100644 ---
> a/sysdeps/unix/sysv/linux/x86_64/kernel-features.h +++
> b/sysdeps/unix/sysv/linux/x86_64/kernel-features.h @@ -24,3 +24,10 @@
>  #endif
>  
>  #include_next <kernel-features.h>
> +
> +/* For x32, which is a special case in respect to 64 bit time support
> +   (it has __WORDSIZE==32 but __TIMESIZE==64), the
> +   __ASSUME_TIME64_SYSCALLS flag needs to be explicitly undefined.
> */ +#ifdef __ILP32__
> +# undef __ASSUME_TIME64_SYSCALLS
> +#endif




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v4 3/3] y2038: linux: Provide __clock_settime64 implementation
  2019-05-20 10:27   ` [PATCH v4 3/3] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
@ 2019-05-23  7:08     ` Stepan Golosunov
  2019-05-23  9:28       ` Lukasz Majewski
  0 siblings, 1 reply; 111+ messages in thread
From: Stepan Golosunov @ 2019-05-23  7:08 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: libc-alpha, Arnd Bergmann, Paul Eggert, Joseph Myers

20.05.2019 в 12:27:23 +0200 Lukasz Majewski написал:
>  /* Set CLOCK to value TP.  */
>  int
> -__clock_settime (clockid_t clock_id, const struct timespec *tp)
> +__clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
>  {
>    /* Make sure the time cvalue is OK.  */
>    if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
> @@ -32,6 +30,40 @@ __clock_settime (clockid_t clock_id, const struct timespec *tp)
>        return -1;
>      }
>  
> +#if __WORDSIZE == 32
> +# ifdef __NR_clock_settime64
> +  int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
> +#  ifdef __ASSUME_TIME64_SYSCALLS
> +  return ret;
> +#  else
> +  if (ret == 0 || errno != ENOSYS)
> +    return ret;
> +#  endif
> +# endif
> +  /* Fall back to syscall supporting 32bit struct timespec.  */
> +# if (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE != 64)
> +  struct timespec ts32;
> +  valid_timespec64_to_timespec (tp, &ts32);
> +  return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);
> +# endif
> +#endif
>    return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp);
>  }

This still uses __NR_clock_settime even if __ASSUME_TIME64_SYSCALLS is
defined.  This won't even compile on newer 32-bit architectures where
__NR_clock_settime is not defined.  valid_timespec64_to_timespec
won't exist in these cases too.

And in_time_t_range check is missing for the fallback case.

>  weak_alias (__clock_settime, clock_settime)
> +
> +#if __TIMESIZE != 64
> +int
> +__clock_settime (clockid_t clock_id, const struct timespec *tp)
> +{
> +  struct __timespec64 ts64;
> +
> +  if (! in_time_t_range (tp->tv_sec))
> +    {
> +      __set_errno (EOVERFLOW);
> +      return -1;
> +    }

What is this if (false) { … } statement doing here?

> +
> +  valid_timespec_to_timespec64 (tp, &ts64);
> +  return __clock_settime64 (clock_id, &ts64);
> +}
> +#endif

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-15 14:27 ` [PATCH v5] " Lukasz Majewski
  2019-05-21 15:15   ` Lukasz Majewski
@ 2019-05-23  7:34   ` Stepan Golosunov
  2019-05-23  9:35     ` Lukasz Majewski
  2019-05-23 21:17     ` Joseph Myers
  1 sibling, 2 replies; 111+ messages in thread
From: Stepan Golosunov @ 2019-05-23  7:34 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: libc-alpha, Arnd Bergmann, Paul Eggert, Joseph Myers

15.05.2019 в 16:27:23 +0200 Lukasz Majewski написал:
> This define indicates if the Linux kernel (5.1+) provides syscalls supporting
> 64 bit versions of struct timespec and timeval.
> 
> For architectures with __WORDSIZE==64 and __TIMESIZE==64 (e.g. x86_64, aarch64)
> this flag is never defined (as those already use 64 bit versions of struct
> timespec and timeval).
> 
> The __ASSUME_TIME64_SYSCALLS shall be only defined on systems with
> __WORDSIZE==32.
> 
> For x32 this flag is explicitly undefined as this architecture has
> __WORDSIZE==32 with __TIMESIZE==64. Despite having __WORDSIZE==32 the x32
> has support for 64 bit time values and hence needs to undefine
> __ASSUME_TIME64_SYSCALLS flag.

What is not clear is how architectures where syscalls like
clock_settime are already using 64-bit time_t are supposed to be
identified.  Last patch for clock_settime seems to be using

#if __WORDSIZE != 32 || !defined __NR_clock_settime64 && defined __SYSCALL_WORDSIZE && __SYSCALL_WORDSIZE == 64

to select code for these architectures.

This seems too complicated and potentially buggy.  Why not just
define __ASSUME_TIME64_SYSCALLS for this case too and then use

#if defined __ASSUME_TIME64_SYSCALLS && !defined __NR_clock_settime64

?

Especially given that in most cases the only difference in resulting
code with __ASSUME_TIME64_SYSCALLS defined would be the name of the
constant used (__NR_clock_settime64 when it's defined,
__NR_clock_settime otherwise).

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v4 3/3] y2038: linux: Provide __clock_settime64 implementation
  2019-05-23  7:08     ` Stepan Golosunov
@ 2019-05-23  9:28       ` Lukasz Majewski
  0 siblings, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-23  9:28 UTC (permalink / raw)
  To: Stepan Golosunov; +Cc: libc-alpha, Arnd Bergmann, Paul Eggert, Joseph Myers

[-- Attachment #1: Type: text/plain, Size: 3473 bytes --]

Hi Stepan,

First of all - thank you for your reply.

> 20.05.2019 в 12:27:23 +0200 Lukasz Majewski написал:
> >  /* Set CLOCK to value TP.  */
> >  int
> > -__clock_settime (clockid_t clock_id, const struct timespec *tp)
> > +__clock_settime64 (clockid_t clock_id, const struct __timespec64
> > *tp) {
> >    /* Make sure the time cvalue is OK.  */
> >    if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
> > @@ -32,6 +30,40 @@ __clock_settime (clockid_t clock_id, const
> > struct timespec *tp) return -1;
> >      }
> >  
> > +#if __WORDSIZE == 32
> > +# ifdef __NR_clock_settime64
> > +  int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
> > +#  ifdef __ASSUME_TIME64_SYSCALLS
> > +  return ret;
> > +#  else
> > +  if (ret == 0 || errno != ENOSYS)
> > +    return ret;
> > +#  endif
> > +# endif
> > +  /* Fall back to syscall supporting 32bit struct timespec.  */
> > +# if (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE != 64)
> > +  struct timespec ts32;
> > +  valid_timespec64_to_timespec (tp, &ts32);
> > +  return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);
> > +# endif
> > +#endif
> >    return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp);
              ^^^^^ - [1]

> >  }  
> 
> This still uses __NR_clock_settime even if __ASSUME_TIME64_SYSCALLS is
> defined.  This won't even compile on newer 32-bit architectures where
> __NR_clock_settime is not defined.  valid_timespec64_to_timespec
> won't exist in these cases too.

Ach... I see your point. The issue would be when we switch to
__TIMESIZE == 64 for 32 bit systems. For that reason the "conversion
functions" from patch [2] shall be compiled always (no matter if we
have __TIMESIZE == 64 or == 32).

And some explanation - the
if (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE != 64) is to
prevent running the fallback on 'x32' - it shall execute on [1]
execution path.


> 
> And in_time_t_range check is missing for the fallback case.

Yes - I shall move the in_time_t_range() check from __clock_settime to
the fallback.

Last but not least - the [1] shall be executed only when __WORDSIZE !=
64 - the #else is missing

> 
> >  weak_alias (__clock_settime, clock_settime)
> > +
> > +#if __TIMESIZE != 64
> > +int
> > +__clock_settime (clockid_t clock_id, const struct timespec *tp)
> > +{
> > +  struct __timespec64 ts64;
> > +
> > +  if (! in_time_t_range (tp->tv_sec))
> > +    {
> > +      __set_errno (EOVERFLOW);
> > +      return -1;
> > +    }  
> 
> What is this if (false) { … } statement doing here?

Ok, the __clock_settime would receive as an argument the timespec with
32 bit tv_nsec, and tv_sec - hence this check shall be moved from there
to the fallback of __clock_settime64.


Considering the above changes - the code starts to look too much
convoluted. Hence, I would opt for the approach presented in the
__ASSUME_TIME64_SYSCALLS patch reply.


> 
> > +
> > +  valid_timespec_to_timespec64 (tp, &ts64);
> > +  return __clock_settime64 (clock_id, &ts64);
> > +}
> > +#endif  


Note:

[2] - [PATCH v4 2/3] y2038: Provide conversion helpers for struct
__timespec64




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-23  7:34   ` Stepan Golosunov
@ 2019-05-23  9:35     ` Lukasz Majewski
  2019-05-25 16:19       ` Lukasz Majewski
  2019-05-25 19:45       ` Stepan Golosunov
  2019-05-23 21:17     ` Joseph Myers
  1 sibling, 2 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-23  9:35 UTC (permalink / raw)
  To: Stepan Golosunov; +Cc: libc-alpha, Arnd Bergmann, Paul Eggert, Joseph Myers

[-- Attachment #1: Type: text/plain, Size: 3341 bytes --]

Hi Stepan,

> 15.05.2019 в 16:27:23 +0200 Lukasz Majewski написал:
> > This define indicates if the Linux kernel (5.1+) provides syscalls
> > supporting 64 bit versions of struct timespec and timeval.
> > 
> > For architectures with __WORDSIZE==64 and __TIMESIZE==64 (e.g.
> > x86_64, aarch64) this flag is never defined (as those already use
> > 64 bit versions of struct timespec and timeval).
> > 
> > The __ASSUME_TIME64_SYSCALLS shall be only defined on systems with
> > __WORDSIZE==32.
> > 
> > For x32 this flag is explicitly undefined as this architecture has
> > __WORDSIZE==32 with __TIMESIZE==64. Despite having __WORDSIZE==32
> > the x32 has support for 64 bit time values and hence needs to
> > undefine __ASSUME_TIME64_SYSCALLS flag.  
> 
> What is not clear is how architectures where syscalls like
> clock_settime are already using 64-bit time_t are supposed to be
> identified.  Last patch for clock_settime seems to be using
> 
> #if __WORDSIZE != 32 || !defined __NR_clock_settime64 && defined
> __SYSCALL_WORDSIZE && __SYSCALL_WORDSIZE == 64
> 

The check has been taken from:
sysdeps/unix/sysv/linux/bits/statvfs.h (line 24).


Considering your above comment - we would need to introduce two
flags:

1. New, glibc global - __ARCH_HAVE_TIME64_SYSCALLS (other names
possible: __ARCH_SUPPORT_TIME64_SYSCALLS, __ARCH_TIME64_SUPPORT)

#if (__WORDSIZE == 32 \
     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
#define __ARCH_HAVE_TIME64_SYSCALLS
#endif

2. __ASSUME_TIME64_SYSCALLS as it is in this patch (to indicate
kernel support after 5.1+).


The __clock_settime64() pseudo code:

...
tv_nsec check
...

#if __ARCH_HAVE_TIME64_SYSCALLS
# ifdef __NR_clock_settime64
  int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
#  ifdef __ASSUME_TIME64_SYSCALLS
  return ret;
#  else
  if (ret == 0 || errno != ENOSYS)
    return ret;
#  endif
# endif
  if (! in_time_t_range (tp->tv_sec))
    {
      __set_errno (EOVERFLOW);
      return -1;
    }  
  struct timespec ts32;
  valid_timespec64_to_timespec (tp, &ts32);
  return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);
#else
  /* x32, x86_64 */
  return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp);
#endif

> to select code for these architectures.
> 
> This seems too complicated and potentially buggy.  Why not just
> define __ASSUME_TIME64_SYSCALLS for this case too and then use
> 
> #if defined __ASSUME_TIME64_SYSCALLS && !defined __NR_clock_settime64
> 

As fair as I understood the __ASSUME_TIME64_SYSCALLS was supposed to
indicate in-kernel support for syscalls (similar to __ASSUME_STATX) -
which would result in simpler execution paths. 

> ?
> 
> Especially given that in most cases the only difference in resulting
> code with __ASSUME_TIME64_SYSCALLS defined would be the name of the
> constant used (__NR_clock_settime64 when it's defined,
> __NR_clock_settime otherwise).

And also the case where __clock_settime64() is called from
__clock_settime().


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-23  7:34   ` Stepan Golosunov
  2019-05-23  9:35     ` Lukasz Majewski
@ 2019-05-23 21:17     ` Joseph Myers
  1 sibling, 0 replies; 111+ messages in thread
From: Joseph Myers @ 2019-05-23 21:17 UTC (permalink / raw)
  To: Stepan Golosunov; +Cc: Lukasz Majewski, libc-alpha, Arnd Bergmann, Paul Eggert

On Thu, 23 May 2019, Stepan Golosunov wrote:

> This seems too complicated and potentially buggy.  Why not just
> define __ASSUME_TIME64_SYSCALLS for this case too and then use

There are multiple reasonable choices that could be made for the semantics 
of __ASSUME_TIME64_SYSCALLS.

One is the choice in this patch series at present, that it relates to the 
new syscalls *with their given names*.  Another possible choice would be 
the one you suggest, that it relates to *any syscalls whose semantics 
match those of the new syscalls, possibly under different names*.

If we use the latter choice, I think it would be best also to have 
#defines of the new to the old names (such as #define __NR_clock_settime64 
__NR_clock_settime) so the various places that use 
__ASSUME_TIME64_SYSCALLS don't all need their own conditionals.

Also, if we use the latter choice, we need to be very careful about 
ensuring the old syscalls really do have the right semantics, and really 
do exist on all kernels with at least the configured minimum version.  For 
example, we must not claim that semtimedop_time64 is available simply 
because a platform's syscall interface always had 64-bit time, if there 
wasn't an equivalent older syscall, or the equivalent older syscall had 
different semantics or was introduced more recently than the minimum 
kernel version for that glibc build.  This might well mean defining the 
macro to relate to a smaller set of syscalls for which this property can 
be more readily verified.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-23  9:35     ` Lukasz Majewski
@ 2019-05-25 16:19       ` Lukasz Majewski
  2019-05-25 19:45       ` Stepan Golosunov
  1 sibling, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-25 16:19 UTC (permalink / raw)
  To: Stepan Golosunov; +Cc: libc-alpha, Arnd Bergmann, Paul Eggert, Joseph Myers

[-- Attachment #1: Type: text/plain, Size: 4111 bytes --]

Dear Stepan, Joseph,

> Hi Stepan,
> 
> > 15.05.2019 в 16:27:23 +0200 Lukasz Majewski написал:  
> > > This define indicates if the Linux kernel (5.1+) provides syscalls
> > > supporting 64 bit versions of struct timespec and timeval.
> > > 
> > > For architectures with __WORDSIZE==64 and __TIMESIZE==64 (e.g.
> > > x86_64, aarch64) this flag is never defined (as those already use
> > > 64 bit versions of struct timespec and timeval).
> > > 
> > > The __ASSUME_TIME64_SYSCALLS shall be only defined on systems with
> > > __WORDSIZE==32.
> > > 
> > > For x32 this flag is explicitly undefined as this architecture has
> > > __WORDSIZE==32 with __TIMESIZE==64. Despite having __WORDSIZE==32
> > > the x32 has support for 64 bit time values and hence needs to
> > > undefine __ASSUME_TIME64_SYSCALLS flag.    
> > 
> > What is not clear is how architectures where syscalls like
> > clock_settime are already using 64-bit time_t are supposed to be
> > identified.  Last patch for clock_settime seems to be using
> > 
> > #if __WORDSIZE != 32 || !defined __NR_clock_settime64 && defined
> > __SYSCALL_WORDSIZE && __SYSCALL_WORDSIZE == 64
> >   
> 
> The check has been taken from:
> sysdeps/unix/sysv/linux/bits/statvfs.h (line 24).
> 
> 
> Considering your above comment - we would need to introduce two
> flags:
> 
> 1. New, glibc global - __ARCH_HAVE_TIME64_SYSCALLS (other names
> possible: __ARCH_SUPPORT_TIME64_SYSCALLS, __ARCH_TIME64_SUPPORT)
> 
> #if (__WORDSIZE == 32 \
>      && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
> #define __ARCH_HAVE_TIME64_SYSCALLS
> #endif

I would provide more verbose description of course, but in short the
__ARCH_HAVE_TIME64_SYSCALLS would indicate all the archs (with
__WORDSIZE == 32) which would have a chance to have support for 64 bit
time.

> 
> 2. __ASSUME_TIME64_SYSCALLS as it is in this patch (to indicate
> kernel support after 5.1+).
> 
> 
> The __clock_settime64() pseudo code:
> 
> ...
> tv_nsec check
> ...
> 
> #if __ARCH_HAVE_TIME64_SYSCALLS
> # ifdef __NR_clock_settime64
>   int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
> #  ifdef __ASSUME_TIME64_SYSCALLS
>   return ret;
> #  else
>   if (ret == 0 || errno != ENOSYS)
>     return ret;
> #  endif
> # endif
>   if (! in_time_t_range (tp->tv_sec))
>     {
>       __set_errno (EOVERFLOW);
>       return -1;
>     }  
>   struct timespec ts32;
>   valid_timespec64_to_timespec (tp, &ts32);
>   return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);
> #else
>   /* x32, x86_64 */
>   return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp);
> #endif

What do you think about this idea?

> 
> > to select code for these architectures.
> > 
> > This seems too complicated and potentially buggy.  Why not just
> > define __ASSUME_TIME64_SYSCALLS for this case too and then use
> > 
> > #if defined __ASSUME_TIME64_SYSCALLS && !defined
> > __NR_clock_settime64 
> 
> As fair as I understood the __ASSUME_TIME64_SYSCALLS was supposed to
> indicate in-kernel support for syscalls (similar to __ASSUME_STATX) -
> which would result in simpler execution paths. 
> 
> > ?
> > 
> > Especially given that in most cases the only difference in resulting
> > code with __ASSUME_TIME64_SYSCALLS defined would be the name of the
> > constant used (__NR_clock_settime64 when it's defined,
> > __NR_clock_settime otherwise).  
> 
> And also the case where __clock_settime64() is called from
> __clock_settime().
> 
> 
> Best regards,
> 
> Lukasz Majewski
> 
> --
> 
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email:
> lukma@denx.de




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-23  9:35     ` Lukasz Majewski
  2019-05-25 16:19       ` Lukasz Majewski
@ 2019-05-25 19:45       ` Stepan Golosunov
  2019-05-26 12:39         ` Lukasz Majewski
  2019-05-28 19:47         ` Joseph Myers
  1 sibling, 2 replies; 111+ messages in thread
From: Stepan Golosunov @ 2019-05-25 19:45 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: libc-alpha, Arnd Bergmann, Paul Eggert, Joseph Myers

23.05.2019 в 11:35:30 +0200 Lukasz Majewski написал:
> Hi Stepan,
> 
> > 15.05.2019 в 16:27:23 +0200 Lukasz Majewski написал:
> > > This define indicates if the Linux kernel (5.1+) provides syscalls
> > > supporting 64 bit versions of struct timespec and timeval.
> > > 
> > > For architectures with __WORDSIZE==64 and __TIMESIZE==64 (e.g.
> > > x86_64, aarch64) this flag is never defined (as those already use
> > > 64 bit versions of struct timespec and timeval).
> > > 
> > > The __ASSUME_TIME64_SYSCALLS shall be only defined on systems with
> > > __WORDSIZE==32.
> > > 
> > > For x32 this flag is explicitly undefined as this architecture has
> > > __WORDSIZE==32 with __TIMESIZE==64. Despite having __WORDSIZE==32
> > > the x32 has support for 64 bit time values and hence needs to
> > > undefine __ASSUME_TIME64_SYSCALLS flag.  
> > 
> > What is not clear is how architectures where syscalls like
> > clock_settime are already using 64-bit time_t are supposed to be
> > identified.  Last patch for clock_settime seems to be using
> > 
> > #if __WORDSIZE != 32 || !defined __NR_clock_settime64 && defined
> > __SYSCALL_WORDSIZE && __SYSCALL_WORDSIZE == 64
> > 
> 
> The check has been taken from:
> sysdeps/unix/sysv/linux/bits/statvfs.h (line 24).
> 
> 
> Considering your above comment - we would need to introduce two
> flags:
> 
> 1. New, glibc global - __ARCH_HAVE_TIME64_SYSCALLS (other names
> possible: __ARCH_SUPPORT_TIME64_SYSCALLS, __ARCH_TIME64_SUPPORT)
> 
> #if (__WORDSIZE == 32 \
>      && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
> #define __ARCH_HAVE_TIME64_SYSCALLS
> #endif
> 
> 2. __ASSUME_TIME64_SYSCALLS as it is in this patch (to indicate
> kernel support after 5.1+).
> 
> 
> The __clock_settime64() pseudo code:
> 
> ...
> tv_nsec check
> ...
> 
> #if __ARCH_HAVE_TIME64_SYSCALLS
> # ifdef __NR_clock_settime64
>   int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
> #  ifdef __ASSUME_TIME64_SYSCALLS
>   return ret;
> #  else
>   if (ret == 0 || errno != ENOSYS)
>     return ret;
> #  endif
> # endif

>   if (! in_time_t_range (tp->tv_sec))
>     {
>       __set_errno (EOVERFLOW);
>       return -1;
>     }  
>   struct timespec ts32;
>   valid_timespec64_to_timespec (tp, &ts32);
>   return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);

This part needs to be guarded by
#ifndef __ASSUME_TIME64_SYSCALLS

Not only it would be unreacheable when __ASSUME_TIME64_SYSCALLS is
defined, but also
INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32)
won't be compilable on some architectures.
__NR_clock_settime does not exist on new 32-bit architectures.

> #else
>   /* x32, x86_64 */
>   return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp);
> #endif
> 
> > to select code for these architectures.
> > 
> > This seems too complicated and potentially buggy.  Why not just
> > define __ASSUME_TIME64_SYSCALLS for this case too and then use
> > 
> > #if defined __ASSUME_TIME64_SYSCALLS && !defined __NR_clock_settime64
> > 
> 
> As fair as I understood the __ASSUME_TIME64_SYSCALLS was supposed to
> indicate in-kernel support for syscalls (similar to __ASSUME_STATX) -
> which would result in simpler execution paths.

I proposed that __ASSUME_TIME64_SYSCALLS means what __ASSUME_* usually
mean: fallback (to old syscalls with 32-bit time) is not needed and
must not be compiled.

Which should be equivalent to: either the 20 time64 syscalls are
always available or traditional kernel interfaces for the same
functionality are already using 64-bit time_t.

It also allows to have simple answer to question on which syscalls
should be used.  When __ASSUME_TIME64_SYSCALLS is not defined both new
time64 and traditional syscall with 32-bit time_t should be tried.
When __ASSUME_TIME64_SYSCALLS is defined then new time64 syscall
should be used if it exists in kernel headers and traditional syscalls
(they would have 64-bit time_t) should be used otherwise.

In most cases code can look like this:

#ifdef __ASSUME_TIME64_SYSCALLS
#ifndef __NR_clock_settime64
#define __NR_clock_settime64 __NR_clock_settime
#endif
INLINE_SYSCALL_CALL (clock_settime64, …)
#else
try clock_settime64, if that fails (whether compiletime or runtime)
convert data to 32-bit, call clock_settime
#endif

(Yes, for semtimedop it won't be that simple.  Because traditional
syscall isn't semtimedop in some cases.  This also assumes that the
20 time64 syscall names won't suddenly be added to kernel headers for
64-bit ABIs.)



Defining __ASSUME_TIME64_SYSCALLS to mean "20 time64 syscalls are
guaranteed to be present at compile and runtime" and
__ARCH_HAVE_TIME64_SYSCALLS to mean "20 time64 syscalls are providing
the 64-bit time_t syscalls" would also work. But then:

1. Names like __ARCH_HAVE_* are currently not used in glibc.
2. It's easy to confuse __ASSUME_TIME64_SYSCALLS with
   __ARCH_HAVE_TIME64_SYSCALLS.
3. Code would probably be more complicated.
4. Care should be taken that __ASSUME_TIME64_SYSCALLS is not checked
   when __ARCH_HAVE_TIME64_SYSCALLS is not defined.  So that
   __ASSUME_TIME64_SYSCALLS can be easily removed when glibc will
   cease to support pre-5.1 kernels.
5. If 4. is done then defining __ASSUME_TIME64_SYSCALLS on 64-bit
   architectures and x32 won't break anything.  Then when pre-5.1
   kernels are no longer supported __ASSUME_TIME64_SYSCALLS will be
   defined unconditionally and its removal will be trivial.


> > ?
> > 
> > Especially given that in most cases the only difference in resulting
> > code with __ASSUME_TIME64_SYSCALLS defined would be the name of the
> > constant used (__NR_clock_settime64 when it's defined,
> > __NR_clock_settime otherwise).
> 
> And also the case where __clock_settime64() is called from
> __clock_settime().

That part is supposed to be guarded by __TIMESIZE and is not related
to __ASSUME_TIME64_SYSCALLS.

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-25 19:45       ` Stepan Golosunov
@ 2019-05-26 12:39         ` Lukasz Majewski
  2019-05-28 16:00           ` Lukasz Majewski
  2019-05-28 19:53           ` Joseph Myers
  2019-05-28 19:47         ` Joseph Myers
  1 sibling, 2 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-26 12:39 UTC (permalink / raw)
  To: Stepan Golosunov, Joseph Myers; +Cc: libc-alpha, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 8982 bytes --]

Hi Stepan, Joseph,

Thank you for your input.

> 23.05.2019 в 11:35:30 +0200 Lukasz Majewski написал:
> > Hi Stepan,
> >   
> > > 15.05.2019 в 16:27:23 +0200 Lukasz Majewski написал:  
> > > > This define indicates if the Linux kernel (5.1+) provides
> > > > syscalls supporting 64 bit versions of struct timespec and
> > > > timeval.
> > > > 
> > > > For architectures with __WORDSIZE==64 and __TIMESIZE==64 (e.g.
> > > > x86_64, aarch64) this flag is never defined (as those already
> > > > use 64 bit versions of struct timespec and timeval).
> > > > 
> > > > The __ASSUME_TIME64_SYSCALLS shall be only defined on systems
> > > > with __WORDSIZE==32.
> > > > 
> > > > For x32 this flag is explicitly undefined as this architecture
> > > > has __WORDSIZE==32 with __TIMESIZE==64. Despite having
> > > > __WORDSIZE==32 the x32 has support for 64 bit time values and
> > > > hence needs to undefine __ASSUME_TIME64_SYSCALLS flag.    
> > > 
> > > What is not clear is how architectures where syscalls like
> > > clock_settime are already using 64-bit time_t are supposed to be
> > > identified.  Last patch for clock_settime seems to be using
> > > 
> > > #if __WORDSIZE != 32 || !defined __NR_clock_settime64 && defined
> > > __SYSCALL_WORDSIZE && __SYSCALL_WORDSIZE == 64
> > >   
> > 
> > The check has been taken from:
> > sysdeps/unix/sysv/linux/bits/statvfs.h (line 24).
> > 
> > 
> > Considering your above comment - we would need to introduce two
> > flags:
> > 
> > 1. New, glibc global - __ARCH_HAVE_TIME64_SYSCALLS (other names
> > possible: __ARCH_SUPPORT_TIME64_SYSCALLS, __ARCH_TIME64_SUPPORT)
> > 
> > #if (__WORDSIZE == 32 \
> >      && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
> > #define __ARCH_HAVE_TIME64_SYSCALLS
> > #endif
> > 
> > 2. __ASSUME_TIME64_SYSCALLS as it is in this patch (to indicate
> > kernel support after 5.1+).
> > 
> > 
> > The __clock_settime64() pseudo code:
> > 
> > ...
> > tv_nsec check
> > ...
> > 
> > #if __ARCH_HAVE_TIME64_SYSCALLS
> > # ifdef __NR_clock_settime64
> >   int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
> > #  ifdef __ASSUME_TIME64_SYSCALLS
> >   return ret;
> > #  else
> >   if (ret == 0 || errno != ENOSYS)
> >     return ret;
> > #  endif
> > # endif  
> 
> >   if (! in_time_t_range (tp->tv_sec))
> >     {
> >       __set_errno (EOVERFLOW);
> >       return -1;
> >     }  
> >   struct timespec ts32;
> >   valid_timespec64_to_timespec (tp, &ts32);
> >   return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);  
> 
> This part needs to be guarded by
> #ifndef __ASSUME_TIME64_SYSCALLS
> 
> Not only it would be unreacheable when __ASSUME_TIME64_SYSCALLS is
> defined, but also
> INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32)
> won't be compilable on some architectures.
> __NR_clock_settime does not exist on new 32-bit architectures.

The above code path is added for two use cases:

1. The fallback on systems where both __NR_clock_settime and
__NR_clock_settime64 are defined, but for some reason the call to
latter syscall is not supported (by having older kernel than headers
used for glibc compilation).

2. The __TIMESIZE != 64 execution patch for 32 bit systems (the glibc
configuration to not support Y2038 time).

However, I do prefer the described below solution.

> 
> > #else
> >   /* x32, x86_64 */
> >   return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp);
> > #endif
> >   
> > > to select code for these architectures.
> > > 
> > > This seems too complicated and potentially buggy.  Why not just
> > > define __ASSUME_TIME64_SYSCALLS for this case too and then use
> > > 
> > > #if defined __ASSUME_TIME64_SYSCALLS && !defined
> > > __NR_clock_settime64 
> > 
> > As fair as I understood the __ASSUME_TIME64_SYSCALLS was supposed to
> > indicate in-kernel support for syscalls (similar to __ASSUME_STATX)
> > - which would result in simpler execution paths.  
> 
> I proposed that __ASSUME_TIME64_SYSCALLS means what __ASSUME_* usually
> mean: fallback (to old syscalls with 32-bit time) is not needed and
> must not be compiled.
> 
> Which should be equivalent to: either the 20 time64 syscalls are
> always available or traditional kernel interfaces for the same
> functionality are already using 64-bit time_t.
> 

Shall the __ASSUME_TIME64_SYSCALLS be defined as:
(@ sysdeps/unix/sysv/linux/kernel-features.h):

#if __WORDSIZE == 32
# if __LINUX_KERNEL_VERSION >= 0x050100
#  define __ASSUME_TIME64_SYSCALLS 1
# endif
#endif

And also for __TIMESIZE==64
(@ include/time.h)

#if __TIMESIZE==64
# define __ASSUME_TIME64_SYSCALLS 1
#endif



Then the code would be (it is easier for me to understand the
execution paths when providing the pseudo code):

__clock_settime64(....)
{
...

#ifdef __ASSUME_TIME64_SYSCALLS
#  ifndef __NR_clock_settime64
#    define __NR_clock_settime64 __NR_clock_settime [1]
#  endif
  INLINE_SYSCALL_CALL (clock_settime64, …) [2]
#else [3]
  int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
  if (ret == 0 || errno != ENOSYS)
	return ret;
  struct timespec ts32;
  valid_timespec64_to_timespec (tp, &ts32);
  return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);	
#endif

}


Notes:
======

[1] - x32/x86_64 - The __NR_clock_settime64 is NOT defined. The syscall
itself is called in [2].

[1] - arm32 - linux kernel headers (used for glibc build) are not
providing the __NR_clock_settime64 for some reason.

[3] - systems with old headers or kernel. Also fallback code when
__TIMESIZE != 64 and the __clock_settime64() is called from
clock_settime() on legacy, non 64 bit time supporting systems.

> It also allows to have simple answer to question on which syscalls
> should be used.  When __ASSUME_TIME64_SYSCALLS is not defined both new
> time64 and traditional syscall with 32-bit time_t should be tried.
> When __ASSUME_TIME64_SYSCALLS is defined then new time64 syscall
> should be used if it exists in kernel headers and traditional syscalls
> (they would have 64-bit time_t) should be used otherwise.
> 
> In most cases code can look like this:
> 
> #ifdef __ASSUME_TIME64_SYSCALLS
> #ifndef __NR_clock_settime64
> #define __NR_clock_settime64 __NR_clock_settime
> #endif
> INLINE_SYSCALL_CALL (clock_settime64, …)
> #else
> try clock_settime64, if that fails (whether compiletime or runtime)
> convert data to 32-bit, call clock_settime
> #endif
> 
> (Yes, for semtimedop it won't be that simple.  Because traditional
> syscall isn't semtimedop in some cases.  This also assumes that the
> 20 time64 syscall names won't suddenly be added to kernel headers for
> 64-bit ABIs.)
> 
> 
> 
> Defining __ASSUME_TIME64_SYSCALLS to mean "20 time64 syscalls are
> guaranteed to be present at compile and runtime" and
> __ARCH_HAVE_TIME64_SYSCALLS to mean "20 time64 syscalls are providing
> the 64-bit time_t syscalls" would also work. But then:
> 
> 1. Names like __ARCH_HAVE_* are currently not used in glibc.
> 2. It's easy to confuse __ASSUME_TIME64_SYSCALLS with
>    __ARCH_HAVE_TIME64_SYSCALLS.
> 3. Code would probably be more complicated.
> 4. Care should be taken that __ASSUME_TIME64_SYSCALLS is not checked
>    when __ARCH_HAVE_TIME64_SYSCALLS is not defined.  So that
>    __ASSUME_TIME64_SYSCALLS can be easily removed when glibc will
>    cease to support pre-5.1 kernels.
> 5. If 4. is done then defining __ASSUME_TIME64_SYSCALLS on 64-bit
>    architectures and x32 won't break anything.  Then when pre-5.1
>    kernels are no longer supported __ASSUME_TIME64_SYSCALLS will be
>    defined unconditionally and its removal will be trivial.
> 

I think that your approach with __ASSUME_TIME64_SYSCALLS meaning:
"either the 20 time64 syscalls are always available or traditional
kernel interfaces for the same functionality are already using 64-bit
time_t." is better and shall be used as it provides more concise code.

Please correct me if I made a mistake in the above pseudo code and the
__ASSUME_TIME64_SYSCALLS definition itself. I've tried to "implement"
your idea.

> 
> > > ?
> > > 
> > > Especially given that in most cases the only difference in
> > > resulting code with __ASSUME_TIME64_SYSCALLS defined would be the
> > > name of the constant used (__NR_clock_settime64 when it's defined,
> > > __NR_clock_settime otherwise).  
> > 
> > And also the case where __clock_settime64() is called from
> > __clock_settime().  
> 
> That part is supposed to be guarded by __TIMESIZE and is not related
> to __ASSUME_TIME64_SYSCALLS.

Ok.


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-26 12:39         ` Lukasz Majewski
@ 2019-05-28 16:00           ` Lukasz Majewski
  2019-05-28 19:53           ` Joseph Myers
  1 sibling, 0 replies; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-28 16:00 UTC (permalink / raw)
  To: Stepan Golosunov, Joseph Myers; +Cc: libc-alpha, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 9924 bytes --]

Hi Stepan, Joseph,

> Hi Stepan, Joseph,
> 
> Thank you for your input.
> 
> > 23.05.2019 в 11:35:30 +0200 Lukasz Majewski написал:  
> > > Hi Stepan,
> > >     
> > > > 15.05.2019 в 16:27:23 +0200 Lukasz Majewski написал:    
> > > > > This define indicates if the Linux kernel (5.1+) provides
> > > > > syscalls supporting 64 bit versions of struct timespec and
> > > > > timeval.
> > > > > 
> > > > > For architectures with __WORDSIZE==64 and __TIMESIZE==64 (e.g.
> > > > > x86_64, aarch64) this flag is never defined (as those already
> > > > > use 64 bit versions of struct timespec and timeval).
> > > > > 
> > > > > The __ASSUME_TIME64_SYSCALLS shall be only defined on systems
> > > > > with __WORDSIZE==32.
> > > > > 
> > > > > For x32 this flag is explicitly undefined as this architecture
> > > > > has __WORDSIZE==32 with __TIMESIZE==64. Despite having
> > > > > __WORDSIZE==32 the x32 has support for 64 bit time values and
> > > > > hence needs to undefine __ASSUME_TIME64_SYSCALLS flag.      
> > > > 
> > > > What is not clear is how architectures where syscalls like
> > > > clock_settime are already using 64-bit time_t are supposed to be
> > > > identified.  Last patch for clock_settime seems to be using
> > > > 
> > > > #if __WORDSIZE != 32 || !defined __NR_clock_settime64 && defined
> > > > __SYSCALL_WORDSIZE && __SYSCALL_WORDSIZE == 64
> > > >     
> > > 
> > > The check has been taken from:
> > > sysdeps/unix/sysv/linux/bits/statvfs.h (line 24).
> > > 
> > > 
> > > Considering your above comment - we would need to introduce two
> > > flags:
> > > 
> > > 1. New, glibc global - __ARCH_HAVE_TIME64_SYSCALLS (other names
> > > possible: __ARCH_SUPPORT_TIME64_SYSCALLS, __ARCH_TIME64_SUPPORT)
> > > 
> > > #if (__WORDSIZE == 32 \
> > >      && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
> > > #define __ARCH_HAVE_TIME64_SYSCALLS
> > > #endif
> > > 
> > > 2. __ASSUME_TIME64_SYSCALLS as it is in this patch (to indicate
> > > kernel support after 5.1+).
> > > 
> > > 
> > > The __clock_settime64() pseudo code:
> > > 
> > > ...
> > > tv_nsec check
> > > ...
> > > 
> > > #if __ARCH_HAVE_TIME64_SYSCALLS
> > > # ifdef __NR_clock_settime64
> > >   int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
> > > #  ifdef __ASSUME_TIME64_SYSCALLS
> > >   return ret;
> > > #  else
> > >   if (ret == 0 || errno != ENOSYS)
> > >     return ret;
> > > #  endif
> > > # endif    
> >   
> > >   if (! in_time_t_range (tp->tv_sec))
> > >     {
> > >       __set_errno (EOVERFLOW);
> > >       return -1;
> > >     }  
> > >   struct timespec ts32;
> > >   valid_timespec64_to_timespec (tp, &ts32);
> > >   return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);    
> > 
> > This part needs to be guarded by
> > #ifndef __ASSUME_TIME64_SYSCALLS
> > 
> > Not only it would be unreacheable when __ASSUME_TIME64_SYSCALLS is
> > defined, but also
> > INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32)
> > won't be compilable on some architectures.
> > __NR_clock_settime does not exist on new 32-bit architectures.  
> 
> The above code path is added for two use cases:
> 
> 1. The fallback on systems where both __NR_clock_settime and
> __NR_clock_settime64 are defined, but for some reason the call to
> latter syscall is not supported (by having older kernel than headers
> used for glibc compilation).
> 
> 2. The __TIMESIZE != 64 execution patch for 32 bit systems (the glibc
> configuration to not support Y2038 time).
> 
> However, I do prefer the described below solution.
> 
> >   
> > > #else
> > >   /* x32, x86_64 */
> > >   return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp);
> > > #endif
> > >     
> > > > to select code for these architectures.
> > > > 
> > > > This seems too complicated and potentially buggy.  Why not just
> > > > define __ASSUME_TIME64_SYSCALLS for this case too and then use
> > > > 
> > > > #if defined __ASSUME_TIME64_SYSCALLS && !defined
> > > > __NR_clock_settime64   
> > > 
> > > As fair as I understood the __ASSUME_TIME64_SYSCALLS was supposed
> > > to indicate in-kernel support for syscalls (similar to
> > > __ASSUME_STATX)
> > > - which would result in simpler execution paths.    
> > 
> > I proposed that __ASSUME_TIME64_SYSCALLS means what __ASSUME_*
> > usually mean: fallback (to old syscalls with 32-bit time) is not
> > needed and must not be compiled.
> > 
> > Which should be equivalent to: either the 20 time64 syscalls are
> > always available or traditional kernel interfaces for the same
> > functionality are already using 64-bit time_t.
> >   
> 
> Shall the __ASSUME_TIME64_SYSCALLS be defined as:
> (@ sysdeps/unix/sysv/linux/kernel-features.h):
> 
> #if __WORDSIZE == 32
> # if __LINUX_KERNEL_VERSION >= 0x050100
> #  define __ASSUME_TIME64_SYSCALLS 1
> # endif
> #endif
> 
> And also for __TIMESIZE==64
> (@ include/time.h)
> 
> #if __TIMESIZE==64
> # define __ASSUME_TIME64_SYSCALLS 1
> #endif
> 
> 
> 
> Then the code would be (it is easier for me to understand the
> execution paths when providing the pseudo code):
> 
> __clock_settime64(....)
> {
> ...
> 
> #ifdef __ASSUME_TIME64_SYSCALLS
> #  ifndef __NR_clock_settime64
> #    define __NR_clock_settime64 __NR_clock_settime [1]
> #  endif
>   INLINE_SYSCALL_CALL (clock_settime64, …) [2]
> #else [3]
>   int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
>   if (ret == 0 || errno != ENOSYS)
> 	return ret;
>   struct timespec ts32;
>   valid_timespec64_to_timespec (tp, &ts32);
>   return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);	
> #endif
> 
> }
> 
> 
> Notes:
> ======
> 
> [1] - x32/x86_64 - The __NR_clock_settime64 is NOT defined. The
> syscall itself is called in [2].
> 
> [1] - arm32 - linux kernel headers (used for glibc build) are not
> providing the __NR_clock_settime64 for some reason.
> 
> [3] - systems with old headers or kernel. Also fallback code when
> __TIMESIZE != 64 and the __clock_settime64() is called from
> clock_settime() on legacy, non 64 bit time supporting systems.
> 
> > It also allows to have simple answer to question on which syscalls
> > should be used.  When __ASSUME_TIME64_SYSCALLS is not defined both
> > new time64 and traditional syscall with 32-bit time_t should be
> > tried. When __ASSUME_TIME64_SYSCALLS is defined then new time64
> > syscall should be used if it exists in kernel headers and
> > traditional syscalls (they would have 64-bit time_t) should be used
> > otherwise.
> > 
> > In most cases code can look like this:
> > 
> > #ifdef __ASSUME_TIME64_SYSCALLS
> > #ifndef __NR_clock_settime64
> > #define __NR_clock_settime64 __NR_clock_settime
> > #endif
> > INLINE_SYSCALL_CALL (clock_settime64, …)
> > #else
> > try clock_settime64, if that fails (whether compiletime or runtime)
> > convert data to 32-bit, call clock_settime
> > #endif
> > 
> > (Yes, for semtimedop it won't be that simple.  Because traditional
> > syscall isn't semtimedop in some cases.  This also assumes that the
> > 20 time64 syscall names won't suddenly be added to kernel headers
> > for 64-bit ABIs.)
> > 
> > 
> > 
> > Defining __ASSUME_TIME64_SYSCALLS to mean "20 time64 syscalls are
> > guaranteed to be present at compile and runtime" and
> > __ARCH_HAVE_TIME64_SYSCALLS to mean "20 time64 syscalls are
> > providing the 64-bit time_t syscalls" would also work. But then:
> > 
> > 1. Names like __ARCH_HAVE_* are currently not used in glibc.
> > 2. It's easy to confuse __ASSUME_TIME64_SYSCALLS with
> >    __ARCH_HAVE_TIME64_SYSCALLS.
> > 3. Code would probably be more complicated.
> > 4. Care should be taken that __ASSUME_TIME64_SYSCALLS is not checked
> >    when __ARCH_HAVE_TIME64_SYSCALLS is not defined.  So that
> >    __ASSUME_TIME64_SYSCALLS can be easily removed when glibc will
> >    cease to support pre-5.1 kernels.
> > 5. If 4. is done then defining __ASSUME_TIME64_SYSCALLS on 64-bit
> >    architectures and x32 won't break anything.  Then when pre-5.1
> >    kernels are no longer supported __ASSUME_TIME64_SYSCALLS will be
> >    defined unconditionally and its removal will be trivial.
> >   
> 
> I think that your approach with __ASSUME_TIME64_SYSCALLS meaning:
> "either the 20 time64 syscalls are always available or traditional
> kernel interfaces for the same functionality are already using 64-bit
> time_t." is better and shall be used as it provides more concise code.
> 
> Please correct me if I made a mistake in the above pseudo code and the
> __ASSUME_TIME64_SYSCALLS definition itself. I've tried to "implement"
> your idea.
> 
> >   
> > > > ?
> > > > 
> > > > Especially given that in most cases the only difference in
> > > > resulting code with __ASSUME_TIME64_SYSCALLS defined would be
> > > > the name of the constant used (__NR_clock_settime64 when it's
> > > > defined, __NR_clock_settime otherwise).    
> > > 
> > > And also the case where __clock_settime64() is called from
> > > __clock_settime().    
> > 
> > That part is supposed to be guarded by __TIMESIZE and is not related
> > to __ASSUME_TIME64_SYSCALLS.  
> 
> Ok.
> 

Could you share your thoughts regarding the above idea?
Thanks in advance.

> 
> Best regards,
> 
> Lukasz Majewski
> 
> --
> 
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email:
> lukma@denx.de




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-25 19:45       ` Stepan Golosunov
  2019-05-26 12:39         ` Lukasz Majewski
@ 2019-05-28 19:47         ` Joseph Myers
  2019-05-28 22:09           ` Lukasz Majewski
  1 sibling, 1 reply; 111+ messages in thread
From: Joseph Myers @ 2019-05-28 19:47 UTC (permalink / raw)
  To: Stepan Golosunov; +Cc: Lukasz Majewski, libc-alpha, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 1534 bytes --]

On Sat, 25 May 2019, Stepan Golosunov wrote:

> In most cases code can look like this:
> 
> #ifdef __ASSUME_TIME64_SYSCALLS
> #ifndef __NR_clock_settime64
> #define __NR_clock_settime64 __NR_clock_settime
> #endif
> INLINE_SYSCALL_CALL (clock_settime64, …)
> #else
> try clock_settime64, if that fails (whether compiletime or runtime)
> convert data to 32-bit, call clock_settime
> #endif
> 
> (Yes, for semtimedop it won't be that simple.  Because traditional
> syscall isn't semtimedop in some cases.  This also assumes that the

If we follow this approach, it would be reasonable to say that 
__ASSUME_TIME64_SYSCALLS is *only* for those syscalls where the old 
syscall, on platforms that had 64-bit time in their syscall interface all 
along, is exactly equivalent (and to list that subset) - not for 
semtimedop.  Then there could be a separate __ASSUME_SEMTIMEDOP_TIME64.

> 20 time64 syscall names won't suddenly be added to kernel headers for
> 64-bit ABIs.)

Rather, that they won't be added *with new syscall numbers*.  If the 
kernel adds them as macro aliases for the old syscall numbers, code like 
that would work just fine.  If the kernel adds them as new syscall 
numbers, the definition of __ASSUME_TIME64_SYSCALLS (that assumes it can 
always be true for existing 64-bit syscall ABIs) would suddenly become 
wrong when using new kernel headers, because it would result in glibc code 
using new syscall numbers without regard to a possibly older runtime 
kernel version.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-26 12:39         ` Lukasz Majewski
  2019-05-28 16:00           ` Lukasz Majewski
@ 2019-05-28 19:53           ` Joseph Myers
  2019-05-28 22:46             ` Lukasz Majewski
  1 sibling, 1 reply; 111+ messages in thread
From: Joseph Myers @ 2019-05-28 19:53 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: Stepan Golosunov, libc-alpha, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 2098 bytes --]

On Sun, 26 May 2019, Lukasz Majewski wrote:

> Shall the __ASSUME_TIME64_SYSCALLS be defined as:
> (@ sysdeps/unix/sysv/linux/kernel-features.h):
> 
> #if __WORDSIZE == 32
> # if __LINUX_KERNEL_VERSION >= 0x050100
> #  define __ASSUME_TIME64_SYSCALLS 1
> # endif
> #endif
> 
> And also for __TIMESIZE==64
> (@ include/time.h)
> 
> #if __TIMESIZE==64
> # define __ASSUME_TIME64_SYSCALLS 1
> #endif

__ASSUME_* should *only* be defined in kernel-features.h.  A definition in 
include/* would be incorrect.

It's not clear to me that __TIMESIZE == 64 would be the right condition 
(in kernel-features.h) for defining __ASSUME_TIME64_SYSCALLS independent 
of kernel version, because it would get wrong the case of 32-bit 
architectures with old kernel support and glibc support added in future 
with 64-bit time only (if we decide that any such future glibc port should 
use only 64-bit time in userspace, but without also requiring a new kernel 
for such a port).  Rather, __WORDSIZE == 64 (with a special case for x32) 
is, as previously discussed, closer to what we want (which is that the 
"long" in the syscall ABI is 64-bit, which corresponds to __WORDSIZE and 
the userspace "long" in all cases except for x32).

> Then the code would be (it is easier for me to understand the
> execution paths when providing the pseudo code):
> 
> __clock_settime64(....)
> {
> ...
> 
> #ifdef __ASSUME_TIME64_SYSCALLS
> #  ifndef __NR_clock_settime64
> #    define __NR_clock_settime64 __NR_clock_settime [1]
> #  endif
>   INLINE_SYSCALL_CALL (clock_settime64, …) [2]
> #else [3]
>   int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
>   if (ret == 0 || errno != ENOSYS)
> 	return ret;

This part of the code inside the #else needs to be conditional, as well, 
on "#ifdef __NR_clock_settime64".  (Unless we require very new kernel 
headers to build glibc.  But we obviously can't right now - there's no 
existing kernel release whose headers both include these syscalls and are 
suitable for testing glibc, because of the fds_bits namespace issue.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-28 19:47         ` Joseph Myers
@ 2019-05-28 22:09           ` Lukasz Majewski
  2019-05-28 22:43             ` Joseph Myers
  0 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-28 22:09 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Stepan Golosunov, libc-alpha, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 2625 bytes --]

Hi Joseph,

> On Sat, 25 May 2019, Stepan Golosunov wrote:
> 
> > In most cases code can look like this:
> > 
> > #ifdef __ASSUME_TIME64_SYSCALLS
> > #ifndef __NR_clock_settime64
> > #define __NR_clock_settime64 __NR_clock_settime
> > #endif
> > INLINE_SYSCALL_CALL (clock_settime64, …)
> > #else
> > try clock_settime64, if that fails (whether compiletime or runtime)
> > convert data to 32-bit, call clock_settime
> > #endif
> > 
> > (Yes, for semtimedop it won't be that simple.  Because traditional
> > syscall isn't semtimedop in some cases.  This also assumes that
> > the  
> 
> If we follow this approach, it would be reasonable to say that 
> __ASSUME_TIME64_SYSCALLS is *only* for those syscalls where the old 
> syscall, on platforms that had 64-bit time in their syscall interface
> all along, is exactly equivalent (and to list that subset) 

Yes, I do agree. Also those syscalls shall be explicitly listed in the
commit message and code (as comments).

> - not for 
> semtimedop.  Then there could be a separate
> __ASSUME_SEMTIMEDOP_TIME64.
> 
> > 20 time64 syscall names won't suddenly be added to kernel headers
> > for 64-bit ABIs.)  
> 
> Rather, that they won't be added *with new syscall numbers*.  If the 
> kernel adds them as macro aliases for the old syscall numbers, code
> like that would work just fine.  If the kernel adds them as new
> syscall numbers, the definition of __ASSUME_TIME64_SYSCALLS (that
> assumes it can always be true for existing 64-bit syscall ABIs) would
> suddenly become wrong when using new kernel headers, because it would
> result in glibc code using new syscall numbers without regard to a
> possibly older runtime kernel version.
> 

Maybe I'm missing something, but would there be any use case
(possibility) that for archs supporting 64 bit time ABI (and using e.g.
__NR_clock_settime now) the new syscalls (like __NR_clock_settime64),
with the same functionality, would be added with different numbers?

Why already perfectly working __NR_clock_settime would be replaced by
other syscall (like __NR_clock_settime64) not with alias but different
number (on e.g x86_64)?

I always thought that __NR_clock_settime64 would be added on archs with
__WORDSIZE==32 to allow them to work after Y2038 and hence there would
be no chance for such collision.


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-28 22:09           ` Lukasz Majewski
@ 2019-05-28 22:43             ` Joseph Myers
  0 siblings, 0 replies; 111+ messages in thread
From: Joseph Myers @ 2019-05-28 22:43 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: Stepan Golosunov, libc-alpha, Arnd Bergmann, Paul Eggert

On Wed, 29 May 2019, Lukasz Majewski wrote:

> Maybe I'm missing something, but would there be any use case
> (possibility) that for archs supporting 64 bit time ABI (and using e.g.
> __NR_clock_settime now) the new syscalls (like __NR_clock_settime64),
> with the same functionality, would be added with different numbers?

I don't see a use case for it, but it's one of many ideas that were 
discussed in the past (to have the same syscalls on all systems with the 
same numbers as far as possible).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-28 19:53           ` Joseph Myers
@ 2019-05-28 22:46             ` Lukasz Majewski
  2019-05-28 22:50               ` Joseph Myers
  0 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-05-28 22:46 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Stepan Golosunov, libc-alpha, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 4126 bytes --]

Hi Joseph

> On Sun, 26 May 2019, Lukasz Majewski wrote:
> 
> > Shall the __ASSUME_TIME64_SYSCALLS be defined as:
> > (@ sysdeps/unix/sysv/linux/kernel-features.h):
> > 
> > #if __WORDSIZE == 32
> > # if __LINUX_KERNEL_VERSION >= 0x050100
> > #  define __ASSUME_TIME64_SYSCALLS 1
> > # endif
> > #endif
> > 
> > And also for __TIMESIZE==64
> > (@ include/time.h)
> > 
> > #if __TIMESIZE==64
> > # define __ASSUME_TIME64_SYSCALLS 1
> > #endif  
> 
> __ASSUME_* should *only* be defined in kernel-features.h.  A
> definition in include/* would be incorrect.

Ok.

> 
> It's not clear to me that __TIMESIZE == 64 would be the right
> condition (in kernel-features.h) for defining
> __ASSUME_TIME64_SYSCALLS independent of kernel version, because it
> would get wrong the case of 32-bit architectures with old kernel
> support and glibc support added in future with 64-bit time only (if
> we decide that any such future glibc port should use only 64-bit time
> in userspace, but without also requiring a new kernel for such a
> port). 

In the above case we would switch to __TIMESIZE == 64 in some point.

> Rather, __WORDSIZE == 64 (with a special case for x32) is, as
> previously discussed, closer to what we want (which is that the
> "long" in the syscall ABI is 64-bit, which corresponds to __WORDSIZE
> and the userspace "long" in all cases except for x32).
> 

Shall the __ASSUME_TIME64_SYSCALLS be defined as:
(@ sysdeps/unix/sysv/linux/kernel-features.h):

#if (__WORDSIZE == 32 && \
	((__LINUX_KERNEL_VERSION >= 0x050100 || \
	 (defined __SYSCALL_WORDSIZE && __SYSCALL_WORDSIZE == 64))) || \
    (__WORDSIZE == 64)
#  define __ASSUME_TIME64_SYSCALLS 1
# endif
#endif

The above statement supports:

- 32 bit __WORDSIZE devices with 64 bit time ABI syscalls after 5.1
  kernel (e.g. clock_settime64)

- x32 (which defines __SYSCALL_WORDSIZE == 64)

- 64 bit systems (with 64 bit time ABI) - the __WORDSIZE == 64

> > Then the code would be (it is easier for me to understand the
> > execution paths when providing the pseudo code):
> > 
> > __clock_settime64(....)
> > {
> > ...
> > 
> > #ifdef __ASSUME_TIME64_SYSCALLS
> > #  ifndef __NR_clock_settime64
> > #    define __NR_clock_settime64 __NR_clock_settime [1]
> > #  endif
> >   INLINE_SYSCALL_CALL (clock_settime64, …) [2]
> > #else [3]
> >   int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
> >   if (ret == 0 || errno != ENOSYS)
> > 	return ret;  
> 
> This part of the code inside the #else needs to be conditional, as
> well, on "#ifdef __NR_clock_settime64".  (Unless we require very new
> kernel headers to build glibc.  But we obviously can't right now -
> there's no existing kernel release whose headers both include these
> syscalls and are suitable for testing glibc, because of the fds_bits
> namespace issue.)
> 

I assume that the "#ifdef __NR_clock_settime64" would prevent from
unneeded call to clock_settime64 (as we would end up in the fallback
path) on setup with old kernel and glibc build with old headers (by
'old' I mean one not supporting 64 bit time).

Also it will prevent from described above situation where we do have
kernel 5.1+ but glibc is build with kernel headers older than 5.1.


The corrected version of clock_settime64:

__clock_settime64(....)
{
...

#ifdef __ASSUME_TIME64_SYSCALLS
#  ifndef __NR_clock_settime64
#    define __NR_clock_settime64 __NR_clock_settime [1]
#  endif
  INLINE_SYSCALL_CALL (clock_settime64, …) [2]
#else [3]
# ifdef __NR_clock_settime64
  int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
  if (ret == 0 || errno != ENOSYS)
	return ret;
# endif
  struct timespec ts32;
  valid_timespec64_to_timespec (tp, &ts32);
  return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);	
#endif



Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define
  2019-05-28 22:46             ` Lukasz Majewski
@ 2019-05-28 22:50               ` Joseph Myers
  0 siblings, 0 replies; 111+ messages in thread
From: Joseph Myers @ 2019-05-28 22:50 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: Stepan Golosunov, libc-alpha, Arnd Bergmann, Paul Eggert

On Wed, 29 May 2019, Lukasz Majewski wrote:

> Shall the __ASSUME_TIME64_SYSCALLS be defined as:
> (@ sysdeps/unix/sysv/linux/kernel-features.h):
> 
> #if (__WORDSIZE == 32 && \
> 	((__LINUX_KERNEL_VERSION >= 0x050100 || \
> 	 (defined __SYSCALL_WORDSIZE && __SYSCALL_WORDSIZE == 64))) || \
>     (__WORDSIZE == 64)
> #  define __ASSUME_TIME64_SYSCALLS 1
> # endif
> #endif

That's not correctly formatted (break lines before not after operators), 
but it seems like the right sort of idea.

> I assume that the "#ifdef __NR_clock_settime64" would prevent from
> unneeded call to clock_settime64 (as we would end up in the fallback

It would prevent a *compilation failure* from trying to call a syscall 
whose syscall number is not defined.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-08 10:18               ` Lukasz Majewski
  2019-05-09 15:46                 ` Joseph Myers
@ 2019-05-31 11:37                 ` Stepan Golosunov
  2019-06-05 16:35                   ` Lukasz Majewski
  1 sibling, 1 reply; 111+ messages in thread
From: Stepan Golosunov @ 2019-05-31 11:37 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: Joseph Myers, libc-alpha, Arnd Bergmann, Paul Eggert

08.05.2019 в 12:18:40 +0200 Lukasz Majewski написал:
> Hi Joseph,
> 
> > On Mon, 6 May 2019, Lukasz Majewski wrote:
> > 
> > > > So, which is (or will be) the case in 5.1 release?  Padding
> > > > ignored or not?  
> > > 
> > > As confirmed in the other mail - the padding is ignored in Linux
> > > kernel (and the fix patch for x32 is up its way to be pulled).  
> > 
> > Did the patch to ignore padding (for compat syscalls under 64-bit
> > kernels, non-x32) make it into the final 5.1 release?
> 
> As fair as I can tell, it was not pulled to 5.1.

The patch went into 5.1.5 and 5.2-rc1.

So the question now is:

Should Linux 5.1.0–5.1.4 be considered buggy and unsupported, or
should glibc clear padding around tv_nsec on 32-bit architectures when
__LINUX_KERNEL_VERSION < 0x050105 and 64-bit kernel exists?

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-05-31 11:37                 ` Stepan Golosunov
@ 2019-06-05 16:35                   ` Lukasz Majewski
  2019-06-06  6:50                     ` Stepan Golosunov
  0 siblings, 1 reply; 111+ messages in thread
From: Lukasz Majewski @ 2019-06-05 16:35 UTC (permalink / raw)
  To: Stepan Golosunov; +Cc: Joseph Myers, libc-alpha, Arnd Bergmann, Paul Eggert

[-- Attachment #1: Type: text/plain, Size: 1498 bytes --]

Hi Stepan,

> 08.05.2019 в 12:18:40 +0200 Lukasz Majewski написал:
> > Hi Joseph,
> >   
> > > On Mon, 6 May 2019, Lukasz Majewski wrote:
> > >   
> > > > > So, which is (or will be) the case in 5.1 release?  Padding
> > > > > ignored or not?    
> > > > 
> > > > As confirmed in the other mail - the padding is ignored in Linux
> > > > kernel (and the fix patch for x32 is up its way to be
> > > > pulled).    
> > > 
> > > Did the patch to ignore padding (for compat syscalls under 64-bit
> > > kernels, non-x32) make it into the final 5.1 release?  
> > 
> > As fair as I can tell, it was not pulled to 5.1.  
> 
> The patch went into 5.1.5 and 5.2-rc1.
> 
> So the question now is:
> 
> Should Linux 5.1.0–5.1.4 be considered buggy and unsupported, or
> should glibc clear padding around tv_nsec on 32-bit architectures when
> __LINUX_KERNEL_VERSION < 0x050105 and 64-bit kernel exists?

I would assume that the kernel is buggy for 5.1.0–5.1.4 on x32 (I
don't know what would be the impact of such decision - to be more
specific how many x32 ABI users would be affected).

Moreover, I would add the condition __LINUX_KERNEL_VERSION >= 0x050105
when we define __ASSUME_TIME64_SYSCALLS.



Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 111+ messages in thread

* Re: [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define
  2019-06-05 16:35                   ` Lukasz Majewski
@ 2019-06-06  6:50                     ` Stepan Golosunov
  0 siblings, 0 replies; 111+ messages in thread
From: Stepan Golosunov @ 2019-06-06  6:50 UTC (permalink / raw)
  To: Lukasz Majewski; +Cc: Joseph Myers, libc-alpha, Arnd Bergmann, Paul Eggert

05.06.2019 в 18:35:16 +0200 Lukasz Majewski написал:
> Hi Stepan,
> 
> > 08.05.2019 в 12:18:40 +0200 Lukasz Majewski написал:
> > > Hi Joseph,
> > >   
> > > > On Mon, 6 May 2019, Lukasz Majewski wrote:
> > > >   
> > > > > > So, which is (or will be) the case in 5.1 release?  Padding
> > > > > > ignored or not?    
> > > > > 
> > > > > As confirmed in the other mail - the padding is ignored in Linux
> > > > > kernel (and the fix patch for x32 is up its way to be
> > > > > pulled).    
> > > > 
> > > > Did the patch to ignore padding (for compat syscalls under 64-bit
> > > > kernels, non-x32) make it into the final 5.1 release?  
> > > 
> > > As fair as I can tell, it was not pulled to 5.1.  
> > 
> > The patch went into 5.1.5 and 5.2-rc1.
> > 
> > So the question now is:
> > 
> > Should Linux 5.1.0–5.1.4 be considered buggy and unsupported, or
> > should glibc clear padding around tv_nsec on 32-bit architectures when
> > __LINUX_KERNEL_VERSION < 0x050105 and 64-bit kernel exists?
> 
> I would assume that the kernel is buggy for 5.1.0–5.1.4 on x32 (I
> don't know what would be the impact of such decision - to be more
> specific how many x32 ABI users would be affected).

x32 is irrelevant for this bug (as long as it has 64-bit tv_nsec in
glibc).  All other 32-bit ABIs which can be used on 64-bit kernels are
affected.

> Moreover, I would add the condition __LINUX_KERNEL_VERSION >= 0x050105
> when we define __ASSUME_TIME64_SYSCALLS.

This won't help as _time64 syscalls should be called even when
__ASSUME_TIME64_SYSCALLS is not defined.

^ permalink raw reply	[flat|nested] 111+ messages in thread

end of thread, other threads:[~2019-06-06  6:50 UTC | newest]

Thread overview: 111+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-14 22:08 [PATCH 0/6] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
2019-04-14 22:08 ` [PATCH 1/6] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
2019-04-14 22:08 ` [PATCH 2/6] y2038: Provide conversion helpers for " Lukasz Majewski
2019-04-14 22:08 ` [PATCH 3/6] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
2019-04-17 22:08   ` Joseph Myers
2019-04-18  6:46     ` Lukasz Majewski
2019-04-20  0:20   ` Stepan Golosunov
2019-04-20 11:21     ` Lukasz Majewski
2019-04-22  9:07       ` Stepan Golosunov
2019-04-22 21:45         ` Arnd Bergmann
2019-04-23 15:45           ` Lukasz Majewski
2019-04-14 22:08 ` [PATCH 4/6] y2038: linux: Provide __clock_getres64 implementation Lukasz Majewski
2019-04-14 22:08 ` [PATCH 5/6] y2038: linux: Provide __clock_gettime64 implementation Lukasz Majewski
2019-04-14 22:08 ` [PATCH 6/6] y2038: linux: Provide __clock_nanosleep64 implementation Lukasz Majewski
2019-04-17 22:11   ` Joseph Myers
2019-04-18  5:54     ` Lukasz Majewski
2019-04-29 10:46 ` [PATCH v2 0/7] y2038: Linux: Provide __clock_* functions supporting 64 bit time Lukasz Majewski
2019-04-29 10:46   ` [PATCH v2 1/7] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
2019-04-29 10:46   ` [PATCH v2 2/7] y2038: Introduce __ASSUME_64BIT_TIME define Lukasz Majewski
2019-04-29 21:50     ` Joseph Myers
2019-04-30  9:05       ` Lukasz Majewski
2019-04-30 21:47         ` Stepan Golosunov
2019-05-02  8:51           ` Lukasz Majewski
2019-05-02 11:54             ` Stepan Golosunov
2019-05-02 13:55               ` Lukasz Majewski
2019-05-06 13:38                 ` Lukasz Majewski
2019-05-06 14:26                   ` Lukasz Majewski
2019-05-06 19:36                     ` Stepan Golosunov
2019-05-06 21:14                       ` Lukasz Majewski
2019-05-07 20:03                         ` Stepan Golosunov
2019-05-07 20:44                           ` Joseph Myers
2019-05-08  7:51                           ` Lukasz Majewski
2019-05-08 19:48                             ` Stepan Golosunov
2019-05-09 16:12                               ` Joseph Myers
2019-05-16  4:00                               ` Arnd Bergmann
2019-05-16 19:54                                 ` Stepan Golosunov
2019-05-16 19:59                                 ` Joseph Myers
2019-05-17  7:23                                   ` Florian Weimer
2019-05-17  8:34                                     ` Arnd Bergmann
2019-05-07 15:43                       ` Joseph Myers
2019-05-02 15:04         ` Joseph Myers
2019-05-05 14:10           ` Stepan Golosunov
2019-05-05 20:46             ` Lukasz Majewski
2019-05-06 14:56           ` Lukasz Majewski
2019-05-07 15:35             ` Joseph Myers
2019-05-08 10:18               ` Lukasz Majewski
2019-05-09 15:46                 ` Joseph Myers
2019-05-15 15:39                   ` Lukasz Majewski
2019-05-16  3:57                     ` Arnd Bergmann
2019-05-16  6:58                       ` Lukasz Majewski
2019-05-31 11:37                 ` Stepan Golosunov
2019-06-05 16:35                   ` Lukasz Majewski
2019-06-06  6:50                     ` Stepan Golosunov
2019-04-29 10:46   ` [PATCH v2 3/7] y2038: Provide conversion helpers for struct __timespec64 Lukasz Majewski
2019-05-02 11:56     ` Stepan Golosunov
2019-05-02 14:17       ` Lukasz Majewski
2019-05-02 15:59         ` Joseph Myers
2019-05-02 16:19           ` Lukasz Majewski
2019-04-29 10:46   ` [PATCH v2 4/7] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
2019-04-29 10:46   ` [PATCH v2 5/7] y2038: linux: Provide __clock_getres64 implementation Lukasz Majewski
2019-04-29 10:46   ` [PATCH v2 6/7] y2038: linux: Provide __clock_gettime64 implementation Lukasz Majewski
2019-04-29 10:46   ` [PATCH v2 7/7] y2038: linux: Provide __clock_nanosleep64 implementation Lukasz Majewski
2019-05-07 13:18 ` [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time Lukasz Majewski
2019-05-07 13:18   ` [PATCH v3 1/5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define Lukasz Majewski
2019-05-07 16:04     ` Joseph Myers
2019-05-07 13:18   ` [PATCH v3 2/5] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
2019-05-07 13:30     ` Andreas Schwab
2019-05-07 14:07       ` Lukasz Majewski
2019-05-07 14:13         ` Andreas Schwab
2019-05-08  8:32           ` Lukasz Majewski
2019-05-08  8:38             ` Andreas Schwab
2019-05-08  9:10               ` Lukasz Majewski
2019-05-08  9:12                 ` Andreas Schwab
2019-05-08  9:37                   ` Lukasz Majewski
2019-05-07 13:18   ` [PATCH v3 3/5] y2038: Provide conversion helpers for " Lukasz Majewski
2019-05-07 13:18   ` [PATCH v3 4/5] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
2019-05-07 16:40     ` Joseph Myers
2019-05-07 13:18   ` [PATCH v3 5/5] y2038: Support for Y2038 safe time on 32 bit systems Lukasz Majewski
2019-05-07 16:37     ` Joseph Myers
2019-05-08 10:27       ` Lukasz Majewski
2019-05-07 13:18   ` [PATCH v3 0/5] y2038: Linux: Provide __clock_settime function supporting 64 bit time Lukasz Majewski
2019-05-07 13:18   ` [PATCH v3 1/5] y2038: Introduce __ASSUME_TIME64_SYSCALLS define Lukasz Majewski
2019-05-07 13:18   ` [PATCH v3 2/5] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
2019-05-07 13:18   ` [PATCH v3 3/5] y2038: Provide conversion helpers for " Lukasz Majewski
2019-05-07 13:18   ` [PATCH v3 4/5] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
2019-05-07 13:18   ` [PATCH v3 5/5] y2038: Support for Y2038 safe time on 32 bit systems Lukasz Majewski
2019-05-07 13:34     ` Andreas Schwab
2019-05-08 15:56 ` [PATCH] y2038: Introduce __ASSUME_TIME64_SYSCALLS define Lukasz Majewski
2019-05-09 15:58   ` Joseph Myers
2019-05-09 16:18     ` Stepan Golosunov
2019-05-15 14:27 ` [PATCH v5] " Lukasz Majewski
2019-05-21 15:15   ` Lukasz Majewski
2019-05-23  7:34   ` Stepan Golosunov
2019-05-23  9:35     ` Lukasz Majewski
2019-05-25 16:19       ` Lukasz Majewski
2019-05-25 19:45       ` Stepan Golosunov
2019-05-26 12:39         ` Lukasz Majewski
2019-05-28 16:00           ` Lukasz Majewski
2019-05-28 19:53           ` Joseph Myers
2019-05-28 22:46             ` Lukasz Majewski
2019-05-28 22:50               ` Joseph Myers
2019-05-28 19:47         ` Joseph Myers
2019-05-28 22:09           ` Lukasz Majewski
2019-05-28 22:43             ` Joseph Myers
2019-05-23 21:17     ` Joseph Myers
2019-05-20 10:27 ` [PATCH v4 0/3] y2038: Linux: Provide __clock_settime64 function supporting 64 bit time Lukasz Majewski
2019-05-20 10:27   ` [PATCH v4 1/3] y2038: Introduce internal for glibc struct __timespec64 Lukasz Majewski
2019-05-20 10:27   ` [PATCH v4 2/3] y2038: Provide conversion helpers for " Lukasz Majewski
2019-05-20 10:27   ` [PATCH v4 3/3] y2038: linux: Provide __clock_settime64 implementation Lukasz Majewski
2019-05-23  7:08     ` Stepan Golosunov
2019-05-23  9:28       ` Lukasz Majewski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).