[v2] Y2038: provide kernel support indication

Message ID 20181017111911.26368-1-albert.aribaud@3adev.fr
State New, archived
Headers

Commit Message

Albert ARIBAUD Oct. 17, 2018, 11:19 a.m. UTC
  Introduce __ASSUME_KERNEL_Y2038_SUPPORT which means that
the underlying kernel *always* implements 64-bit-time Y2038-proof
syscalls.

If __ASSUME_KERNEL_Y2038_SUPPORT is not defined, glibc must
check dynamically whether the underlying kernel provides these
syscalls or not, and must fallback to 32-bit-time syscalls if
not.

Introduce function __y2038_get_kernel_support(), which returns
true if the underlying kernel supports 64-bit-time syscalls.

Also introduce function __y2038_set_kernel_support(), which
allows an implementation to notify glibc of the absence of
64-bit-time syscalls (ENOSYS) so that they are not needlessly
tried again.

* misc/Makefile: Add module y2038-support.
* misc/Versions: (__y2038_get_kernel_support): Add to GLIBC_PRIVATE.
* misc/Versions: (__y2038_set_kernel_support): Likewise.
* misc/y2038-support.c: New file.
* misc/y2038-support.h: Likewise.
* sysdeps/unix/sysv/linux/kernel-features.h (__ASSUME_KERNEL_Y2038_SUPPORT): Add.
* sysdeps/unix/sysv/linux/y2038-support.c: New file.
* sysdeps/unix/sysv/linux/y2038-support.h: New file.
---
 misc/Makefile                             |  2 +-
 misc/Versions                             |  4 ++
 misc/y2038-support.c                      | 40 ++++++++++++++++++++
 misc/y2038-support.h                      | 33 ++++++++++++++++
 sysdeps/unix/sysv/linux/kernel-features.h | 14 +++++++
 sysdeps/unix/sysv/linux/y2038-support.c   | 46 +++++++++++++++++++++++
 sysdeps/unix/sysv/linux/y2038-support.h   | 34 +++++++++++++++++
 7 files changed, 172 insertions(+), 1 deletion(-)
 create mode 100644 misc/y2038-support.c
 create mode 100644 misc/y2038-support.h
 create mode 100644 sysdeps/unix/sysv/linux/y2038-support.c
 create mode 100644 sysdeps/unix/sysv/linux/y2038-support.h
  

Comments

Albert ARIBAUD Oct. 17, 2018, 11:22 a.m. UTC | #1
On Wed, 17 Oct 2018 13:19:11 +0200, "Albert ARIBAUD (3ADEV)"
<albert.aribaud@3adev.fr> wrote :

Note that

1. this patch is basically independent from the previously posted Y2038
patches, and

2. this patch was not tested using make check, as it only adds a
feature and accompanying functions, and does not modify any existing
functionality.

Cordialement,
Albert ARIBAUD
3ADEV
  
Joseph Myers Oct. 17, 2018, 12:18 p.m. UTC | #2
On Wed, 17 Oct 2018, Albert ARIBAUD (3ADEV) wrote:

> diff --git a/misc/Versions b/misc/Versions
> index 900e4ffb79..48285d8c42 100644
> --- a/misc/Versions
> +++ b/misc/Versions
> @@ -158,6 +158,8 @@ libc {
>    GLIBC_2.26 {
>      preadv2; preadv64v2; pwritev2; pwritev64v2;
>    }
> +  GLIBC_2.29 {
> +  }

Why?  I don't see any SHLIB_COMPAT or similar conditionals that might 
require such an empty symbol version.

> +/* Support for Y2038-proof times.
> +
> +   If defined, the underlying kernel always provides a set of syscalls
> +   (__NR_* names and numbers) which can handle times beyond Y2038.
> +
> +   If undefined, whether the underlying kernel provides this set or not
> +   must be checked dynamically.
> +
> +   Definition is commented out until Y2038 syscalls are merged in the
> +   kernel.

I am unable to tell from this comment what the correct definition is for 
64-bit systems where time_t in the default syscalls has always been 
64-bit.  That information needs to be completely obvious from the comment; 
it needs to be completely explicit whether the macro relates to new 
syscalls whose names explicitly refer to 64-bit times, or whether it 
relates to syscalls supporting 64-bit times whose names might not mention 
64-bit when on 64-bit platforms.

If the latter, the macro should of course be defined on 64-bit systems.  
If the former, however, while the macro should then not be defined on 
64-bit systems, the contents of y2038-support.c (both versions) must also 
be conditioned out for __TIMESIZE == 64; there should be no additional 
code added to libc binaries whatever in support of this feature on systems 
where time_t is already 64-bit.  (The declarations in y2038-support.h 
should probably also be disabled in that case, to result in compile 
failures if anything tries to call those functions with __TIMESIZE == 64.)

> +/* By default the underlying Linux kernel is assumed not to support Y2038.
> + * Any Linux architecture may (test and) claim Y2038 kernel support by
> + * setting __y2038_linux_support.

We don't use leading '*' on each comment line.

> +bool
> +__linux_y2038_get_kernel_support (void)
> +{
> +  return __y2038_linux_support;
> +}
> +strong_alias (__linux_y2038_get_kernel_support, __y2038_get_kernel_support)
> +
> +void
> +__linux_y2038_set_kernel_support (bool support)
> +{
> +  __y2038_linux_support = support;

Are you sure about using direct read / assignment like this rather than 
relaxed atomics, which seem more logically correct for such cases (and 
hopefully will generate the same code) where multiple threads might be 
using the variable at once?

> +strong_alias (__linux_y2038_set_kernel_support, __y2038_set_kernel_support)

Why?  The functions should never be accessed under the __linux_* names; 
I'd expect them to be defined directly with the __y2038_* names, in both 
files, rather than complicating things with __default_* / __linux_* names 
and aliases.  (You need to use libc_hidden_proto / libc_hidden_def, 
however, since you have GLIBC_PRIVATE exports, so that accesses from 
within libc.so use a hidden symbol name rather than going via the PLT.)

> +/* Indicates Y2038 support.
> + * Can be read directly from within libc linux-related files.
> + * Can be written non-zero to indicate support or lack thereof.
> + * Other libraries (e.g. librt) cannot access this variable and must
> + * call __y2038_get_kernel_support() and __y2038_set_kernel_support().  */
> +extern bool __y2038_linux_support;

Same point about comment formatting.  If you have accessor functions, I 
don't think you should be accessing this variable directly other than 
through inline versions of those accessor functions.  So either make this 
variable static and remove that declaration, or add "#if IS_IN (libc)" 
inline definitions of the accessors (and make that declaration, which 
should also use attribute_hidden, conditional on IS_IN (libc) as well).
  
Joseph Myers Oct. 17, 2018, 12:19 p.m. UTC | #3
On Wed, 17 Oct 2018, Albert ARIBAUD wrote:

> 2. this patch was not tested using make check, as it only adds a
> feature and accompanying functions, and does not modify any existing
> functionality.

It adds new C code built into libc.  That always needs testing with "make 
check", to verify that it doesn't introduce any ABI test failures, for 
example.
  

Patch

diff --git a/misc/Makefile b/misc/Makefile
index 30e0673c8a..7ced1eac88 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -71,7 +71,7 @@  routines := brk sbrk sstk ioctl \
 	    fgetxattr flistxattr fremovexattr fsetxattr getxattr \
 	    listxattr lgetxattr llistxattr lremovexattr lsetxattr \
 	    removexattr setxattr getauxval ifunc-impl-list makedev \
-	    allocate_once
+	    allocate_once y2038-support
 
 generated += tst-error1.mtrace tst-error1-mem.out \
   tst-allocate_once.mtrace tst-allocate_once-mem.out
diff --git a/misc/Versions b/misc/Versions
index 900e4ffb79..48285d8c42 100644
--- a/misc/Versions
+++ b/misc/Versions
@@ -158,6 +158,8 @@  libc {
   GLIBC_2.26 {
     preadv2; preadv64v2; pwritev2; pwritev64v2;
   }
+  GLIBC_2.29 {
+  }
   GLIBC_PRIVATE {
     __madvise;
     __mktemp;
@@ -166,5 +168,7 @@  libc {
     __mmap; __munmap; __mprotect;
     __sched_get_priority_min; __sched_get_priority_max;
     __libc_allocate_once_slow;
+    __y2038_get_kernel_support;
+    __y2038_set_kernel_support;
   }
 }
diff --git a/misc/y2038-support.c b/misc/y2038-support.c
new file mode 100644
index 0000000000..64f8036ebb
--- /dev/null
+++ b/misc/y2038-support.c
@@ -0,0 +1,40 @@ 
+/* y2038 general kernel support indication.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdbool.h>
+
+#ifndef __ASSUME_KERNEL_Y2038_SUPPORT
+
+/* By default glibc assumes the underlying kernel does not support Y2038.  */ 
+bool
+__default_y2038_get_kernel_support (void)
+{
+  return false;
+}
+weak_alias (__default_y2038_get_kernel_support, __y2038_get_kernel_support)
+
+/* By default glibc just ignores Y2038 support indication setting.  */ 
+void
+__default_y2038_set_kernel_support (bool support __attribute__ ((unused)))
+{
+  /* Do nothing.  */
+}
+weak_alias (__default_y2038_set_kernel_support, __y2038_set_kernel_support)
+
+#endif
diff --git a/misc/y2038-support.h b/misc/y2038-support.h
new file mode 100644
index 0000000000..aad387b39d
--- /dev/null
+++ b/misc/y2038-support.h
@@ -0,0 +1,33 @@ 
+/* y2038 general kernel support indication.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdbool.h>
+
+/* If we do not assume that the kernel provides 64-bit-time syscalls,
+ * then we need a dynamic way to remember whether it does or not.  */
+
+#ifndef __ASSUME_KERNEL_Y2038_SUPPORT
+
+/* Dynamically check whether actual kernel supports Y2038 or not.  */
+extern bool __y2038_get_kernel_support (void);
+
+/* Dynamically set whether actual kernel supports Y2038 or not.  */
+extern void __y2038_set_kernel_support (bool support);
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
index 5543d92d7e..b47755b36c 100644
--- a/sysdeps/unix/sysv/linux/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/kernel-features.h
@@ -154,3 +154,17 @@ 
    */
 
 #define __ASSUME_CLONE_DEFAULT 1
+
+/* Support for Y2038-proof times.
+
+   If defined, the underlying kernel always provides a set of syscalls
+   (__NR_* names and numbers) which can handle times beyond Y2038.
+
+   If undefined, whether the underlying kernel provides this set or not
+   must be checked dynamically.
+
+   Definition is commented out until Y2038 syscalls are merged in the
+   kernel.
+   */
+
+/* #define __ASSUME_KERNEL_Y2038_SUPPORT 1 */
diff --git a/sysdeps/unix/sysv/linux/y2038-support.c b/sysdeps/unix/sysv/linux/y2038-support.c
new file mode 100644
index 0000000000..adbcd8fa00
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/y2038-support.c
@@ -0,0 +1,46 @@ 
+/* y2038 Linux kernel support indication.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef __ASSUME_KERNEL_Y2038_SUPPORT
+
+#include <stdbool.h>
+
+/* By default the underlying Linux kernel is assumed not to support Y2038.
+ * Any Linux architecture may (test and) claim Y2038 kernel support by
+ * setting __y2038_linux_support.
+ */
+bool __y2038_linux_support = false;
+
+/* For Linux, Y2038 kernel support is determined by __y2038_linux_support.  */
+
+bool
+__linux_y2038_get_kernel_support (void)
+{
+  return __y2038_linux_support;
+}
+strong_alias (__linux_y2038_get_kernel_support, __y2038_get_kernel_support)
+
+void
+__linux_y2038_set_kernel_support (bool support)
+{
+  __y2038_linux_support = support;
+}
+strong_alias (__linux_y2038_set_kernel_support, __y2038_set_kernel_support)
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/y2038-support.h b/sysdeps/unix/sysv/linux/y2038-support.h
new file mode 100644
index 0000000000..b8b6b8eeba
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/y2038-support.h
@@ -0,0 +1,34 @@ 
+/* y2038 Linux kernel support indication.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef __ASSUME_KERNEL_Y2038_SUPPORT
+
+#include <stdbool.h>
+
+/* Indicates Y2038 support.
+ * Can be read directly from within libc linux-related files.
+ * Can be written non-zero to indicate support or lack thereof.
+ * Other libraries (e.g. librt) cannot access this variable and must
+ * call __y2038_get_kernel_support() and __y2038_set_kernel_support().  */
+extern bool __y2038_linux_support;
+
+#endif
+
+/* As a fallback, provide generic Y2038 support indication.  */
+#include <misc/y2038-support.h>