All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/5] cobalt/kernel: y2038: convert struct timeval to __kernel_old_timeval
@ 2021-02-20 15:18 Philippe Gerum
  2021-02-20 15:18 ` [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64 Philippe Gerum
                   ` (3 more replies)
  0 siblings, 4 replies; 57+ messages in thread
From: Philippe Gerum @ 2021-02-20 15:18 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai, Philippe Gerum

From: Philippe Gerum <rpm@xenomai.org>

As internal interfaces are gradually being made y2038-safe, the
deprecated timeval type is now available as __kernel_old_timeval in
the mainline kernel for the sake of clarity. Switch to this type until
Cobalt is y2038-safe as well.

A wrapper is provided to build on older kernels not defining
__kernel_old_timeval yet.

Signed-off-by: Philippe Gerum <rpm@xenomai.org>
---
 include/cobalt/kernel/compat.h                       | 4 ++--
 kernel/cobalt/include/asm-generic/xenomai/wrappers.h | 4 ++++
 kernel/cobalt/posix/clock.h                          | 4 ++--
 kernel/cobalt/posix/compat.c                         | 4 ++--
 kernel/cobalt/posix/io.c                             | 6 +++---
 kernel/cobalt/posix/io.h                             | 2 +-
 kernel/cobalt/posix/syscall32.c                      | 2 +-
 kernel/drivers/ipc/bufp.c                            | 5 +++--
 kernel/drivers/ipc/iddp.c                            | 5 +++--
 kernel/drivers/ipc/internal.h                        | 9 +++++----
 kernel/drivers/ipc/rtipc.c                           | 9 +++++----
 kernel/drivers/ipc/xddp.c                            | 5 +++--
 kernel/drivers/net/stack/ipv4/tcp/tcp.c              | 2 +-
 13 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/include/cobalt/kernel/compat.h b/include/cobalt/kernel/compat.h
index c9cb84f72..313b6251b 100644
--- a/include/cobalt/kernel/compat.h
+++ b/include/cobalt/kernel/compat.h
@@ -98,11 +98,11 @@ int sys32_get_itimerspec(struct itimerspec *its,
 int sys32_put_itimerspec(struct compat_itimerspec __user *cits,
 			 const struct itimerspec *its);
 
-int sys32_get_timeval(struct timeval *tv,
+int sys32_get_timeval(struct __kernel_old_timeval *tv,
 		      const struct compat_timeval __user *ctv);
 
 int sys32_put_timeval(struct compat_timeval __user *ctv,
-		      const struct timeval *tv);
+		      const struct __kernel_old_timeval *tv);
 
 int sys32_get_timex(struct timex *tx,
 		    const struct old_timex32 __user *ctx);
diff --git a/kernel/cobalt/include/asm-generic/xenomai/wrappers.h b/kernel/cobalt/include/asm-generic/xenomai/wrappers.h
index e093676e1..2e9fb203a 100644
--- a/kernel/cobalt/include/asm-generic/xenomai/wrappers.h
+++ b/kernel/cobalt/include/asm-generic/xenomai/wrappers.h
@@ -162,4 +162,8 @@ devm_hwmon_device_register_with_groups(struct device *dev, const char *name,
 #define mmiowb()		do { } while (0)
 #endif
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)
+#define __kernel_old_timeval	timeval
+#endif
+
 #endif /* _COBALT_ASM_GENERIC_WRAPPERS_H */
diff --git a/kernel/cobalt/posix/clock.h b/kernel/cobalt/posix/clock.h
index 0b06b9316..7cb161df2 100644
--- a/kernel/cobalt/posix/clock.h
+++ b/kernel/cobalt/posix/clock.h
@@ -43,7 +43,7 @@ static inline xnticks_t ts2ns(const struct timespec *ts)
 	return nsecs;
 }
 
-static inline xnticks_t tv2ns(const struct timeval *tv)
+static inline xnticks_t tv2ns(const struct __kernel_old_timeval *tv)
 {
 	xnticks_t nsecs = tv->tv_usec * 1000;
 
@@ -53,7 +53,7 @@ static inline xnticks_t tv2ns(const struct timeval *tv)
 	return nsecs;
 }
 
-static inline void ticks2tv(struct timeval *tv, xnticks_t ticks)
+static inline void ticks2tv(struct __kernel_old_timeval *tv, xnticks_t ticks)
 {
 	unsigned long nsecs;
 
diff --git a/kernel/cobalt/posix/compat.c b/kernel/cobalt/posix/compat.c
index e53e72e0c..2ffc0dbdf 100644
--- a/kernel/cobalt/posix/compat.c
+++ b/kernel/cobalt/posix/compat.c
@@ -60,7 +60,7 @@ int sys32_put_itimerspec(struct compat_itimerspec __user *cits,
 }
 EXPORT_SYMBOL_GPL(sys32_put_itimerspec);
 
-int sys32_get_timeval(struct timeval *tv,
+int sys32_get_timeval(struct __kernel_old_timeval *tv,
 		      const struct compat_timeval __user *ctv)
 {
 	return (ctv == NULL ||
@@ -71,7 +71,7 @@ int sys32_get_timeval(struct timeval *tv,
 EXPORT_SYMBOL_GPL(sys32_get_timeval);
 
 int sys32_put_timeval(struct compat_timeval __user *ctv,
-		      const struct timeval *tv)
+		      const struct __kernel_old_timeval *tv)
 {
 	return (ctv == NULL ||
 		!access_wok(ctv, sizeof(*ctv)) ||
diff --git a/kernel/cobalt/posix/io.c b/kernel/cobalt/posix/io.c
index f35aaf8cd..e9908feeb 100644
--- a/kernel/cobalt/posix/io.c
+++ b/kernel/cobalt/posix/io.c
@@ -212,13 +212,13 @@ int __cobalt_select_bind_all(struct xnselector *selector,
 	return 0;
 }
 
-/* int select(int, fd_set *, fd_set *, fd_set *, struct timeval *) */
+/* int select(int, fd_set *, fd_set *, fd_set *, struct __kernel_old_timeval *) */
 COBALT_SYSCALL(select, primary,
 	       (int nfds,
 		fd_set __user *u_rfds,
 		fd_set __user *u_wfds,
 		fd_set __user *u_xfds,
-		struct timeval __user *u_tv))
+		struct __kernel_old_timeval __user *u_tv))
 {
 	fd_set __user *ufd_sets[XNSELECT_MAX_TYPES] = {
 		[XNSELECT_READ] = u_rfds,
@@ -234,7 +234,7 @@ COBALT_SYSCALL(select, primary,
 	xntmode_t mode = XN_RELATIVE;
 	struct xnselector *selector;
 	struct xnthread *curr;
-	struct timeval tv;
+	struct __kernel_old_timeval tv;
 	size_t fds_size;
 	int i, err;
 
diff --git a/kernel/cobalt/posix/io.h b/kernel/cobalt/posix/io.h
index 6f20dbedd..82187cc7b 100644
--- a/kernel/cobalt/posix/io.h
+++ b/kernel/cobalt/posix/io.h
@@ -71,6 +71,6 @@ COBALT_SYSCALL_DECL(select,
 		     fd_set __user *u_rfds,
 		     fd_set __user *u_wfds,
 		     fd_set __user *u_xfds,
-		     struct timeval __user *u_tv));
+		     struct __kernel_old_timeval __user *u_tv));
 
 #endif /* !_COBALT_POSIX_IO_H */
diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
index c2fd6a1e0..cb02dacd3 100644
--- a/kernel/cobalt/posix/syscall32.c
+++ b/kernel/cobalt/posix/syscall32.c
@@ -715,7 +715,7 @@ COBALT_SYSCALL32emu(select, nonrestartable,
 	xntmode_t mode = XN_RELATIVE;
 	struct xnselector *selector;
 	struct xnthread *curr;
-	struct timeval tv;
+	struct __kernel_old_timeval tv;
 	xnsticks_t diff;
 	size_t fds_size;
 	int i, err;
diff --git a/kernel/drivers/ipc/bufp.c b/kernel/drivers/ipc/bufp.c
index d45480f94..5692f3146 100644
--- a/kernel/drivers/ipc/bufp.c
+++ b/kernel/drivers/ipc/bufp.c
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
+#include <linux/time.h>
 #include <cobalt/kernel/heap.h>
 #include <cobalt/kernel/map.h>
 #include <cobalt/kernel/bufd.h>
@@ -818,7 +819,7 @@ static int __bufp_setsockopt(struct bufp_socket *sk,
 {
 	struct _rtdm_setsockopt_args sopt;
 	struct rtipc_port_label plabel;
-	struct timeval tv;
+	struct __kernel_old_timeval tv;
 	rtdm_lockctx_t s;
 	size_t len;
 	int ret;
@@ -907,7 +908,7 @@ static int __bufp_getsockopt(struct bufp_socket *sk,
 {
 	struct _rtdm_getsockopt_args sopt;
 	struct rtipc_port_label plabel;
-	struct timeval tv;
+	struct __kernel_old_timeval tv;
 	rtdm_lockctx_t s;
 	socklen_t len;
 	int ret;
diff --git a/kernel/drivers/ipc/iddp.c b/kernel/drivers/ipc/iddp.c
index f31b9bb66..3a9de845f 100644
--- a/kernel/drivers/ipc/iddp.c
+++ b/kernel/drivers/ipc/iddp.c
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
+#include <linux/time.h>
 #include <cobalt/kernel/heap.h>
 #include <cobalt/kernel/bufd.h>
 #include <cobalt/kernel/map.h>
@@ -700,7 +701,7 @@ static int __iddp_setsockopt(struct iddp_socket *sk,
 {
 	struct _rtdm_setsockopt_args sopt;
 	struct rtipc_port_label plabel;
-	struct timeval tv;
+	struct __kernel_old_timeval tv;
 	rtdm_lockctx_t s;
 	size_t len;
 	int ret;
@@ -789,7 +790,7 @@ static int __iddp_getsockopt(struct iddp_socket *sk,
 {
 	struct _rtdm_getsockopt_args sopt;
 	struct rtipc_port_label plabel;
-	struct timeval tv;
+	struct __kernel_old_timeval tv;
 	rtdm_lockctx_t s;
 	socklen_t len;
 	int ret;
diff --git a/kernel/drivers/ipc/internal.h b/kernel/drivers/ipc/internal.h
index 7c09dd312..919a5d978 100644
--- a/kernel/drivers/ipc/internal.h
+++ b/kernel/drivers/ipc/internal.h
@@ -21,6 +21,7 @@
 #define _RTIPC_INTERNAL_H
 
 #include <linux/uio.h>
+#include <linux/time.h>
 #include <cobalt/kernel/registry.h>
 #include <cobalt/kernel/clock.h>
 #include <cobalt/kernel/select.h>
@@ -65,7 +66,7 @@ static inline void *rtipc_fd_to_state(struct rtdm_fd *fd)
 	return p->state;
 }
 
-static inline nanosecs_rel_t rtipc_timeval_to_ns(const struct timeval *tv)
+static inline nanosecs_rel_t rtipc_timeval_to_ns(const struct __kernel_old_timeval *tv)
 {
 	nanosecs_rel_t ns = tv->tv_usec * 1000;
 
@@ -75,7 +76,7 @@ static inline nanosecs_rel_t rtipc_timeval_to_ns(const struct timeval *tv)
 	return ns;
 }
 
-static inline void rtipc_ns_to_timeval(struct timeval *tv, nanosecs_rel_t ns)
+static inline void rtipc_ns_to_timeval(struct __kernel_old_timeval *tv, nanosecs_rel_t ns)
 {
 	unsigned long nsecs;
 
@@ -101,11 +102,11 @@ int rtipc_get_sockoptin(struct rtdm_fd *fd,
 			struct _rtdm_setsockopt_args *sopt,
 			const void *arg);
 
-int rtipc_get_timeval(struct rtdm_fd *fd, struct timeval *tv,
+int rtipc_get_timeval(struct rtdm_fd *fd, struct __kernel_old_timeval *tv,
 		      const void *arg, size_t arglen);
 
 int rtipc_put_timeval(struct rtdm_fd *fd, void *arg,
-		      const struct timeval *tv, size_t arglen);
+		      const struct __kernel_old_timeval *tv, size_t arglen);
 
 int rtipc_get_length(struct rtdm_fd *fd, size_t *lenp,
 		     const void *arg, size_t arglen);
diff --git a/kernel/drivers/ipc/rtipc.c b/kernel/drivers/ipc/rtipc.c
index 99f73202d..b6fafdb41 100644
--- a/kernel/drivers/ipc/rtipc.c
+++ b/kernel/drivers/ipc/rtipc.c
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
+#include <linux/time.h>
 #include <rtdm/ipc.h>
 #include <rtdm/compat.h>
 #include "internal.h"
@@ -267,7 +268,7 @@ int rtipc_get_sockoptin(struct rtdm_fd *fd, struct _rtdm_setsockopt_args *sopt,
 	return rtdm_safe_copy_from_user(fd, sopt, arg, sizeof(*sopt));
 }
 
-int rtipc_get_timeval(struct rtdm_fd *fd, struct timeval *tv,
+int rtipc_get_timeval(struct rtdm_fd *fd, struct __kernel_old_timeval *tv,
 		      const void *arg, size_t arglen)
 {
 #ifdef CONFIG_XENO_ARCH_SYS3264
@@ -282,7 +283,7 @@ int rtipc_get_timeval(struct rtdm_fd *fd, struct timeval *tv,
 		return -EINVAL;
 
 	if (!rtdm_fd_is_user(fd)) {
-		*tv = *(struct timeval *)arg;
+		*tv = *(struct __kernel_old_timeval *)arg;
 		return 0;
 	}
 
@@ -290,7 +291,7 @@ int rtipc_get_timeval(struct rtdm_fd *fd, struct timeval *tv,
 }
 
 int rtipc_put_timeval(struct rtdm_fd *fd, void *arg,
-		      const struct timeval *tv, size_t arglen)
+		      const struct __kernel_old_timeval *tv, size_t arglen)
 {
 #ifdef CONFIG_XENO_ARCH_SYS3264
 	if (rtdm_fd_is_compat(fd)) {
@@ -304,7 +305,7 @@ int rtipc_put_timeval(struct rtdm_fd *fd, void *arg,
 		return -EINVAL;
 
 	if (!rtdm_fd_is_user(fd)) {
-		*(struct timeval *)arg = *tv;
+		*(struct __kernel_old_timeval *)arg = *tv;
 		return 0;
 	}
 
diff --git a/kernel/drivers/ipc/xddp.c b/kernel/drivers/ipc/xddp.c
index c9236a229..25dd68a9d 100644
--- a/kernel/drivers/ipc/xddp.c
+++ b/kernel/drivers/ipc/xddp.c
@@ -21,6 +21,7 @@
 #include <linux/string.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
+#include <linux/time.h>
 #include <cobalt/kernel/heap.h>
 #include <cobalt/kernel/bufd.h>
 #include <cobalt/kernel/pipe.h>
@@ -855,7 +856,7 @@ static int __xddp_setsockopt(struct xddp_socket *sk,
 	int (*monitor)(struct rtdm_fd *fd, int event, long arg);
 	struct _rtdm_setsockopt_args sopt;
 	struct rtipc_port_label plabel;
-	struct timeval tv;
+	struct __kernel_old_timeval tv;
 	rtdm_lockctx_t s;
 	size_t len;
 	int ret;
@@ -961,7 +962,7 @@ static int __xddp_getsockopt(struct xddp_socket *sk,
 {
 	struct _rtdm_getsockopt_args sopt;
 	struct rtipc_port_label plabel;
-	struct timeval tv;
+	struct __kernel_old_timeval tv;
 	rtdm_lockctx_t s;
 	socklen_t len;
 	int ret;
diff --git a/kernel/drivers/net/stack/ipv4/tcp/tcp.c b/kernel/drivers/net/stack/ipv4/tcp/tcp.c
index 54d6f7925..08753e48a 100644
--- a/kernel/drivers/net/stack/ipv4/tcp/tcp.c
+++ b/kernel/drivers/net/stack/ipv4/tcp/tcp.c
@@ -1742,7 +1742,7 @@ static int rt_tcp_setsockopt(struct rtdm_fd *fd, struct tcp_socket *ts,
 			     socklen_t optlen)
 {
 	/* uint64_t val; */
-	struct timeval tv;
+	struct __kernel_old_timeval tv;
 	rtdm_lockctx_t context;
 
 	switch (optname) {
-- 
2.26.2



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

* [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-02-20 15:18 [PATCH 1/5] cobalt/kernel: y2038: convert struct timeval to __kernel_old_timeval Philippe Gerum
@ 2021-02-20 15:18 ` Philippe Gerum
  2021-02-21  2:17   ` chensong
                     ` (2 more replies)
  2021-02-20 15:18 ` [PATCH 3/5] lib: y2038: convert to internal timespec type Philippe Gerum
                   ` (2 subsequent siblings)
  3 siblings, 3 replies; 57+ messages in thread
From: Philippe Gerum @ 2021-02-20 15:18 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai, Philippe Gerum

From: Philippe Gerum <rpm@xenomai.org>

As internal interfaces are gradually being made y2038-safe, the
timespec64 type should be used internally by the kernel to represent
time values. Apply the same reasoning to Cobalt.

We still use a legacy y2038-unsafe timespec type at the kernel<->user
interface boundary (struct __user_old_timespec) until libcobalt is
y2038-safe.

Signed-off-by: Philippe Gerum <rpm@xenomai.org>
---
 include/cobalt/kernel/clock.h                 |  6 +-
 include/cobalt/kernel/compat.h                |  4 +-
 .../cobalt/kernel/dovetail/pipeline/clock.h   |  4 +-
 include/cobalt/kernel/ipipe/pipeline/clock.h  |  4 +-
 include/cobalt/kernel/rtdm/fd.h               |  2 +-
 include/cobalt/uapi/kernel/types.h            | 10 ++++
 include/cobalt/uapi/sched.h                   | 12 ++--
 .../include/asm-generic/xenomai/syscall.h     | 58 +++++++++++++++++++
 kernel/cobalt/ipipe/clock.c                   |  2 +-
 kernel/cobalt/posix/clock.c                   | 38 ++++++------
 kernel/cobalt/posix/clock.h                   | 39 +++++++++----
 kernel/cobalt/posix/compat.c                  | 46 ++++++++++-----
 kernel/cobalt/posix/cond.c                    | 11 ++--
 kernel/cobalt/posix/cond.h                    |  4 +-
 kernel/cobalt/posix/event.c                   |  8 +--
 kernel/cobalt/posix/event.h                   |  4 +-
 kernel/cobalt/posix/io.c                      |  6 +-
 kernel/cobalt/posix/io.h                      |  2 +-
 kernel/cobalt/posix/monitor.c                 |  8 +--
 kernel/cobalt/posix/monitor.h                 |  4 +-
 kernel/cobalt/posix/mqueue.c                  | 18 +++---
 kernel/cobalt/posix/mqueue.h                  |  8 +--
 kernel/cobalt/posix/mutex.c                   | 10 ++--
 kernel/cobalt/posix/mutex.h                   |  6 +-
 kernel/cobalt/posix/sched.c                   | 16 ++---
 kernel/cobalt/posix/sem.c                     |  8 +--
 kernel/cobalt/posix/sem.h                     |  4 +-
 kernel/cobalt/posix/signal.c                  |  6 +-
 kernel/cobalt/posix/signal.h                  |  4 +-
 kernel/cobalt/posix/syscall32.c               | 26 ++++-----
 kernel/cobalt/posix/syscall32.h               |  2 +-
 kernel/cobalt/posix/thread.c                  |  6 +-
 kernel/cobalt/rtdm/fd.c                       |  4 +-
 kernel/cobalt/trace/cobalt-posix.h            | 30 +++++-----
 34 files changed, 260 insertions(+), 160 deletions(-)

diff --git a/include/cobalt/kernel/clock.h b/include/cobalt/kernel/clock.h
index bbf34c53c..1c99173ff 100644
--- a/include/cobalt/kernel/clock.h
+++ b/include/cobalt/kernel/clock.h
@@ -54,7 +54,7 @@ struct xnclock {
 		xnticks_t (*read_raw)(struct xnclock *clock);
 		xnticks_t (*read_monotonic)(struct xnclock *clock);
 		int (*set_time)(struct xnclock *clock,
-				const struct timespec *ts);
+				const struct timespec64 *ts);
 		xnsticks_t (*ns_to_ticks)(struct xnclock *clock,
 					  xnsticks_t ns);
 		xnsticks_t (*ticks_to_ns)(struct xnclock *clock,
@@ -211,7 +211,7 @@ static inline xnticks_t xnclock_read_monotonic(struct xnclock *clock)
 }
 
 static inline int xnclock_set_time(struct xnclock *clock,
-				   const struct timespec *ts)
+				   const struct timespec64 *ts)
 {
 	if (likely(clock == &nkclock))
 		return -EINVAL;
@@ -264,7 +264,7 @@ static inline xnticks_t xnclock_read_monotonic(struct xnclock *clock)
 }
 
 static inline int xnclock_set_time(struct xnclock *clock,
-				   const struct timespec *ts)
+				   const struct timespec64 *ts)
 {
 	/*
 	 * There is no way to change the core clock's idea of time.
diff --git a/include/cobalt/kernel/compat.h b/include/cobalt/kernel/compat.h
index 313b6251b..c57ef6532 100644
--- a/include/cobalt/kernel/compat.h
+++ b/include/cobalt/kernel/compat.h
@@ -86,11 +86,11 @@ struct compat_rtdm_mmap_request {
 	int flags;
 };
 
-int sys32_get_timespec(struct timespec *ts,
+int sys32_get_timespec(struct timespec64 *ts,
 		       const struct compat_timespec __user *cts);
 
 int sys32_put_timespec(struct compat_timespec __user *cts,
-		       const struct timespec *ts);
+		       const struct timespec64 *ts);
 
 int sys32_get_itimerspec(struct itimerspec *its,
 			 const struct compat_itimerspec __user *cits);
diff --git a/include/cobalt/kernel/dovetail/pipeline/clock.h b/include/cobalt/kernel/dovetail/pipeline/clock.h
index 933e100ba..19e3d8986 100644
--- a/include/cobalt/kernel/dovetail/pipeline/clock.h
+++ b/include/cobalt/kernel/dovetail/pipeline/clock.h
@@ -8,7 +8,7 @@
 #include <cobalt/uapi/kernel/types.h>
 #include <cobalt/kernel/assert.h>
 
-struct timespec;
+struct timespec64;
 
 static inline u64 pipeline_read_cycle_counter(void)
 {
@@ -49,7 +49,7 @@ static inline const char *pipeline_clock_name(void)
 	return "?";
 }
 
-static inline int pipeline_get_host_time(struct timespec *tp)
+static inline int pipeline_get_host_time(struct timespec64 *tp)
 {
 	/* Convert ktime_get_real_fast_ns() to timespec. */
 	TODO();
diff --git a/include/cobalt/kernel/ipipe/pipeline/clock.h b/include/cobalt/kernel/ipipe/pipeline/clock.h
index fa7ac2a5e..d35aea17b 100644
--- a/include/cobalt/kernel/ipipe/pipeline/clock.h
+++ b/include/cobalt/kernel/ipipe/pipeline/clock.h
@@ -7,7 +7,7 @@
 
 #include <linux/ipipe_tickdev.h>
 
-struct timespec;
+struct timespec64;
 
 static inline u64 pipeline_read_cycle_counter(void)
 {
@@ -31,7 +31,7 @@ static inline const char *pipeline_clock_name(void)
 	return ipipe_clock_name();
 }
 
-int pipeline_get_host_time(struct timespec *tp);
+int pipeline_get_host_time(struct timespec64 *tp);
 
 void pipeline_update_clock_freq(unsigned long long freq);
 
diff --git a/include/cobalt/kernel/rtdm/fd.h b/include/cobalt/kernel/rtdm/fd.h
index 289065082..37a09c43e 100644
--- a/include/cobalt/kernel/rtdm/fd.h
+++ b/include/cobalt/kernel/rtdm/fd.h
@@ -380,7 +380,7 @@ int __rtdm_fd_recvmmsg(int ufd, void __user *u_msgvec, unsigned int vlen,
 		       unsigned int flags, void __user *u_timeout,
 		       int (*get_mmsg)(struct mmsghdr *mmsg, void __user *u_mmsg),
 		       int (*put_mmsg)(void __user **u_mmsg_p, const struct mmsghdr *mmsg),
-		       int (*get_timespec)(struct timespec *ts, const void __user *u_ts));
+		       int (*get_timespec)(struct timespec64 *ts, const void __user *u_ts));
 
 ssize_t rtdm_fd_sendmsg(int ufd, const struct user_msghdr *msg,
 			int flags);
diff --git a/include/cobalt/uapi/kernel/types.h b/include/cobalt/uapi/kernel/types.h
index ee5bbadca..8ce9b03df 100644
--- a/include/cobalt/uapi/kernel/types.h
+++ b/include/cobalt/uapi/kernel/types.h
@@ -57,4 +57,14 @@ static inline xnhandle_t xnhandle_get_id(xnhandle_t handle)
 	return handle & ~XN_HANDLE_TRANSIENT_MASK;
 }
 
+/*
+ * Our representation of time at the kernel<->user interface boundary
+ * at the moment, until we have fully transitioned to a y2038-safe
+ * implementation in libcobalt.
+ */
+struct __user_old_timespec {
+	long  tv_sec;
+	long  tv_nsec;
+};
+
 #endif /* !_COBALT_UAPI_KERNEL_TYPES_H */
diff --git a/include/cobalt/uapi/sched.h b/include/cobalt/uapi/sched.h
index b672095c3..14095870f 100644
--- a/include/cobalt/uapi/sched.h
+++ b/include/cobalt/uapi/sched.h
@@ -18,6 +18,8 @@
 #ifndef _COBALT_UAPI_SCHED_H
 #define _COBALT_UAPI_SCHED_H
 
+#include <cobalt/uapi/kernel/types.h>
+
 #define SCHED_COBALT		42
 #define SCHED_WEAK		43
 
@@ -31,15 +33,15 @@
 
 struct __sched_ss_param {
 	int __sched_low_priority;
-	struct timespec __sched_repl_period;
-	struct timespec __sched_init_budget;
+	struct __user_old_timespec __sched_repl_period;
+	struct __user_old_timespec __sched_init_budget;
 	int __sched_max_repl;
 };
 
 #define sched_rr_quantum	sched_u.rr.__sched_rr_quantum
 
 struct __sched_rr_param {
-	struct timespec __sched_rr_quantum;
+	struct __user_old_timespec __sched_rr_quantum;
 };
 
 #ifndef SCHED_TP
@@ -52,8 +54,8 @@ struct __sched_tp_param {
 };
 
 struct sched_tp_window {
-	struct timespec offset;
-	struct timespec duration;
+	struct __user_old_timespec offset;
+	struct __user_old_timespec duration;
 	int ptid;
 };
 
diff --git a/kernel/cobalt/include/asm-generic/xenomai/syscall.h b/kernel/cobalt/include/asm-generic/xenomai/syscall.h
index 0d50d4107..05a7d2868 100644
--- a/kernel/cobalt/include/asm-generic/xenomai/syscall.h
+++ b/kernel/cobalt/include/asm-generic/xenomai/syscall.h
@@ -26,6 +26,7 @@
 #include <asm/xenomai/wrappers.h>
 #include <asm/xenomai/machine.h>
 #include <cobalt/uapi/asm-generic/syscall.h>
+#include <cobalt/uapi/kernel/types.h>
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
 #define access_rok(addr, size)	access_ok((addr), (size))
@@ -81,6 +82,63 @@ static inline int cobalt_strncpy_from_user(char *dst, const char __user *src,
 	return __xn_strncpy_from_user(dst, src, count);
 }
 
+#if __BITS_PER_LONG == 64
+
+/*
+ * NOTE: those copy helpers won't work in compat mode: use
+ * sys32_get_timespec(), sys32_put_timespec() instead.
+ */
+
+static inline int cobalt_get_u_timespec(struct timespec64 *dst,
+			const struct __user_old_timespec __user *src)
+{
+	return cobalt_copy_from_user(dst, src, sizeof(*dst));
+}
+
+static inline int cobalt_put_u_timespec(
+	struct __user_old_timespec __user *dst,
+	const struct timespec64 *src)
+{
+	return cobalt_copy_to_user(dst, src, sizeof(*dst));
+}
+
+#else /* __BITS_PER_LONG == 32 */
+
+static inline int cobalt_get_u_timespec(struct timespec64 *dst,
+			const struct __user_old_timespec __user *src)
+{
+	struct __user_old_timespec u_ts;
+	int ret;
+
+	ret = cobalt_copy_from_user(&u_ts, src, sizeof(u_ts));
+	if (ret)
+		return ret;
+
+	dst->tv_sec = u_ts.tv_sec;
+	dst->tv_nsec = u_ts.tv_nsec;
+
+	return 0;
+}
+
+static inline int cobalt_put_u_timespec(
+	struct __user_old_timespec __user *dst,
+	const struct timespec64 *src)
+{
+	struct __user_old_timespec u_ts;
+	int ret;
+
+	u_ts.tv_sec = src->tv_sec;
+	u_ts.tv_nsec = src->tv_nsec;
+
+	ret = cobalt_copy_to_user(dst, &u_ts, sizeof(*dst));
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+#endif
+
 /* 32bit syscall emulation */
 #define __COBALT_COMPAT_BIT	0x1
 /* 32bit syscall emulation - extended form */
diff --git a/kernel/cobalt/ipipe/clock.c b/kernel/cobalt/ipipe/clock.c
index 606c6bf8c..d40b0ac89 100644
--- a/kernel/cobalt/ipipe/clock.c
+++ b/kernel/cobalt/ipipe/clock.c
@@ -67,7 +67,7 @@ EXPORT_SYMBOL_GPL(xnclock_core_ticks_to_ns);
 EXPORT_SYMBOL_GPL(xnclock_core_ticks_to_ns_rounded);
 EXPORT_SYMBOL_GPL(xnclock_core_ns_to_ticks);
 
-int pipeline_get_host_time(struct timespec *tp)
+int pipeline_get_host_time(struct timespec64 *tp)
 {
 #ifdef CONFIG_IPIPE_HAVE_HOSTRT
 	struct xnvdso_hostrt_data *hostrt_data;
diff --git a/kernel/cobalt/posix/clock.c b/kernel/cobalt/posix/clock.c
index e957dd956..4a3365d2a 100644
--- a/kernel/cobalt/posix/clock.c
+++ b/kernel/cobalt/posix/clock.c
@@ -51,7 +51,7 @@ DECLARE_BITMAP(cobalt_clock_extids, COBALT_MAX_EXTCLOCKS);
 	__val;							\
 })
 
-int __cobalt_clock_getres(clockid_t clock_id, struct timespec *ts)
+int __cobalt_clock_getres(clockid_t clock_id, struct timespec64 *ts)
 {
 	xnticks_t ns;
 	int ret;
@@ -75,16 +75,16 @@ int __cobalt_clock_getres(clockid_t clock_id, struct timespec *ts)
 }
 
 COBALT_SYSCALL(clock_getres, current,
-	       (clockid_t clock_id, struct timespec __user *u_ts))
+	       (clockid_t clock_id, struct __user_old_timespec __user *u_ts))
 {
-	struct timespec ts;
+	struct timespec64 ts;
 	int ret;
 
 	ret = __cobalt_clock_getres(clock_id, &ts);
 	if (ret)
 		return ret;
 
-	if (u_ts && cobalt_copy_to_user(u_ts, &ts, sizeof(ts)))
+	if (u_ts && cobalt_put_u_timespec(u_ts, &ts))
 		return -EFAULT;
 
 	trace_cobalt_clock_getres(clock_id, &ts);
@@ -92,7 +92,7 @@ COBALT_SYSCALL(clock_getres, current,
 	return 0;
 }
 
-int __cobalt_clock_gettime(clockid_t clock_id, struct timespec *ts)
+int __cobalt_clock_gettime(clockid_t clock_id, struct timespec64 *ts)
 {
 	xnticks_t ns;
 	int ret;
@@ -122,16 +122,16 @@ int __cobalt_clock_gettime(clockid_t clock_id, struct timespec *ts)
 }
 
 COBALT_SYSCALL(clock_gettime, current,
-	       (clockid_t clock_id, struct timespec __user *u_ts))
+	       (clockid_t clock_id, struct __user_old_timespec __user *u_ts))
 {
-	struct timespec ts;
+	struct timespec64 ts;
 	int ret;
 
 	ret = __cobalt_clock_gettime(clock_id, &ts);
 	if (ret)
 		return ret;
 
-	if (cobalt_copy_to_user(u_ts, &ts, sizeof(*u_ts)))
+	if (cobalt_put_u_timespec(u_ts, &ts))
 		return -EFAULT;
 
 	trace_cobalt_clock_gettime(clock_id, &ts);
@@ -139,7 +139,7 @@ COBALT_SYSCALL(clock_gettime, current,
 	return 0;
 }
 
-int __cobalt_clock_settime(clockid_t clock_id, const struct timespec *ts)
+int __cobalt_clock_settime(clockid_t clock_id, const struct timespec64 *ts)
 {
 	int _ret, ret = 0;
 	xnticks_t now;
@@ -188,11 +188,11 @@ int __cobalt_clock_adjtime(clockid_t clock_id, struct timex *tx)
 }
 
 COBALT_SYSCALL(clock_settime, current,
-	       (clockid_t clock_id, const struct timespec __user *u_ts))
+	       (clockid_t clock_id, const struct __user_old_timespec __user *u_ts))
 {
-	struct timespec ts;
+	struct timespec64 ts;
 
-	if (cobalt_copy_from_user(&ts, u_ts, sizeof(ts)))
+	if (cobalt_get_u_timespec(&ts, u_ts))
 		return -EFAULT;
 
 	return __cobalt_clock_settime(clock_id, &ts);
@@ -215,8 +215,8 @@ COBALT_SYSCALL(clock_adjtime, current,
 }
 
 int __cobalt_clock_nanosleep(clockid_t clock_id, int flags,
-			     const struct timespec *rqt,
-			     struct timespec *rmt)
+			     const struct timespec64 *rqt,
+			     struct timespec64 *rmt)
 {
 	struct restart_block *restart;
 	struct xnthread *cur;
@@ -296,21 +296,21 @@ int __cobalt_clock_nanosleep(clockid_t clock_id, int flags,
 
 COBALT_SYSCALL(clock_nanosleep, primary,
 	       (clockid_t clock_id, int flags,
-		const struct timespec __user *u_rqt,
-		struct timespec __user *u_rmt))
+		const struct __user_old_timespec __user *u_rqt,
+		struct __user_old_timespec __user *u_rmt))
 {
-	struct timespec rqt, rmt, *rmtp = NULL;
+	struct timespec64 rqt, rmt, *rmtp = NULL;
 	int ret;
 
 	if (u_rmt)
 		rmtp = &rmt;
 
-	if (cobalt_copy_from_user(&rqt, u_rqt, sizeof(rqt)))
+	if (cobalt_get_u_timespec(&rqt, u_rqt))
 		return -EFAULT;
 
 	ret = __cobalt_clock_nanosleep(clock_id, flags, &rqt, rmtp);
 	if (ret == -EINTR && flags == 0 && rmtp) {
-		if (cobalt_copy_to_user(u_rmt, rmtp, sizeof(*u_rmt)))
+		if (cobalt_put_u_timespec(u_rmt, rmtp))
 			return -EFAULT;
 	}
 
diff --git a/kernel/cobalt/posix/clock.h b/kernel/cobalt/posix/clock.h
index 7cb161df2..7e45fdcc6 100644
--- a/kernel/cobalt/posix/clock.h
+++ b/kernel/cobalt/posix/clock.h
@@ -28,12 +28,27 @@
 
 struct xnclock;
 
-static inline void ns2ts(struct timespec *ts, xnticks_t nsecs)
+static inline void ns2ts(struct timespec64 *ts, xnticks_t nsecs)
 {
 	ts->tv_sec = xnclock_divrem_billion(nsecs, &ts->tv_nsec);
 }
 
-static inline xnticks_t ts2ns(const struct timespec *ts)
+static inline void u_ns2ts(struct __user_old_timespec *ts, xnticks_t nsecs)
+{
+	ts->tv_sec = xnclock_divrem_billion(nsecs, &ts->tv_nsec);
+}
+
+static inline xnticks_t ts2ns(const struct timespec64 *ts)
+{
+	xnticks_t nsecs = ts->tv_nsec;
+
+	if (ts->tv_sec)
+		nsecs += (xnticks_t)ts->tv_sec * ONE_BILLION;
+
+	return nsecs;
+}
+
+static inline xnticks_t u_ts2ns(const struct __user_old_timespec *ts)
 {
 	xnticks_t nsecs = ts->tv_nsec;
 
@@ -80,37 +95,37 @@ static inline int clock_flag(int flag, clockid_t clock_id)
 }
 
 int __cobalt_clock_getres(clockid_t clock_id,
-			  struct timespec *ts);
+			  struct timespec64 *ts);
 
 int __cobalt_clock_gettime(clockid_t clock_id,
-			   struct timespec *ts);
+			   struct timespec64 *ts);
 
 int __cobalt_clock_settime(clockid_t clock_id,
-			   const struct timespec *ts);
+			   const struct timespec64 *ts);
 
 int __cobalt_clock_adjtime(clockid_t clock_id,
 			   struct timex *tx);
 
 int __cobalt_clock_nanosleep(clockid_t clock_id, int flags,
-			     const struct timespec *rqt,
-			     struct timespec *rmt);
+			     const struct timespec64 *rqt,
+			     struct timespec64 *rmt);
 
 COBALT_SYSCALL_DECL(clock_getres,
-		    (clockid_t clock_id, struct timespec __user *u_ts));
+		    (clockid_t clock_id, struct __user_old_timespec __user *u_ts));
 
 COBALT_SYSCALL_DECL(clock_gettime,
-		    (clockid_t clock_id, struct timespec __user *u_ts));
+		    (clockid_t clock_id, struct __user_old_timespec __user *u_ts));
 
 COBALT_SYSCALL_DECL(clock_settime,
-		    (clockid_t clock_id, const struct timespec __user *u_ts));
+		    (clockid_t clock_id, const struct __user_old_timespec __user *u_ts));
 
 COBALT_SYSCALL_DECL(clock_adjtime,
 		    (clockid_t clock_id, struct timex __user *u_tx));
 
 COBALT_SYSCALL_DECL(clock_nanosleep,
 		    (clockid_t clock_id, int flags,
-		     const struct timespec __user *u_rqt,
-		     struct timespec __user *u_rmt));
+		     const struct __user_old_timespec __user *u_rqt,
+		     struct __user_old_timespec __user *u_rmt));
 
 int cobalt_clock_register(struct xnclock *clock,
 			  const cpumask_t *affinity,
diff --git a/kernel/cobalt/posix/compat.c b/kernel/cobalt/posix/compat.c
index 2ffc0dbdf..185295082 100644
--- a/kernel/cobalt/posix/compat.c
+++ b/kernel/cobalt/posix/compat.c
@@ -22,23 +22,41 @@
 #include <asm/xenomai/syscall.h>
 #include <xenomai/posix/mqueue.h>
 
-int sys32_get_timespec(struct timespec *ts,
-		       const struct compat_timespec __user *cts)
+int sys32_get_timespec(struct timespec64 *ts,
+		       const struct compat_timespec __user *u_cts)
 {
-	return (cts == NULL ||
-		!access_rok(cts, sizeof(*cts)) ||
-		__xn_get_user(ts->tv_sec, &cts->tv_sec) ||
-		__xn_get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
+	struct compat_timespec cts;
+
+	if (u_cts == NULL || !access_rok(u_cts, sizeof(*u_cts)))
+		return -EFAULT;
+
+	if (__xn_get_user(cts.tv_sec, &u_cts->tv_sec) ||
+		__xn_get_user(cts.tv_nsec, &u_cts->tv_nsec))
+		return -EFAULT;
+
+	ts->tv_sec = cts.tv_sec;
+	ts->tv_nsec = cts.tv_nsec;
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(sys32_get_timespec);
 
-int sys32_put_timespec(struct compat_timespec __user *cts,
-		       const struct timespec *ts)
+int sys32_put_timespec(struct compat_timespec __user *u_cts,
+		       const struct timespec64 *ts)
 {
-	return (cts == NULL ||
-		!access_wok(cts, sizeof(*cts)) ||
-		__xn_put_user(ts->tv_sec, &cts->tv_sec) ||
-		__xn_put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
+	struct compat_timespec cts;
+
+	if (u_cts == NULL || !access_wok(u_cts, sizeof(*u_cts)))
+		return -EFAULT;
+
+	cts.tv_sec = ts->tv_sec;
+	cts.tv_nsec = ts->tv_nsec;
+
+	if (__xn_put_user(cts.tv_sec, &u_cts->tv_sec) ||
+	    __xn_put_user(cts.tv_nsec, &u_cts->tv_nsec))
+		return -EFAULT;
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(sys32_put_timespec);
 
@@ -478,7 +496,7 @@ int sys32_get_iovec(struct iovec *iov,
 	const struct compat_iovec __user *p;
 	struct compat_iovec ciov;
 	int ret, n;
-	
+
 	for (n = 0, p = u_ciov; n < ciovlen; n++, p++) {
 		ret = cobalt_copy_from_user(&ciov, p, sizeof(ciov));
 		if (ret)
@@ -498,7 +516,7 @@ int sys32_put_iovec(struct compat_iovec __user *u_ciov,
 	struct compat_iovec __user *p;
 	struct compat_iovec ciov;
 	int ret, n;
-	
+
 	for (n = 0, p = u_ciov; n < iovlen; n++, p++) {
 		ciov.iov_base = ptr_to_compat(iov[n].iov_base);
 		ciov.iov_len = iov[n].iov_len;
diff --git a/kernel/cobalt/posix/cond.c b/kernel/cobalt/posix/cond.c
index 35a8f7176..bb18fe316 100644
--- a/kernel/cobalt/posix/cond.c
+++ b/kernel/cobalt/posix/cond.c
@@ -270,25 +270,24 @@ struct us_cond_data {
 	int err;
 };
 
-static inline int cond_fetch_timeout(struct timespec *ts,
+static inline int cond_fetch_timeout(struct timespec64 *ts,
 				     const void __user *u_ts)
 {
-	return u_ts == NULL ? -EFAULT :
-		cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
+	return u_ts == NULL ? -EFAULT :	cobalt_get_u_timespec(ts, u_ts);
 }
 
 int __cobalt_cond_wait_prologue(struct cobalt_cond_shadow __user *u_cnd,
 				struct cobalt_mutex_shadow __user *u_mx,
 				int *u_err,
 				void __user *u_ts,
-				int (*fetch_timeout)(struct timespec *ts,
+				int (*fetch_timeout)(struct timespec64 *ts,
 						     const void __user *u_ts))
 {
 	struct xnthread *cur = xnthread_current();
 	struct cobalt_cond *cond;
 	struct cobalt_mutex *mx;
 	struct us_cond_data d;
-	struct timespec ts;
+	struct timespec64 ts;
 	xnhandle_t handle;
 	int err, perr = 0;
 	__u32 offset;
@@ -349,7 +348,7 @@ COBALT_SYSCALL(cond_wait_prologue, nonrestartable,
 		struct cobalt_mutex_shadow __user *u_mx,
 		int *u_err,
 		unsigned int timed,
-		struct timespec __user *u_ts))
+		struct __user_old_timespec __user *u_ts))
 {
 	return __cobalt_cond_wait_prologue(u_cnd, u_mx, u_err, u_ts,
 					   timed ? cond_fetch_timeout : NULL);
diff --git a/kernel/cobalt/posix/cond.h b/kernel/cobalt/posix/cond.h
index c7a9be451..7bec2a649 100644
--- a/kernel/cobalt/posix/cond.h
+++ b/kernel/cobalt/posix/cond.h
@@ -43,7 +43,7 @@ int __cobalt_cond_wait_prologue(struct cobalt_cond_shadow __user *u_cnd,
 				struct cobalt_mutex_shadow __user *u_mx,
 				int *u_err,
 				void __user *u_ts,
-				int (*fetch_timeout)(struct timespec *ts,
+				int (*fetch_timeout)(struct timespec64 *ts,
 						     const void __user *u_ts));
 COBALT_SYSCALL_DECL(cond_init,
 		    (struct cobalt_cond_shadow __user *u_cnd,
@@ -57,7 +57,7 @@ COBALT_SYSCALL_DECL(cond_wait_prologue,
 		     struct cobalt_mutex_shadow __user *u_mx,
 		     int *u_err,
 		     unsigned int timed,
-		     struct timespec __user *u_ts));
+		     struct __user_old_timespec __user *u_ts));
 
 COBALT_SYSCALL_DECL(cond_wait_epilogue,
 		    (struct cobalt_cond_shadow __user *u_cnd,
diff --git a/kernel/cobalt/posix/event.c b/kernel/cobalt/posix/event.c
index c566a09e3..3712154f5 100644
--- a/kernel/cobalt/posix/event.c
+++ b/kernel/cobalt/posix/event.c
@@ -104,7 +104,7 @@ COBALT_SYSCALL(event_init, current,
 int __cobalt_event_wait(struct cobalt_event_shadow __user *u_event,
 			unsigned int bits,
 			unsigned int __user *u_bits_r,
-			int mode, const struct timespec *ts)
+			int mode, const struct timespec64 *ts)
 {
 	unsigned int rbits = 0, testval;
 	xnticks_t timeout = XN_INFINITE;
@@ -193,14 +193,14 @@ COBALT_SYSCALL(event_wait, primary,
 	       (struct cobalt_event_shadow __user *u_event,
 		unsigned int bits,
 		unsigned int __user *u_bits_r,
-		int mode, const struct timespec __user *u_ts))
+		int mode, const struct __user_old_timespec __user *u_ts))
 {
-	struct timespec ts, *tsp = NULL;
+	struct timespec64 ts, *tsp = NULL;
 	int ret;
 
 	if (u_ts) {
 		tsp = &ts;
-		ret = cobalt_copy_from_user(&ts, u_ts, sizeof(ts));
+		ret = cobalt_get_u_timespec(&ts, u_ts);
 		if (ret)
 			return ret;
 	}
diff --git a/kernel/cobalt/posix/event.h b/kernel/cobalt/posix/event.h
index 28d4516ac..ef592f72c 100644
--- a/kernel/cobalt/posix/event.h
+++ b/kernel/cobalt/posix/event.h
@@ -39,7 +39,7 @@ struct cobalt_event {
 int __cobalt_event_wait(struct cobalt_event_shadow __user *u_event,
 			unsigned int bits,
 			unsigned int __user *u_bits_r,
-			int mode, const struct timespec *ts);
+			int mode, const struct timespec64 *ts);
 
 COBALT_SYSCALL_DECL(event_init,
 		    (struct cobalt_event_shadow __user *u_evtsh,
@@ -51,7 +51,7 @@ COBALT_SYSCALL_DECL(event_wait,
 		     unsigned int bits,
 		     unsigned int __user *u_bits_r,
 		     int mode,
-		     const struct timespec __user *u_ts));
+		     const struct __user_old_timespec __user *u_ts));
 
 COBALT_SYSCALL_DECL(event_sync,
 		    (struct cobalt_event_shadow __user *u_evtsh));
diff --git a/kernel/cobalt/posix/io.c b/kernel/cobalt/posix/io.c
index e9908feeb..97a1f6afc 100644
--- a/kernel/cobalt/posix/io.c
+++ b/kernel/cobalt/posix/io.c
@@ -93,10 +93,10 @@ COBALT_SYSCALL(recvmsg, handover,
 	return cobalt_copy_to_user(umsg, &m, sizeof(*umsg)) ?: ret;
 }
 
-static int get_timespec(struct timespec *ts,
+static int get_timespec(struct timespec64 *ts,
 			const void __user *u_ts)
 {
-	return cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
+	return cobalt_get_u_timespec(ts, u_ts);
 }
 
 static int get_mmsg(struct mmsghdr *mmsg, void __user *u_mmsg)
@@ -114,7 +114,7 @@ static int put_mmsg(void __user **u_mmsg_p, const struct mmsghdr *mmsg)
 
 COBALT_SYSCALL(recvmmsg, primary,
 	       (int fd, struct mmsghdr __user *u_msgvec, unsigned int vlen,
-		unsigned int flags, struct timespec *u_timeout))
+		unsigned int flags, struct __user_old_timespec __user *u_timeout))
 {
 	return __rtdm_fd_recvmmsg(fd, u_msgvec, vlen, flags, u_timeout,
 				  get_mmsg, put_mmsg, get_timespec);
diff --git a/kernel/cobalt/posix/io.h b/kernel/cobalt/posix/io.h
index 82187cc7b..e4f7d4d51 100644
--- a/kernel/cobalt/posix/io.h
+++ b/kernel/cobalt/posix/io.h
@@ -53,7 +53,7 @@ COBALT_SYSCALL_DECL(recvmsg,
 
 COBALT_SYSCALL_DECL(recvmmsg,
 		    (int fd, struct mmsghdr __user *u_msgvec, unsigned int vlen,
-		     unsigned int flags, struct timespec *u_timeout));
+		     unsigned int flags, struct __user_old_timespec __user *u_timeout));
 
 COBALT_SYSCALL_DECL(sendmsg,
 		    (int fd, struct user_msghdr __user *umsg, int flags));
diff --git a/kernel/cobalt/posix/monitor.c b/kernel/cobalt/posix/monitor.c
index 5237545be..b907e0050 100644
--- a/kernel/cobalt/posix/monitor.c
+++ b/kernel/cobalt/posix/monitor.c
@@ -203,7 +203,7 @@ drain:
 }
 
 int __cobalt_monitor_wait(struct cobalt_monitor_shadow __user *u_mon,
-			  int event, const struct timespec *ts,
+			  int event, const struct timespec64 *ts,
 			  int __user *u_ret)
 {
 	struct cobalt_thread *curr = cobalt_current_thread();
@@ -291,15 +291,15 @@ out:
 
 COBALT_SYSCALL(monitor_wait, nonrestartable,
 	       (struct cobalt_monitor_shadow __user *u_mon,
-	       int event, const struct timespec __user *u_ts,
+	       int event, const struct __user_old_timespec __user *u_ts,
 	       int __user *u_ret))
 {
-	struct timespec ts, *tsp = NULL;
+	struct timespec64 ts, *tsp = NULL;
 	int ret;
 
 	if (u_ts) {
 		tsp = &ts;
-		ret = cobalt_copy_from_user(&ts, u_ts, sizeof(ts));
+		ret = cobalt_get_u_timespec(&ts, u_ts);
 		if (ret)
 			return ret;
 	}
diff --git a/kernel/cobalt/posix/monitor.h b/kernel/cobalt/posix/monitor.h
index 8b321aaec..d4a4aa24e 100644
--- a/kernel/cobalt/posix/monitor.h
+++ b/kernel/cobalt/posix/monitor.h
@@ -39,7 +39,7 @@ struct cobalt_monitor {
 };
 
 int __cobalt_monitor_wait(struct cobalt_monitor_shadow __user *u_mon,
-			  int event, const struct timespec *ts,
+			  int event, const struct timespec64 *ts,
 			  int __user *u_ret);
 
 COBALT_SYSCALL_DECL(monitor_init,
@@ -58,7 +58,7 @@ COBALT_SYSCALL_DECL(monitor_exit,
 
 COBALT_SYSCALL_DECL(monitor_wait,
 		    (struct cobalt_monitor_shadow __user *u_monsh,
-		     int event, const struct timespec __user *u_ts,
+		     int event, const struct __user_old_timespec __user *u_ts,
 		     int __user *u_ret));
 
 COBALT_SYSCALL_DECL(monitor_destroy,
diff --git a/kernel/cobalt/posix/mqueue.c b/kernel/cobalt/posix/mqueue.c
index cd1cf3ce8..b2cf92e43 100644
--- a/kernel/cobalt/posix/mqueue.c
+++ b/kernel/cobalt/posix/mqueue.c
@@ -468,13 +468,13 @@ mq_tryrcv(struct cobalt_mqd *mqd, size_t len)
 static struct cobalt_msg *
 mq_timedsend_inner(struct cobalt_mqd *mqd,
 		   size_t len, const void __user *u_ts,
-		   int (*fetch_timeout)(struct timespec *ts,
+		   int (*fetch_timeout)(struct timespec64 *ts,
 					const void __user *u_ts))
 {
 	struct cobalt_mqwait_context mwc;
 	struct cobalt_msg *msg;
 	struct cobalt_mq *mq;
-	struct timespec ts;
+	struct timespec64 ts;
 	xntmode_t tmode;
 	xnticks_t to;
 	spl_t s;
@@ -597,13 +597,13 @@ static struct cobalt_msg *
 mq_timedrcv_inner(struct cobalt_mqd *mqd,
 		  size_t len,
 		  const void __user *u_ts,
-		  int (*fetch_timeout)(struct timespec *ts,
+		  int (*fetch_timeout)(struct timespec64 *ts,
 				       const void __user *u_ts))
 {
 	struct cobalt_mqwait_context mwc;
 	struct cobalt_msg *msg;
 	struct cobalt_mq *mq;
-	struct timespec ts;
+	struct timespec64 ts;
 	xntmode_t tmode;
 	xnticks_t to;
 	spl_t s;
@@ -880,7 +880,7 @@ COBALT_SYSCALL(mq_getattr, current,
 	return cobalt_copy_to_user(u_attr, &attr, sizeof(attr));
 }
 
-static inline int mq_fetch_timeout(struct timespec *ts,
+static inline int mq_fetch_timeout(struct timespec64 *ts,
 				   const void __user *u_ts)
 {
 	return u_ts == NULL ? -EFAULT :
@@ -889,7 +889,7 @@ static inline int mq_fetch_timeout(struct timespec *ts,
 
 int __cobalt_mq_timedsend(mqd_t uqd, const void __user *u_buf, size_t len,
 			  unsigned int prio, const void __user *u_ts,
-			  int (*fetch_timeout)(struct timespec *ts,
+			  int (*fetch_timeout)(struct timespec64 *ts,
 					       const void __user *u_ts))
 {
 	struct cobalt_msg *msg;
@@ -933,7 +933,7 @@ out:
 
 COBALT_SYSCALL(mq_timedsend, primary,
 	       (mqd_t uqd, const void __user *u_buf, size_t len,
-		unsigned int prio, const struct timespec __user *u_ts))
+		unsigned int prio, const struct __user_old_timespec __user *u_ts))
 {
 	return __cobalt_mq_timedsend(uqd, u_buf, len, prio,
 				     u_ts, u_ts ? mq_fetch_timeout : NULL);
@@ -943,7 +943,7 @@ int __cobalt_mq_timedreceive(mqd_t uqd, void __user *u_buf,
 			     ssize_t *lenp,
 			     unsigned int __user *u_prio,
 			     const void __user *u_ts,
-			     int (*fetch_timeout)(struct timespec *ts,
+			     int (*fetch_timeout)(struct timespec64 *ts,
 						  const void __user *u_ts))
 {
 	struct cobalt_mqd *mqd;
@@ -994,7 +994,7 @@ COBALT_SYSCALL(mq_timedreceive, primary,
 	       (mqd_t uqd, void __user *u_buf,
 		ssize_t __user *u_len,
 		unsigned int __user *u_prio,
-		const struct timespec __user *u_ts))
+		const struct __user_old_timespec __user *u_ts))
 {
 	ssize_t len;
 	int ret;
diff --git a/kernel/cobalt/posix/mqueue.h b/kernel/cobalt/posix/mqueue.h
index acae2a424..d33220227 100644
--- a/kernel/cobalt/posix/mqueue.h
+++ b/kernel/cobalt/posix/mqueue.h
@@ -37,14 +37,14 @@ int __cobalt_mq_getattr(mqd_t uqd, struct mq_attr *attr);
 
 int __cobalt_mq_timedsend(mqd_t uqd, const void __user *u_buf, size_t len,
 			  unsigned int prio, const void __user *u_ts,
-			  int (*fetch_timeout)(struct timespec *ts,
+			  int (*fetch_timeout)(struct timespec64 *ts,
 					       const void __user *u_ts));
 
 int __cobalt_mq_timedreceive(mqd_t uqd, void __user *u_buf,
 			     ssize_t *lenp,
 			     unsigned int __user *u_prio,
 			     const void __user *u_ts,
-			     int (*fetch_timeout)(struct timespec *ts,
+			     int (*fetch_timeout)(struct timespec64 *ts,
 						  const void __user *u_ts));
 
 int __cobalt_mq_notify(mqd_t fd, const struct sigevent *evp);
@@ -61,12 +61,12 @@ COBALT_SYSCALL_DECL(mq_getattr, (mqd_t uqd, struct mq_attr __user *u_attr));
 
 COBALT_SYSCALL_DECL(mq_timedsend,
 		    (mqd_t uqd, const void __user *u_buf, size_t len,
-		     unsigned int prio, const struct timespec __user *u_ts));
+		     unsigned int prio, const struct __user_old_timespec __user *u_ts));
 
 COBALT_SYSCALL_DECL(mq_timedreceive,
 		    (mqd_t uqd, void __user *u_buf, ssize_t __user *u_len,
 		     unsigned int __user *u_prio,
-		     const struct timespec __user *u_ts));
+		     const struct __user_old_timespec __user *u_ts));
 
 COBALT_SYSCALL_DECL(mq_notify,
 		    (mqd_t fd, const struct sigevent *__user evp));
diff --git a/kernel/cobalt/posix/mutex.c b/kernel/cobalt/posix/mutex.c
index 79260b544..d43a747b3 100644
--- a/kernel/cobalt/posix/mutex.c
+++ b/kernel/cobalt/posix/mutex.c
@@ -71,7 +71,7 @@ static int cobalt_mutex_init_inner(struct cobalt_mutex_shadow *shadow,
 /* must be called with nklock locked, interrupts off. */
 int __cobalt_mutex_acquire_unchecked(struct xnthread *cur,
 				     struct cobalt_mutex *mutex,
-				     const struct timespec *ts)
+				     const struct timespec64 *ts)
 {
 	int ret;
 
@@ -134,11 +134,11 @@ int cobalt_mutex_release(struct xnthread *curr,
 
 int __cobalt_mutex_timedlock_break(struct cobalt_mutex_shadow __user *u_mx,
 				   const void __user *u_ts,
-				   int (*fetch_timeout)(struct timespec *ts,
+				   int (*fetch_timeout)(struct timespec64 *ts,
 							const void __user *u_ts))
 {
 	struct xnthread *curr = xnthread_current();
-	struct timespec ts, *tsp = NULL;
+	struct timespec64 ts, *tsp = NULL;
 	struct cobalt_mutex *mutex;
 	xnhandle_t handle;
 	spl_t s;
@@ -346,7 +346,7 @@ COBALT_SYSCALL(mutex_lock, primary,
 	return __cobalt_mutex_timedlock_break(u_mx, NULL, NULL);
 }
 
-static inline int mutex_fetch_timeout(struct timespec *ts,
+static inline int mutex_fetch_timeout(struct timespec64 *ts,
 				      const void __user *u_ts)
 {
 	return u_ts == NULL ? -EFAULT :
@@ -355,7 +355,7 @@ static inline int mutex_fetch_timeout(struct timespec *ts,
 
 COBALT_SYSCALL(mutex_timedlock, primary,
 	       (struct cobalt_mutex_shadow __user *u_mx,
-		const struct timespec __user *u_ts))
+		const struct __user_old_timespec __user *u_ts))
 {
 	return __cobalt_mutex_timedlock_break(u_mx, u_ts, mutex_fetch_timeout);
 }
diff --git a/kernel/cobalt/posix/mutex.h b/kernel/cobalt/posix/mutex.h
index ac1c50291..d76f2a9ea 100644
--- a/kernel/cobalt/posix/mutex.h
+++ b/kernel/cobalt/posix/mutex.h
@@ -37,12 +37,12 @@ struct cobalt_mutex {
 
 int __cobalt_mutex_timedlock_break(struct cobalt_mutex_shadow __user *u_mx,
 				   const void __user *u_ts,
-				   int (*fetch_timeout)(struct timespec *ts,
+				   int (*fetch_timeout)(struct timespec64 *ts,
 							const void __user *u_ts));
 
 int __cobalt_mutex_acquire_unchecked(struct xnthread *cur,
 				     struct cobalt_mutex *mutex,
-				     const struct timespec *ts);
+				     const struct timespec64 *ts);
 
 COBALT_SYSCALL_DECL(mutex_check_init,
 		    (struct cobalt_mutex_shadow __user *u_mx));
@@ -62,7 +62,7 @@ COBALT_SYSCALL_DECL(mutex_lock,
 
 COBALT_SYSCALL_DECL(mutex_timedlock,
 		    (struct cobalt_mutex_shadow __user *u_mx,
-		     const struct timespec __user *u_ts));
+		     const struct __user_old_timespec __user *u_ts));
 
 COBALT_SYSCALL_DECL(mutex_unlock,
 		    (struct cobalt_mutex_shadow __user *u_mx));
diff --git a/kernel/cobalt/posix/sched.c b/kernel/cobalt/posix/sched.c
index 798a172d7..4fd9c2b46 100644
--- a/kernel/cobalt/posix/sched.c
+++ b/kernel/cobalt/posix/sched.c
@@ -73,7 +73,7 @@ cobalt_sched_policy_param(union xnsched_policy_param *param,
 		break;
 	case SCHED_RR:
 		/* if unspecified, use current one. */
-		tslice = ts2ns(&param_ex->sched_rr_quantum);
+		tslice = u_ts2ns(&param_ex->sched_rr_quantum);
 		if (tslice == XN_INFINITE && tslice_r)
 			tslice = *tslice_r;
 		/* fallthrough */
@@ -92,8 +92,8 @@ cobalt_sched_policy_param(union xnsched_policy_param *param,
 		param->pss.normal_prio = param_ex->sched_priority;
 		param->pss.low_prio = param_ex->sched_ss_low_priority;
 		param->pss.current_prio = param->pss.normal_prio;
-		param->pss.init_budget = ts2ns(&param_ex->sched_ss_init_budget);
-		param->pss.repl_period = ts2ns(&param_ex->sched_ss_repl_period);
+		param->pss.init_budget = u_ts2ns(&param_ex->sched_ss_init_budget);
+		param->pss.repl_period = u_ts2ns(&param_ex->sched_ss_repl_period);
 		param->pss.max_repl = param_ex->sched_ss_max_repl;
 		sched_class = &xnsched_class_sporadic;
 		break;
@@ -280,11 +280,11 @@ int set_tp_config(int cpu, union sched_config *config, size_t len)
 		 * be defined using windows assigned to the pseudo
 		 * partition #-1.
 		 */
-		offset = ts2ns(&p->offset);
+		offset = u_ts2ns(&p->offset);
 		if (offset != next_offset)
 			goto cleanup_and_fail;
 
-		duration = ts2ns(&p->duration);
+		duration = u_ts2ns(&p->duration);
 		if (duration <= 0)
 			goto cleanup_and_fail;
 
@@ -357,11 +357,11 @@ ssize_t get_tp_config(int cpu, void __user *u_config, size_t len,
 	config->tp.nr_windows = gps->pwin_nr;
 	for (n = 0, pp = p = config->tp.windows, pw = w = gps->pwins;
 	     n < gps->pwin_nr; pp = p, p++, pw = w, w++, n++) {
-		ns2ts(&p->offset, w->w_offset);
-		ns2ts(&pp->duration, w->w_offset - pw->w_offset);
+		u_ns2ts(&p->offset, w->w_offset);
+		u_ns2ts(&pp->duration, w->w_offset - pw->w_offset);
 		p->ptid = w->w_part;
 	}
-	ns2ts(&pp->duration, gps->tf_duration - pw->w_offset);
+	u_ns2ts(&pp->duration, gps->tf_duration - pw->w_offset);
 	ret = put_config(SCHED_TP, u_config, len, config, elen);
 	xnfree(config);
 out:
diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
index 05a861dfe..467a9b7dd 100644
--- a/kernel/cobalt/posix/sem.c
+++ b/kernel/cobalt/posix/sem.c
@@ -267,7 +267,7 @@ out:
 	return ret;
 }
 
-static inline int sem_fetch_timeout(struct timespec *ts,
+static inline int sem_fetch_timeout(struct timespec64 *ts,
 				    const void __user *u_ts)
 {
 	return u_ts == NULL ? -EFAULT :
@@ -276,10 +276,10 @@ static inline int sem_fetch_timeout(struct timespec *ts,
 
 int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
 			   const void __user *u_ts,
-			   int (*fetch_timeout)(struct timespec *ts,
+			   int (*fetch_timeout)(struct timespec64 *ts,
 						const void __user *u_ts))
 {
-	struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
+	struct timespec64 ts = { .tv_sec = 0, .tv_nsec = 0 };
 	int pull_ts = 1, ret, info;
 	struct cobalt_sem *sem;
 	xnhandle_t handle;
@@ -434,7 +434,7 @@ COBALT_SYSCALL(sem_wait, primary,
 
 COBALT_SYSCALL(sem_timedwait, primary,
 	       (struct cobalt_sem_shadow __user *u_sem,
-		struct timespec __user *u_ts))
+		struct __user_old_timespec __user *u_ts))
 {
 	return __cobalt_sem_timedwait(u_sem, u_ts, sem_fetch_timeout);
 }
diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h
index 17238078e..d17299495 100644
--- a/kernel/cobalt/posix/sem.h
+++ b/kernel/cobalt/posix/sem.h
@@ -65,7 +65,7 @@ __cobalt_sem_open(struct cobalt_sem_shadow __user *usm,
 
 int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
 			   const void __user *u_ts,
-			   int (*fetch_timeout)(struct timespec *ts,
+			   int (*fetch_timeout)(struct timespec64 *ts,
 						const void __user *u_ts));
 
 int __cobalt_sem_destroy(xnhandle_t handle);
@@ -91,7 +91,7 @@ COBALT_SYSCALL_DECL(sem_wait,
 
 COBALT_SYSCALL_DECL(sem_timedwait,
 		    (struct cobalt_sem_shadow __user *u_sem,
-		     struct timespec __user *u_ts));
+		     struct __user_old_timespec __user *u_ts));
 
 COBALT_SYSCALL_DECL(sem_trywait,
 		    (struct cobalt_sem_shadow __user *u_sem));
diff --git a/kernel/cobalt/posix/signal.c b/kernel/cobalt/posix/signal.c
index 862a644c0..0b43b5fcf 100644
--- a/kernel/cobalt/posix/signal.c
+++ b/kernel/cobalt/posix/signal.c
@@ -407,7 +407,7 @@ COBALT_SYSCALL(sigwait, primary,
 }
 
 int __cobalt_sigtimedwait(sigset_t *set,
-			  const struct timespec *timeout,
+			  const struct timespec64 *timeout,
 			  void __user *u_si,
 			  bool compat)
 {
@@ -426,9 +426,9 @@ int __cobalt_sigtimedwait(sigset_t *set,
 COBALT_SYSCALL(sigtimedwait, nonrestartable,
 	       (const sigset_t __user *u_set,
 		struct siginfo __user *u_si,
-		const struct timespec __user *u_timeout))
+		const struct __user_old_timespec __user *u_timeout))
 {
-	struct timespec timeout;
+	struct timespec64 timeout;
 	sigset_t set;
 
 	if (cobalt_copy_from_user(&set, u_set, sizeof(set)))
diff --git a/kernel/cobalt/posix/signal.h b/kernel/cobalt/posix/signal.h
index 7a0b4b22b..fc26ad065 100644
--- a/kernel/cobalt/posix/signal.h
+++ b/kernel/cobalt/posix/signal.h
@@ -59,7 +59,7 @@ void cobalt_copy_siginfo(int code,
 int __cobalt_sigwait(sigset_t *set);
 
 int __cobalt_sigtimedwait(sigset_t *set,
-			  const struct timespec *timeout,
+			  const struct timespec64 *timeout,
 			  void __user *u_si,
 			  bool compat);
 
@@ -94,7 +94,7 @@ COBALT_SYSCALL_DECL(sigwait,
 COBALT_SYSCALL_DECL(sigtimedwait,
 		    (const sigset_t __user *u_set,
 		     struct siginfo __user *u_si,
-		     const struct timespec __user *u_timeout));
+		     const struct __user_old_timespec __user *u_timeout));
 
 COBALT_SYSCALL_DECL(sigwaitinfo,
 		    (const sigset_t __user *u_set,
diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
index cb02dacd3..ae25a6e74 100644
--- a/kernel/cobalt/posix/syscall32.c
+++ b/kernel/cobalt/posix/syscall32.c
@@ -97,7 +97,7 @@ COBALT_SYSCALL32emu(thread_setschedprio, conforming,
 	return cobalt_thread_setschedprio(pth, prio, u_winoff, u_promoted);
 }
 
-static inline int sys32_fetch_timeout(struct timespec *ts,
+static inline int sys32_fetch_timeout(struct timespec64 *ts,
 				      const void __user *u_ts)
 {
 	return u_ts == NULL ? -EFAULT :
@@ -133,7 +133,7 @@ COBALT_SYSCALL32emu(clock_getres, current,
 		    (clockid_t clock_id,
 		     struct compat_timespec __user *u_ts))
 {
-	struct timespec ts;
+	struct timespec64 ts;
 	int ret;
 
 	ret = __cobalt_clock_getres(clock_id, &ts);
@@ -147,7 +147,7 @@ COBALT_SYSCALL32emu(clock_gettime, current,
 		    (clockid_t clock_id,
 		     struct compat_timespec __user *u_ts))
 {
-	struct timespec ts;
+	struct timespec64 ts;
 	int ret;
 
 	ret = __cobalt_clock_gettime(clock_id, &ts);
@@ -161,7 +161,7 @@ COBALT_SYSCALL32emu(clock_settime, current,
 		    (clockid_t clock_id,
 		     const struct compat_timespec __user *u_ts))
 {
-	struct timespec ts;
+	struct timespec64 ts;
 	int ret;
 
 	ret = sys32_get_timespec(&ts, u_ts);
@@ -193,7 +193,7 @@ COBALT_SYSCALL32emu(clock_nanosleep, nonrestartable,
 		     const struct compat_timespec __user *u_rqt,
 		     struct compat_timespec __user *u_rmt))
 {
-	struct timespec rqt, rmt, *rmtp = NULL;
+	struct timespec64 rqt, rmt, *rmtp = NULL;
 	int ret;
 
 	if (u_rmt)
@@ -289,12 +289,10 @@ COBALT_SYSCALL32emu(mq_timedreceive, primary,
 	return ret ?: cobalt_copy_to_user(u_len, &clen, sizeof(*u_len));
 }
 
-static inline int mq_fetch_timeout(struct timespec *ts,
+static inline int mq_fetch_timeout(struct timespec64 *ts,
 				   const void __user *u_ts)
 {
-	return u_ts == NULL ? -EFAULT :
-		cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
-
+	return u_ts == NULL ? -EFAULT : cobalt_get_u_timespec(ts, u_ts);
 }
 
 COBALT_SYSCALL32emu(mq_notify, primary,
@@ -610,7 +608,7 @@ COBALT_SYSCALL32emu(sigtimedwait, nonrestartable,
 		     struct compat_siginfo __user *u_si,
 		     const struct compat_timespec __user *u_timeout))
 {
-	struct timespec timeout;
+	struct timespec64 timeout;
 	sigset_t set;
 	int ret;
 
@@ -663,7 +661,7 @@ COBALT_SYSCALL32emu(monitor_wait, nonrestartable,
 		     int event, const struct compat_timespec __user *u_ts,
 		     int __user *u_ret))
 {
-	struct timespec ts, *tsp = NULL;
+	struct timespec64 ts, *tsp = NULL;
 	int ret;
 
 	if (u_ts) {
@@ -682,7 +680,7 @@ COBALT_SYSCALL32emu(event_wait, primary,
 		     unsigned int __user *u_bits_r,
 		     int mode, const struct compat_timespec __user *u_ts))
 {
-	struct timespec ts, *tsp = NULL;
+	struct timespec64 ts, *tsp = NULL;
 	int ret;
 
 	if (u_ts) {
@@ -810,7 +808,7 @@ COBALT_SYSCALL32emu(recvmsg, handover,
 	return sys32_put_msghdr(umsg, &m) ?: ret;
 }
 
-static int get_timespec32(struct timespec *ts,
+static int get_timespec32(struct timespec64 *ts,
 			  const void __user *u_ts)
 {
 	return sys32_get_timespec(ts, u_ts);
@@ -924,7 +922,7 @@ COBALT_SYSCALL32x(mq_timedreceive, primary,
 		  (mqd_t uqd, void __user *u_buf,
 		   compat_ssize_t __user *u_len,
 		   unsigned int __user *u_prio,
-		   const struct timespec __user *u_ts))
+		   const struct __user_old_timespec __user *u_ts))
 {
 	compat_ssize_t clen;
 	ssize_t len;
diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h
index eb3e4bd30..9da405229 100644
--- a/kernel/cobalt/posix/syscall32.h
+++ b/kernel/cobalt/posix/syscall32.h
@@ -105,7 +105,7 @@ COBALT_SYSCALL32x_DECL(mq_timedreceive,
 		       (mqd_t uqd, void __user *u_buf,
 			compat_ssize_t __user *u_len,
 			unsigned int __user *u_prio,
-			const struct timespec __user *u_ts));
+			const struct __user_old_timespec __user *u_ts));
 
 COBALT_SYSCALL32emu_DECL(mq_notify,
 			 (mqd_t fd, const struct compat_sigevent *__user u_cev));
diff --git a/kernel/cobalt/posix/thread.c b/kernel/cobalt/posix/thread.c
index bf9c08212..cdeb66d4f 100644
--- a/kernel/cobalt/posix/thread.c
+++ b/kernel/cobalt/posix/thread.c
@@ -302,7 +302,7 @@ int __cobalt_thread_getschedparam_ex(struct cobalt_thread *thread,
 
 	if (base_class == &xnsched_class_rt) {
 		if (xnthread_test_state(base_thread, XNRRB)) {
-			ns2ts(&param_ex->sched_rr_quantum, base_thread->rrperiod);
+			u_ns2ts(&param_ex->sched_rr_quantum, base_thread->rrperiod);
 			*policy_r = SCHED_RR;
 		}
 		goto out;
@@ -318,8 +318,8 @@ int __cobalt_thread_getschedparam_ex(struct cobalt_thread *thread,
 #ifdef CONFIG_XENO_OPT_SCHED_SPORADIC
 	if (base_class == &xnsched_class_sporadic) {
 		param_ex->sched_ss_low_priority = base_thread->pss->param.low_prio;
-		ns2ts(&param_ex->sched_ss_repl_period, base_thread->pss->param.repl_period);
-		ns2ts(&param_ex->sched_ss_init_budget, base_thread->pss->param.init_budget);
+		u_ns2ts(&param_ex->sched_ss_repl_period, base_thread->pss->param.repl_period);
+		u_ns2ts(&param_ex->sched_ss_init_budget, base_thread->pss->param.init_budget);
 		param_ex->sched_ss_max_repl = base_thread->pss->param.max_repl;
 		goto out;
 	}
diff --git a/kernel/cobalt/rtdm/fd.c b/kernel/cobalt/rtdm/fd.c
index 7956a8800..038247d54 100644
--- a/kernel/cobalt/rtdm/fd.c
+++ b/kernel/cobalt/rtdm/fd.c
@@ -650,11 +650,11 @@ int __rtdm_fd_recvmmsg(int ufd, void __user *u_msgvec, unsigned int vlen,
 		       unsigned int flags, void __user *u_timeout,
 		       int (*get_mmsg)(struct mmsghdr *mmsg, void __user *u_mmsg),
 		       int (*put_mmsg)(void __user **u_mmsg_p, const struct mmsghdr *mmsg),
-		       int (*get_timespec)(struct timespec *ts, const void __user *u_ts))
+		       int (*get_timespec)(struct timespec64 *ts, const void __user *u_ts))
 {
 	struct cobalt_recvmmsg_timer rq;
 	xntmode_t tmode = XN_RELATIVE;
-	struct timespec ts = { 0 };
+	struct timespec64 ts = { 0 };
 	int ret = 0, datagrams = 0;
 	xnticks_t timeout = 0;
 	struct mmsghdr mmsg;
diff --git a/kernel/cobalt/trace/cobalt-posix.h b/kernel/cobalt/trace/cobalt-posix.h
index aa78efbc0..3a649a671 100644
--- a/kernel/cobalt/trace/cobalt-posix.h
+++ b/kernel/cobalt/trace/cobalt-posix.h
@@ -30,7 +30,7 @@
 #include <xenomai/posix/event.h>
 
 #define __timespec_fields(__name)				\
-	__field(__kernel_time_t, tv_sec_##__name)		\
+	__field(time64_t, tv_sec_##__name)			\
 	__field(long, tv_nsec_##__name)
 
 #define __assign_timespec(__to, __from)				\
@@ -40,7 +40,7 @@
 	} while (0)
 
 #define __timespec_args(__name)					\
-	__entry->tv_sec_##__name, __entry->tv_nsec_##__name
+	(long long)__entry->tv_sec_##__name, __entry->tv_nsec_##__name
 
 #ifdef CONFIG_X86_X32
 #define __sc_x32(__name)	, { sc_cobalt_##__name + __COBALT_X32_BASE, "x32-" #__name }
@@ -729,7 +729,7 @@ TRACE_EVENT(cobalt_psem_unlink,
 );
 
 DECLARE_EVENT_CLASS(cobalt_clock_timespec,
-	TP_PROTO(clockid_t clk_id, const struct timespec *val),
+	TP_PROTO(clockid_t clk_id, const struct timespec64 *val),
 	TP_ARGS(clk_id, val),
 
 	TP_STRUCT__entry(
@@ -742,24 +742,24 @@ DECLARE_EVENT_CLASS(cobalt_clock_timespec,
 		__assign_timespec(val, val);
 	),
 
-	TP_printk("clock_id=%d timeval=(%ld.%09ld)",
+	TP_printk("clock_id=%d timeval=(%lld.%09ld)",
 		  __entry->clk_id,
 		  __timespec_args(val)
 	)
 );
 
 DEFINE_EVENT(cobalt_clock_timespec, cobalt_clock_getres,
-	TP_PROTO(clockid_t clk_id, const struct timespec *res),
+	TP_PROTO(clockid_t clk_id, const struct timespec64 *res),
 	TP_ARGS(clk_id, res)
 );
 
 DEFINE_EVENT(cobalt_clock_timespec, cobalt_clock_gettime,
-	TP_PROTO(clockid_t clk_id, const struct timespec *time),
+	TP_PROTO(clockid_t clk_id, const struct timespec64 *time),
 	TP_ARGS(clk_id, time)
 );
 
 DEFINE_EVENT(cobalt_clock_timespec, cobalt_clock_settime,
-	TP_PROTO(clockid_t clk_id, const struct timespec *time),
+	TP_PROTO(clockid_t clk_id, const struct timespec64 *time),
 	TP_ARGS(clk_id, time)
 );
 
@@ -788,7 +788,7 @@ TRACE_EVENT(cobalt_clock_adjtime,
 		      {TIMER_ABSTIME, "TIMER_ABSTIME"})
 
 TRACE_EVENT(cobalt_clock_nanosleep,
-	TP_PROTO(clockid_t clk_id, int flags, const struct timespec *time),
+	TP_PROTO(clockid_t clk_id, int flags, const struct timespec64 *time),
 	TP_ARGS(clk_id, flags, time),
 
 	TP_STRUCT__entry(
@@ -803,7 +803,7 @@ TRACE_EVENT(cobalt_clock_nanosleep,
 		__assign_timespec(time, time);
 	),
 
-	TP_printk("clock_id=%d flags=%#x(%s) rqt=(%ld.%09ld)",
+	TP_printk("clock_id=%d flags=%#x(%s) rqt=(%lld.%09ld)",
 		  __entry->clk_id,
 		  __entry->flags, cobalt_print_timer_flags(__entry->flags),
 		  __timespec_args(time)
@@ -875,7 +875,7 @@ TRACE_EVENT(cobalt_cond_destroy,
 TRACE_EVENT(cobalt_cond_timedwait,
 	TP_PROTO(const struct cobalt_cond_shadow __user *u_cnd,
 		 const struct cobalt_mutex_shadow __user *u_mx,
-		 const struct timespec *timeout),
+		 const struct timespec64 *timeout),
 	TP_ARGS(u_cnd, u_mx, timeout),
 	TP_STRUCT__entry(
 		__field(const struct cobalt_cond_shadow __user *, u_cnd)
@@ -887,7 +887,7 @@ TRACE_EVENT(cobalt_cond_timedwait,
 		__entry->u_mx = u_mx;
 		__assign_timespec(timeout, timeout);
 	),
-	TP_printk("cond=%p, mutex=%p, timeout=(%ld.%09ld)",
+	TP_printk("cond=%p, mutex=%p, timeout=(%lld.%09ld)",
 		  __entry->u_cnd, __entry->u_mx, __timespec_args(timeout))
 );
 
@@ -1001,7 +1001,7 @@ TRACE_EVENT(cobalt_mq_send,
 
 TRACE_EVENT(cobalt_mq_timedreceive,
 	TP_PROTO(mqd_t mqd, const void __user *u_buf, size_t len,
-		 const struct timespec *timeout),
+		 const struct timespec64 *timeout),
 	TP_ARGS(mqd, u_buf, len, timeout),
 	TP_STRUCT__entry(
 		__field(mqd_t, mqd)
@@ -1015,7 +1015,7 @@ TRACE_EVENT(cobalt_mq_timedreceive,
 		__entry->len = len;
 		__assign_timespec(timeout, timeout);
 	),
-	TP_printk("mqd=%d buf=%p len=%zu timeout=(%ld.%09ld)",
+	TP_printk("mqd=%d buf=%p len=%zu timeout=(%lld.%09ld)",
 		  __entry->mqd, __entry->u_buf, __entry->len,
 		  __timespec_args(timeout))
 );
@@ -1105,7 +1105,7 @@ TRACE_EVENT(cobalt_event_init,
 TRACE_EVENT(cobalt_event_timedwait,
 	TP_PROTO(const struct cobalt_event_shadow __user *u_event,
 		 unsigned long bits, int mode,
-		 const struct timespec *timeout),
+		 const struct timespec64 *timeout),
 	TP_ARGS(u_event, bits, mode, timeout),
 	TP_STRUCT__entry(
 		__field(const struct cobalt_event_shadow __user *, u_event)
@@ -1119,7 +1119,7 @@ TRACE_EVENT(cobalt_event_timedwait,
 		__entry->mode = mode;
 		__assign_timespec(timeout, timeout);
 	),
-	TP_printk("event=%p bits=%#lx mode=%#x(%s) timeout=(%ld.%09ld)",
+	TP_printk("event=%p bits=%#lx mode=%#x(%s) timeout=(%lld.%09ld)",
 		  __entry->u_event, __entry->bits, __entry->mode,
 		  cobalt_print_evmode(__entry->mode),
 		  __timespec_args(timeout))
-- 
2.26.2



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

* [PATCH 3/5] lib: y2038: convert to internal timespec type
  2021-02-20 15:18 [PATCH 1/5] cobalt/kernel: y2038: convert struct timeval to __kernel_old_timeval Philippe Gerum
  2021-02-20 15:18 ` [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64 Philippe Gerum
@ 2021-02-20 15:18 ` Philippe Gerum
  2021-02-20 15:18 ` [PATCH 4/5] cobalt/kernel: y2038: convert struct itimerspec to itimerspec64 Philippe Gerum
  2021-02-20 15:18 ` [PATCH 5/5] cobalt/kernel: y2038: convert struct timex to __kernel_timex Philippe Gerum
  3 siblings, 0 replies; 57+ messages in thread
From: Philippe Gerum @ 2021-02-20 15:18 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai, Philippe Gerum

From: Philippe Gerum <rpm@xenomai.org>

Signed-off-by: Philippe Gerum <rpm@xenomai.org>
---
 lib/alchemy/task.c          | 9 ++++++---
 lib/copperplate/threadobj.c | 9 ++++++---
 lib/psos/task.c             | 9 ++++++---
 lib/vxworks/kernLib.c       | 6 ++++--
 lib/vxworks/taskLib.c       | 6 ++++--
 5 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/lib/alchemy/task.c b/lib/alchemy/task.c
index 949a996d0..9afa2af57 100644
--- a/lib/alchemy/task.c
+++ b/lib/alchemy/task.c
@@ -1410,11 +1410,14 @@ int rt_task_slice(RT_TASK *task, RTIME quantum)
 
 	param_ex.sched_priority = threadobj_get_priority(&tcb->thobj);
 	if (quantum) {
+		struct timespec ts;
 		policy = SCHED_RR;
-		clockobj_ticks_to_timespec(&alchemy_clock, quantum,
-					   &param_ex.sched_rr_quantum);
-	} else
+		clockobj_ticks_to_timespec(&alchemy_clock, quantum, &ts);
+		param_ex.sched_rr_quantum.tv_sec = ts.tv_sec;
+		param_ex.sched_rr_quantum.tv_nsec = ts.tv_nsec;
+	} else {
 		policy = param_ex.sched_priority ? SCHED_FIFO : SCHED_OTHER;
+	}
 
 	ret = threadobj_set_schedparam(&tcb->thobj, policy, &param_ex);
 	switch (ret) {
diff --git a/lib/copperplate/threadobj.c b/lib/copperplate/threadobj.c
index a3101baa1..f4588a17a 100644
--- a/lib/copperplate/threadobj.c
+++ b/lib/copperplate/threadobj.c
@@ -1741,7 +1741,8 @@ int threadobj_set_schedparam(struct threadobj *thobj, int policy,
 		ret = enable_rr_corespec(thobj, param_ex);
 		if (ret)
 			return __bt(ret);
-		thobj->tslice = param_ex->sched_rr_quantum;
+		thobj->tslice.tv_sec = param_ex->sched_rr_quantum.tv_sec;
+		thobj->tslice.tv_nsec = param_ex->sched_rr_quantum.tv_nsec;
 	} else if (thobj->policy == SCHED_RR) /* Switching off round-robin. */
 		disable_rr_corespec(thobj);
 
@@ -1761,8 +1762,10 @@ int threadobj_set_schedprio(struct threadobj *thobj, int priority)
 	param_ex.sched_priority = priority;
 	policy = thobj->policy;
 
-	if (policy == SCHED_RR)
-		param_ex.sched_rr_quantum = thobj->tslice;
+	if (policy == SCHED_RR) {
+		param_ex.sched_rr_quantum.tv_sec = thobj->tslice.tv_sec;
+		param_ex.sched_rr_quantum.tv_nsec = thobj->tslice.tv_nsec;
+	}
 
 	return threadobj_set_schedparam(thobj, policy, &param_ex);
 }
diff --git a/lib/psos/task.c b/lib/psos/task.c
index 46e49ea88..f678be61d 100644
--- a/lib/psos/task.c
+++ b/lib/psos/task.c
@@ -192,7 +192,8 @@ static void *task_trampoline(void *arg)
 
 	if (task->mode & T_TSLICE) {
 		param_ex.sched_priority = threadobj_get_priority(&task->thobj);
-		param_ex.sched_rr_quantum = psos_rrperiod;
+		param_ex.sched_rr_quantum.tv_sec = psos_rrperiod.tv_sec;
+		param_ex.sched_rr_quantum.tv_nsec = psos_rrperiod.tv_nsec;
 		threadobj_set_schedparam(&task->thobj, SCHED_RR, &param_ex);
 	}
 
@@ -630,9 +631,11 @@ u_long t_mode(u_long mask, u_long newmask, u_long *oldmode_r)
 
 	if (task->mode & T_TSLICE) {
 		policy = SCHED_RR;
-		param_ex.sched_rr_quantum = psos_rrperiod;
-	} else
+		param_ex.sched_rr_quantum.tv_sec = psos_rrperiod.tv_sec;
+		param_ex.sched_rr_quantum.tv_nsec = psos_rrperiod.tv_nsec;
+	} else {
 		policy = param_ex.sched_priority ? SCHED_FIFO : SCHED_OTHER;
+	}
 
 	/* Working on self, so -EIDRM can't happen. */
 	threadobj_set_schedparam(&task->thobj, policy, &param_ex);
diff --git a/lib/vxworks/kernLib.c b/lib/vxworks/kernLib.c
index 4f3bd8201..d67502730 100644
--- a/lib/vxworks/kernLib.c
+++ b/lib/vxworks/kernLib.c
@@ -30,9 +30,11 @@ static int switch_slicing(struct threadobj *thobj, struct timespec *quantum)
 
 	if (quantum) {
 		policy = SCHED_RR;
-		param_ex.sched_rr_quantum = *quantum;
-	} else
+		param_ex.sched_rr_quantum.tv_sec = quantum->tv_sec;
+		param_ex.sched_rr_quantum.tv_nsec = quantum->tv_nsec;
+	} else {
 		policy = param_ex.sched_priority ? SCHED_FIFO : SCHED_OTHER;
+	}
 
 	return threadobj_set_schedparam(thobj, policy, &param_ex);
 }
diff --git a/lib/vxworks/taskLib.c b/lib/vxworks/taskLib.c
index a4af36c1f..c8723c6be 100644
--- a/lib/vxworks/taskLib.c
+++ b/lib/vxworks/taskLib.c
@@ -265,8 +265,10 @@ static void *task_trampoline(void *arg)
 
 	/* Turn on time slicing if RR globally enabled. */
 	if (wind_time_slice) {
-		clockobj_ticks_to_timespec(&wind_clock, wind_time_slice,
-					   &param_ex.sched_rr_quantum);
+		struct timespec ts;
+		clockobj_ticks_to_timespec(&wind_clock, wind_time_slice, &ts);
+		param_ex.sched_rr_quantum.tv_sec = ts.tv_sec;
+		param_ex.sched_rr_quantum.tv_nsec = ts.tv_nsec;
 		threadobj_lock(&task->thobj);
 		param_ex.sched_priority = threadobj_get_priority(&task->thobj);
 		threadobj_set_schedparam(&task->thobj, SCHED_RR, &param_ex);
-- 
2.26.2



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

* [PATCH 4/5] cobalt/kernel: y2038: convert struct itimerspec to itimerspec64
  2021-02-20 15:18 [PATCH 1/5] cobalt/kernel: y2038: convert struct timeval to __kernel_old_timeval Philippe Gerum
  2021-02-20 15:18 ` [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64 Philippe Gerum
  2021-02-20 15:18 ` [PATCH 3/5] lib: y2038: convert to internal timespec type Philippe Gerum
@ 2021-02-20 15:18 ` Philippe Gerum
  2021-02-20 15:18 ` [PATCH 5/5] cobalt/kernel: y2038: convert struct timex to __kernel_timex Philippe Gerum
  3 siblings, 0 replies; 57+ messages in thread
From: Philippe Gerum @ 2021-02-20 15:18 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai, Philippe Gerum

From: Philippe Gerum <rpm@xenomai.org>

As internal interfaces are gradually being made y2038-safe, the
itimerspec64 type should be used internally by the kernel to represent
interval timer specs. Apply the same reasoning to Cobalt.

We still use a legacy y2038-unsafe itimerspec type at the
kernel<->user interface boundary (struct __user_old_itimerspec) until
libcobalt is y2038-safe.

Signed-off-by: Philippe Gerum <rpm@xenomai.org>
---
 include/cobalt/kernel/compat.h                |  4 +-
 include/cobalt/uapi/kernel/types.h            |  5 ++
 .../include/asm-generic/xenomai/syscall.h     | 47 ++++++++++++++++++-
 kernel/cobalt/posix/compat.c                  |  4 +-
 kernel/cobalt/posix/extension.h               |  4 +-
 kernel/cobalt/posix/syscall32.c               |  8 ++--
 kernel/cobalt/posix/timer.c                   | 30 ++++++------
 kernel/cobalt/posix/timer.h                   | 16 +++----
 kernel/cobalt/posix/timerfd.c                 | 22 ++++-----
 kernel/cobalt/posix/timerfd.h                 | 12 ++---
 10 files changed, 101 insertions(+), 51 deletions(-)

diff --git a/include/cobalt/kernel/compat.h b/include/cobalt/kernel/compat.h
index c57ef6532..7bec8c3be 100644
--- a/include/cobalt/kernel/compat.h
+++ b/include/cobalt/kernel/compat.h
@@ -92,11 +92,11 @@ int sys32_get_timespec(struct timespec64 *ts,
 int sys32_put_timespec(struct compat_timespec __user *cts,
 		       const struct timespec64 *ts);
 
-int sys32_get_itimerspec(struct itimerspec *its,
+int sys32_get_itimerspec(struct itimerspec64 *its,
 			 const struct compat_itimerspec __user *cits);
 
 int sys32_put_itimerspec(struct compat_itimerspec __user *cits,
-			 const struct itimerspec *its);
+			 const struct itimerspec64 *its);
 
 int sys32_get_timeval(struct __kernel_old_timeval *tv,
 		      const struct compat_timeval __user *ctv);
diff --git a/include/cobalt/uapi/kernel/types.h b/include/cobalt/uapi/kernel/types.h
index 8ce9b03df..10abbb55a 100644
--- a/include/cobalt/uapi/kernel/types.h
+++ b/include/cobalt/uapi/kernel/types.h
@@ -67,4 +67,9 @@ struct __user_old_timespec {
 	long  tv_nsec;
 };
 
+struct __user_old_itimerspec {
+	struct __user_old_timespec it_interval;
+	struct __user_old_timespec it_value;
+};
+
 #endif /* !_COBALT_UAPI_KERNEL_TYPES_H */
diff --git a/kernel/cobalt/include/asm-generic/xenomai/syscall.h b/kernel/cobalt/include/asm-generic/xenomai/syscall.h
index 05a7d2868..91bbf3bfd 100644
--- a/kernel/cobalt/include/asm-generic/xenomai/syscall.h
+++ b/kernel/cobalt/include/asm-generic/xenomai/syscall.h
@@ -86,7 +86,7 @@ static inline int cobalt_strncpy_from_user(char *dst, const char __user *src,
 
 /*
  * NOTE: those copy helpers won't work in compat mode: use
- * sys32_get_timespec(), sys32_put_timespec() instead.
+ * sys32_get_*(), sys32_put_*() instead.
  */
 
 static inline int cobalt_get_u_timespec(struct timespec64 *dst,
@@ -102,6 +102,19 @@ static inline int cobalt_put_u_timespec(
 	return cobalt_copy_to_user(dst, src, sizeof(*dst));
 }
 
+static inline int cobalt_get_u_itimerspec(struct itimerspec64 *dst,
+			const struct __user_old_itimerspec __user *src)
+{
+	return cobalt_copy_from_user(dst, src, sizeof(*dst));
+}
+
+static inline int cobalt_put_u_itimerspec(
+	struct __user_old_itimerspec __user *dst,
+	const struct itimerspec64 *src)
+{
+	return cobalt_copy_to_user(dst, src, sizeof(*dst));
+}
+
 #else /* __BITS_PER_LONG == 32 */
 
 static inline int cobalt_get_u_timespec(struct timespec64 *dst,
@@ -137,6 +150,38 @@ static inline int cobalt_put_u_timespec(
 	return 0;
 }
 
+static inline int cobalt_get_u_itimerspec(struct itimerspec64 *dst,
+			const struct __user_old_itimerspec __user *src)
+{
+	struct __user_old_itimerspec u_its;
+	int ret;
+
+	ret = cobalt_copy_from_user(&u_its, src, sizeof(u_its));
+	if (ret)
+		return ret;
+
+	dst->it_interval.tv_sec = u_its.it_interval.tv_sec;
+	dst->it_interval.tv_nsec = u_its.it_interval.tv_nsec;
+	dst->it_value.tv_sec = u_its.it_value.tv_sec;
+	dst->it_value.tv_nsec = u_its.it_value.tv_nsec;
+
+	return 0;
+}
+
+static inline int cobalt_put_u_itimerspec(
+	struct __user_old_itimerspec __user *dst,
+	const struct itimerspec64 *src)
+{
+	struct __user_old_itimerspec u_its;
+
+	u_its.it_interval.tv_sec = src->it_interval.tv_sec;
+	u_its.it_interval.tv_nsec = src->it_interval.tv_nsec;
+	u_its.it_value.tv_sec = src->it_value.tv_sec;
+	u_its.it_value.tv_nsec = src->it_value.tv_nsec;
+
+	return cobalt_copy_to_user(dst, &u_its, sizeof(*dst));
+}
+
 #endif
 
 /* 32bit syscall emulation */
diff --git a/kernel/cobalt/posix/compat.c b/kernel/cobalt/posix/compat.c
index 185295082..767a8033a 100644
--- a/kernel/cobalt/posix/compat.c
+++ b/kernel/cobalt/posix/compat.c
@@ -60,7 +60,7 @@ int sys32_put_timespec(struct compat_timespec __user *u_cts,
 }
 EXPORT_SYMBOL_GPL(sys32_put_timespec);
 
-int sys32_get_itimerspec(struct itimerspec *its,
+int sys32_get_itimerspec(struct itimerspec64 *its,
 			 const struct compat_itimerspec __user *cits)
 {
 	int ret = sys32_get_timespec(&its->it_value, &cits->it_value);
@@ -70,7 +70,7 @@ int sys32_get_itimerspec(struct itimerspec *its,
 EXPORT_SYMBOL_GPL(sys32_get_itimerspec);
 
 int sys32_put_itimerspec(struct compat_itimerspec __user *cits,
-			 const struct itimerspec *its)
+			 const struct itimerspec64 *its)
 {
 	int ret = sys32_put_timespec(&cits->it_value, &its->it_value);
 
diff --git a/kernel/cobalt/posix/extension.h b/kernel/cobalt/posix/extension.h
index ae365c787..e23c26ccc 100644
--- a/kernel/cobalt/posix/extension.h
+++ b/kernel/cobalt/posix/extension.h
@@ -39,10 +39,10 @@ struct cobalt_extension {
 		(*timer_init)(struct cobalt_extref *reftimer, /* nklocked, IRQs off. */
 			      const struct sigevent *__restrict__ evp);
 		int (*timer_settime)(struct cobalt_extref *reftimer, /* nklocked, IRQs off. */
-				     const struct itimerspec *__restrict__ value,
+				     const struct itimerspec64 *__restrict__ value,
 				     int flags);
 		int (*timer_gettime)(struct cobalt_extref *reftimer, /* nklocked, IRQs off. */
-				     struct itimerspec *__restrict__ value);
+				     struct itimerspec64 *__restrict__ value);
 		int (*timer_delete)(struct cobalt_extref *reftimer); /* nklocked, IRQs off. */
 		int (*timer_cleanup)(struct cobalt_extref *reftimer); /* nklocked, IRQs off. */
 		int (*signal_deliver)(struct cobalt_extref *refthread,
diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
index ae25a6e74..5c858806b 100644
--- a/kernel/cobalt/posix/syscall32.c
+++ b/kernel/cobalt/posix/syscall32.c
@@ -514,7 +514,7 @@ COBALT_SYSCALL32emu(timer_settime, primary,
 		     const struct compat_itimerspec __user *u_newval,
 		     struct compat_itimerspec __user *u_oldval))
 {
-	struct itimerspec newv, oldv, *oldvp = &oldv;
+	struct itimerspec64 newv, oldv, *oldvp = &oldv;
 	int ret;
 
 	if (u_oldval == NULL)
@@ -540,7 +540,7 @@ COBALT_SYSCALL32emu(timer_settime, primary,
 COBALT_SYSCALL32emu(timer_gettime, current,
 		    (timer_t tm, struct compat_itimerspec __user *u_val))
 {
-	struct itimerspec val;
+	struct itimerspec64 val;
 	int ret;
 
 	ret = __cobalt_timer_gettime(tm, &val);
@@ -553,7 +553,7 @@ COBALT_SYSCALL32emu(timerfd_settime, primary,
 		     const struct compat_itimerspec __user *new_value,
 		     struct compat_itimerspec __user *old_value))
 {
-	struct itimerspec ovalue, value;
+	struct itimerspec64 ovalue, value;
 	int ret;
 
 	ret = sys32_get_itimerspec(&value, new_value);
@@ -577,7 +577,7 @@ COBALT_SYSCALL32emu(timerfd_settime, primary,
 COBALT_SYSCALL32emu(timerfd_gettime, current,
 		    (int fd, struct compat_itimerspec __user *curr_value))
 {
-	struct itimerspec value;
+	struct itimerspec64 value;
 	int ret;
 
 	ret = __cobalt_timerfd_gettime(fd, &value);
diff --git a/kernel/cobalt/posix/timer.c b/kernel/cobalt/posix/timer.c
index 3aca90de9..a58ea99a3 100644
--- a/kernel/cobalt/posix/timer.c
+++ b/kernel/cobalt/posix/timer.c
@@ -261,7 +261,7 @@ out:
 }
 
 void __cobalt_timer_getval(struct xntimer *__restrict__ timer,
-			   struct itimerspec *__restrict__ value)
+			   struct itimerspec64 *__restrict__ value)
 {
 	ns2ts(&value->it_interval, xntimer_interval(timer));
 
@@ -275,7 +275,7 @@ void __cobalt_timer_getval(struct xntimer *__restrict__ timer,
 
 static inline void
 timer_gettimeout(struct cobalt_timer *__restrict__ timer,
-		 struct itimerspec *__restrict__ value)
+		 struct itimerspec64 *__restrict__ value)
 {
 	int ret = 0;
 
@@ -287,7 +287,7 @@ timer_gettimeout(struct cobalt_timer *__restrict__ timer,
 }
 
 int __cobalt_timer_setval(struct xntimer *__restrict__ timer, int clock_flag,
-			  const struct itimerspec *__restrict__ value)
+			  const struct itimerspec64 *__restrict__ value)
 {
 	xnticks_t start, period;
 
@@ -312,7 +312,7 @@ int __cobalt_timer_setval(struct xntimer *__restrict__ timer, int clock_flag,
 }
 
 static inline int timer_set(struct cobalt_timer *timer, int flags,
-			    const struct itimerspec *__restrict__ value)
+			    const struct itimerspec64 *__restrict__ value)
 {				/* nklocked, IRQs off. */
 	struct cobalt_thread *thread;
 	int ret = 0;
@@ -362,8 +362,8 @@ timer_deliver_late(struct cobalt_process *cc, timer_t timerid)
 }
 
 int __cobalt_timer_settime(timer_t timerid, int flags,
-			   const struct itimerspec *__restrict__ value,
-			   struct itimerspec *__restrict__ ovalue)
+			   const struct itimerspec64 *__restrict__ value,
+			   struct itimerspec64 *__restrict__ ovalue)
 {
 	struct cobalt_timer *timer;
 	struct cobalt_process *cc;
@@ -402,7 +402,7 @@ out:
 	return ret;
 }
 
-int __cobalt_timer_gettime(timer_t timerid, struct itimerspec *value)
+int __cobalt_timer_gettime(timer_t timerid, struct itimerspec64 *value)
 {
 	struct cobalt_timer *timer;
 	struct cobalt_process *cc;
@@ -471,23 +471,23 @@ COBALT_SYSCALL(timer_create, current,
 
 COBALT_SYSCALL(timer_settime, primary,
 	       (timer_t tm, int flags,
-		const struct itimerspec __user *u_newval,
-		struct itimerspec __user *u_oldval))
+		const struct __user_old_itimerspec __user *u_newval,
+		struct __user_old_itimerspec __user *u_oldval))
 {
-	struct itimerspec newv, oldv, *oldvp = &oldv;
+	struct itimerspec64 newv, oldv, *oldvp = &oldv;
 	int ret;
 
 	if (u_oldval == NULL)
 		oldvp = NULL;
 
-	if (cobalt_copy_from_user(&newv, u_newval, sizeof(newv)))
+	if (cobalt_get_u_itimerspec(&newv, u_newval))
 		return -EFAULT;
 
 	ret = __cobalt_timer_settime(tm, flags, &newv, oldvp);
 	if (ret)
 		return ret;
 
-	if (oldvp && cobalt_copy_to_user(u_oldval, oldvp, sizeof(oldv))) {
+	if (oldvp && cobalt_put_u_itimerspec(u_oldval, oldvp)) {
 		__cobalt_timer_settime(tm, flags, oldvp, NULL);
 		return -EFAULT;
 	}
@@ -496,16 +496,16 @@ COBALT_SYSCALL(timer_settime, primary,
 }
 
 COBALT_SYSCALL(timer_gettime, current,
-	       (timer_t tm, struct itimerspec __user *u_val))
+	       (timer_t tm, struct __user_old_itimerspec __user *u_val))
 {
-	struct itimerspec val;
+	struct itimerspec64 val;
 	int ret;
 
 	ret = __cobalt_timer_gettime(tm, &val);
 	if (ret)
 		return ret;
 
-	return cobalt_copy_to_user(u_val, &val, sizeof(val));
+	return cobalt_put_u_itimerspec(u_val, &val);
 }
 
 COBALT_SYSCALL(timer_getoverrun, current, (timer_t timerid))
diff --git a/kernel/cobalt/posix/timer.h b/kernel/cobalt/posix/timer.h
index 0f5402aee..3b580d470 100644
--- a/kernel/cobalt/posix/timer.h
+++ b/kernel/cobalt/posix/timer.h
@@ -51,20 +51,20 @@ cobalt_timer_by_id(struct cobalt_process *p, timer_t timer_id);
 void cobalt_timer_handler(struct xntimer *xntimer);
 
 void __cobalt_timer_getval(struct xntimer *__restrict__ timer, 
-			   struct itimerspec *__restrict__ value);
+			   struct itimerspec64 *__restrict__ value);
 
 int __cobalt_timer_setval(struct xntimer *__restrict__ timer, int clock_flag, 
-			  const struct itimerspec *__restrict__ value);
+			  const struct itimerspec64 *__restrict__ value);
 
 int __cobalt_timer_create(clockid_t clock,
 			  const struct sigevent *sev,
 			  timer_t __user *u_tm);
 
 int __cobalt_timer_settime(timer_t timerid, int flags,
-			   const struct itimerspec *__restrict__ value,
-			   struct itimerspec *__restrict__ ovalue);
+			   const struct itimerspec64 *__restrict__ value,
+			   struct itimerspec64 *__restrict__ ovalue);
 
-int __cobalt_timer_gettime(timer_t timerid, struct itimerspec *value);
+int __cobalt_timer_gettime(timer_t timerid, struct itimerspec64 *value);
 
 COBALT_SYSCALL_DECL(timer_create,
 		    (clockid_t clock,
@@ -75,11 +75,11 @@ COBALT_SYSCALL_DECL(timer_delete, (timer_t tm));
 
 COBALT_SYSCALL_DECL(timer_settime,
 		    (timer_t tm, int flags,
-		     const struct itimerspec __user *u_newval,
-		     struct itimerspec __user *u_oldval));
+		     const struct __user_old_itimerspec __user *u_newval,
+		     struct __user_old_itimerspec __user *u_oldval));
 
 COBALT_SYSCALL_DECL(timer_gettime,
-		    (timer_t tm, struct itimerspec __user *u_val));
+		    (timer_t tm, struct __user_old_itimerspec __user *u_val));
 
 COBALT_SYSCALL_DECL(timer_getoverrun, (timer_t tm));
 
diff --git a/kernel/cobalt/posix/timerfd.c b/kernel/cobalt/posix/timerfd.c
index 29046cfec..472c4cba0 100644
--- a/kernel/cobalt/posix/timerfd.c
+++ b/kernel/cobalt/posix/timerfd.c
@@ -32,7 +32,7 @@ struct cobalt_tfd {
 	struct rtdm_fd fd;
 	struct xntimer timer;
 	DECLARE_XNSELECT(read_select);
-	struct itimerspec value;
+	struct itimerspec64 value;
 	struct xnsynch readers;
 	struct xnthread *target;
 };
@@ -236,8 +236,8 @@ static inline void tfd_put(struct cobalt_tfd *tfd)
 }
 
 int __cobalt_timerfd_settime(int fd, int flags,
-			     const struct itimerspec *value,
-			     struct itimerspec *ovalue)
+			     const struct itimerspec64 *value,
+			     struct itimerspec64 *ovalue)
 {
 	struct cobalt_tfd *tfd;
 	int cflag, ret;
@@ -280,13 +280,13 @@ out:
 
 COBALT_SYSCALL(timerfd_settime, primary,
 	       (int fd, int flags,
-		const struct itimerspec __user *new_value,
-		struct itimerspec __user *old_value))
+		const struct __user_old_itimerspec __user *new_value,
+		struct __user_old_itimerspec __user *old_value))
 {
-	struct itimerspec ovalue, value;
+	struct itimerspec64 ovalue, value;
 	int ret;
 
-	ret = cobalt_copy_from_user(&value, new_value, sizeof(value));
+	ret = cobalt_get_u_itimerspec(&value, new_value);
 	if (ret)
 		return ret;
 
@@ -304,7 +304,7 @@ COBALT_SYSCALL(timerfd_settime, primary,
 	return ret;
 }
 
-int __cobalt_timerfd_gettime(int fd, struct itimerspec *value)
+int __cobalt_timerfd_gettime(int fd, struct itimerspec64 *value)
 {
 	struct cobalt_tfd *tfd;
 	spl_t s;
@@ -323,12 +323,12 @@ int __cobalt_timerfd_gettime(int fd, struct itimerspec *value)
 }
 
 COBALT_SYSCALL(timerfd_gettime, current,
-	       (int fd, struct itimerspec __user *curr_value))
+	       (int fd, struct __user_old_itimerspec __user *curr_value))
 {
-	struct itimerspec value;
+	struct itimerspec64 value;
 	int ret;
 
 	ret = __cobalt_timerfd_gettime(fd, &value);
 
-	return ret ?: cobalt_copy_to_user(curr_value, &value, sizeof(value));
+	return ret ?: cobalt_put_u_itimerspec(curr_value, &value);
 }
diff --git a/kernel/cobalt/posix/timerfd.h b/kernel/cobalt/posix/timerfd.h
index 5787ff60a..245b8698b 100644
--- a/kernel/cobalt/posix/timerfd.h
+++ b/kernel/cobalt/posix/timerfd.h
@@ -22,21 +22,21 @@
 #include <xenomai/posix/syscall.h>
 
 int __cobalt_timerfd_settime(int fd, int flags,
-			     const struct itimerspec *new_value,
-			     struct itimerspec *old_value);
+			     const struct itimerspec64 *new_value,
+			     struct itimerspec64 *old_value);
 
 int __cobalt_timerfd_gettime(int fd,
-			     struct itimerspec *value);
+			     struct itimerspec64 *value);
 
 COBALT_SYSCALL_DECL(timerfd_create,
 		    (int clockid, int flags));
 
 COBALT_SYSCALL_DECL(timerfd_settime,
 		    (int fd, int flags,
-		     const struct itimerspec __user *new_value,
-		     struct itimerspec __user *old_value));
+		     const struct __user_old_itimerspec __user *new_value,
+		     struct __user_old_itimerspec __user *old_value));
 
 COBALT_SYSCALL_DECL(timerfd_gettime,
-		    (int fd, struct itimerspec __user *curr_value));
+		    (int fd, struct __user_old_itimerspec __user *curr_value));
 
 #endif /* TIMERFD_H */
-- 
2.26.2



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

* [PATCH 5/5] cobalt/kernel: y2038: convert struct timex to __kernel_timex
  2021-02-20 15:18 [PATCH 1/5] cobalt/kernel: y2038: convert struct timeval to __kernel_old_timeval Philippe Gerum
                   ` (2 preceding siblings ...)
  2021-02-20 15:18 ` [PATCH 4/5] cobalt/kernel: y2038: convert struct itimerspec to itimerspec64 Philippe Gerum
@ 2021-02-20 15:18 ` Philippe Gerum
  3 siblings, 0 replies; 57+ messages in thread
From: Philippe Gerum @ 2021-02-20 15:18 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai, Philippe Gerum

From: Philippe Gerum <rpm@xenomai.org>

As internal interfaces are gradually being made y2038-safe, the
__kernel_timex type should be used internally by the kernel to
represent time adjustment parameters. Apply the same reasoning to
Cobalt.

We still use a legacy y2038-unsafe timex type at the kernel<->user
interface boundary (struct __user_old_timex) until libcobalt is
y2038-safe.

Signed-off-by: Philippe Gerum <rpm@xenomai.org>
---
 include/cobalt/kernel/clock.h                 |  7 +--
 include/cobalt/kernel/compat.h                |  4 +-
 include/cobalt/uapi/kernel/types.h            | 44 +++++++++++++++++--
 .../include/asm-generic/xenomai/wrappers.h    |  4 ++
 kernel/cobalt/posix/clock.c                   |  6 +--
 kernel/cobalt/posix/clock.h                   |  4 +-
 kernel/cobalt/posix/compat.c                  | 28 +++++++++---
 kernel/cobalt/posix/syscall32.c               |  2 +-
 kernel/cobalt/trace/cobalt-posix.h            |  4 +-
 9 files changed, 81 insertions(+), 22 deletions(-)

diff --git a/include/cobalt/kernel/clock.h b/include/cobalt/kernel/clock.h
index 1c99173ff..0e4f1e1cb 100644
--- a/include/cobalt/kernel/clock.h
+++ b/include/cobalt/kernel/clock.h
@@ -24,6 +24,7 @@
 #include <cobalt/kernel/list.h>
 #include <cobalt/kernel/vfile.h>
 #include <cobalt/uapi/kernel/types.h>
+#include <asm/xenomai/wrappers.h>
 
 /**
  * @addtogroup cobalt_core_clock
@@ -32,7 +33,7 @@
 
 struct xnsched;
 struct xntimerdata;
-struct timex;
+struct __kernel_timex;
 
 struct xnclock_gravity {
 	unsigned long irq;
@@ -67,7 +68,7 @@ struct xnclock {
 					    struct xnsched *sched);
 #endif
 		int (*adjust_time)(struct xnclock *clock,
-				   struct timex *tx);
+				   struct __kernel_timex *tx);
 		int (*set_gravity)(struct xnclock *clock,
 				   const struct xnclock_gravity *p);
 		void (*reset_gravity)(struct xnclock *clock);
@@ -275,7 +276,7 @@ static inline int xnclock_set_time(struct xnclock *clock,
 #endif /* !CONFIG_XENO_OPT_EXTCLOCK */
 
 static inline int xnclock_adjust_time(struct xnclock *clock,
-				      struct timex *tx)
+				      struct __kernel_timex *tx)
 {
 	if (clock->ops.adjust_time == NULL)
 		return -EOPNOTSUPP;
diff --git a/include/cobalt/kernel/compat.h b/include/cobalt/kernel/compat.h
index 7bec8c3be..d7f0008d9 100644
--- a/include/cobalt/kernel/compat.h
+++ b/include/cobalt/kernel/compat.h
@@ -104,11 +104,11 @@ int sys32_get_timeval(struct __kernel_old_timeval *tv,
 int sys32_put_timeval(struct compat_timeval __user *ctv,
 		      const struct __kernel_old_timeval *tv);
 
-int sys32_get_timex(struct timex *tx,
+int sys32_get_timex(struct __kernel_timex *tx,
 		    const struct old_timex32 __user *ctx);
 
 int sys32_put_timex(struct old_timex32 __user *ctx,
-		    const struct timex *tx);
+		    const struct __kernel_timex *tx);
 
 ssize_t sys32_get_fdset(fd_set *fds, const compat_fd_set __user *cfds,
 			size_t cfdsize);
diff --git a/include/cobalt/uapi/kernel/types.h b/include/cobalt/uapi/kernel/types.h
index 10abbb55a..2c931c29c 100644
--- a/include/cobalt/uapi/kernel/types.h
+++ b/include/cobalt/uapi/kernel/types.h
@@ -58,9 +58,10 @@ static inline xnhandle_t xnhandle_get_id(xnhandle_t handle)
 }
 
 /*
- * Our representation of time at the kernel<->user interface boundary
- * at the moment, until we have fully transitioned to a y2038-safe
- * implementation in libcobalt.
+ * Our representation of time specs at the kernel<->user interface
+ * boundary at the moment, until we have fully transitioned to a
+ * y2038-safe implementation in libcobalt. Once done, those legacy
+ * types will be removed.
  */
 struct __user_old_timespec {
 	long  tv_sec;
@@ -72,4 +73,41 @@ struct __user_old_itimerspec {
 	struct __user_old_timespec it_value;
 };
 
+struct __user_old_timeval {
+	long  tv_sec;
+	long  tv_usec;
+};
+
+/* Lifted from include/uapi/linux/timex.h. */
+struct __user_old_timex {
+	unsigned int modes;	/* mode selector */
+	__kernel_long_t offset;	/* time offset (usec) */
+	__kernel_long_t freq;	/* frequency offset (scaled ppm) */
+	__kernel_long_t maxerror;/* maximum error (usec) */
+	__kernel_long_t esterror;/* estimated error (usec) */
+	int status;		/* clock command/status */
+	__kernel_long_t constant;/* pll time constant */
+	__kernel_long_t precision;/* clock precision (usec) (read only) */
+	__kernel_long_t tolerance;/* clock frequency tolerance (ppm)
+				   * (read only)
+				   */
+	struct __user_old_timeval time;	/* (read only, except for ADJ_SETOFFSET) */
+	__kernel_long_t tick;	/* (modified) usecs between clock ticks */
+
+	__kernel_long_t ppsfreq;/* pps frequency (scaled ppm) (ro) */
+	__kernel_long_t jitter; /* pps jitter (us) (ro) */
+	int shift;              /* interval duration (s) (shift) (ro) */
+	__kernel_long_t stabil;            /* pps stability (scaled ppm) (ro) */
+	__kernel_long_t jitcnt; /* jitter limit exceeded (ro) */
+	__kernel_long_t calcnt; /* calibration intervals (ro) */
+	__kernel_long_t errcnt; /* calibration errors (ro) */
+	__kernel_long_t stbcnt; /* stability limit exceeded (ro) */
+
+	int tai;		/* TAI offset (ro) */
+
+	int  :32; int  :32; int  :32; int  :32;
+	int  :32; int  :32; int  :32; int  :32;
+	int  :32; int  :32; int  :32;
+};
+
 #endif /* !_COBALT_UAPI_KERNEL_TYPES_H */
diff --git a/kernel/cobalt/include/asm-generic/xenomai/wrappers.h b/kernel/cobalt/include/asm-generic/xenomai/wrappers.h
index 2e9fb203a..eaeeafd68 100644
--- a/kernel/cobalt/include/asm-generic/xenomai/wrappers.h
+++ b/kernel/cobalt/include/asm-generic/xenomai/wrappers.h
@@ -152,6 +152,10 @@ devm_hwmon_device_register_with_groups(struct device *dev, const char *name,
 #error "Xenomai/cobalt requires Linux kernel 3.10 or above"
 #endif /* < 3.10 */
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
+#define __kernel_timex		timex
+#endif
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(5,1,0)
 #define old_timex32		compat_timex
 #define SO_RCVTIMEO_OLD		SO_RCVTIMEO
diff --git a/kernel/cobalt/posix/clock.c b/kernel/cobalt/posix/clock.c
index 4a3365d2a..23a45bba9 100644
--- a/kernel/cobalt/posix/clock.c
+++ b/kernel/cobalt/posix/clock.c
@@ -166,7 +166,7 @@ int __cobalt_clock_settime(clockid_t clock_id, const struct timespec64 *ts)
 	return 0;
 }
 
-int __cobalt_clock_adjtime(clockid_t clock_id, struct timex *tx)
+int __cobalt_clock_adjtime(clockid_t clock_id, struct __kernel_timex *tx)
 {
 	int _ret, ret = 0;
 
@@ -199,9 +199,9 @@ COBALT_SYSCALL(clock_settime, current,
 }
 
 COBALT_SYSCALL(clock_adjtime, current,
-	       (clockid_t clock_id, struct timex __user *u_tx))
+	       (clockid_t clock_id, struct __user_old_timex __user *u_tx))
 {
-	struct timex tx;
+	struct __kernel_timex tx;
 	int ret;
 
 	if (cobalt_copy_from_user(&tx, u_tx, sizeof(tx)))
diff --git a/kernel/cobalt/posix/clock.h b/kernel/cobalt/posix/clock.h
index 7e45fdcc6..e69e76e1b 100644
--- a/kernel/cobalt/posix/clock.h
+++ b/kernel/cobalt/posix/clock.h
@@ -104,7 +104,7 @@ int __cobalt_clock_settime(clockid_t clock_id,
 			   const struct timespec64 *ts);
 
 int __cobalt_clock_adjtime(clockid_t clock_id,
-			   struct timex *tx);
+			   struct __kernel_timex *tx);
 
 int __cobalt_clock_nanosleep(clockid_t clock_id, int flags,
 			     const struct timespec64 *rqt,
@@ -120,7 +120,7 @@ COBALT_SYSCALL_DECL(clock_settime,
 		    (clockid_t clock_id, const struct __user_old_timespec __user *u_ts));
 
 COBALT_SYSCALL_DECL(clock_adjtime,
-		    (clockid_t clock_id, struct timex __user *u_tx));
+		    (clockid_t clock_id, struct __user_old_timex __user *u_tx));
 
 COBALT_SYSCALL_DECL(clock_nanosleep,
 		    (clockid_t clock_id, int flags,
diff --git a/kernel/cobalt/posix/compat.c b/kernel/cobalt/posix/compat.c
index 767a8033a..6002d7480 100644
--- a/kernel/cobalt/posix/compat.c
+++ b/kernel/cobalt/posix/compat.c
@@ -98,11 +98,21 @@ int sys32_put_timeval(struct compat_timeval __user *ctv,
 }
 EXPORT_SYMBOL_GPL(sys32_put_timeval);
 
-int sys32_get_timex(struct timex *tx,
+int sys32_get_timex(struct __kernel_timex *tx,
 		    const struct old_timex32 __user *ctx)
 {
+	struct __kernel_old_timeval time;
+	int ret;
+
 	memset(tx, 0, sizeof(*tx));
 
+	ret = sys32_get_timeval(&time, &ctx->time);
+	if (ret)
+		return ret;
+
+	tx->time.tv_sec = time.tv_sec;
+	tx->time.tv_usec = time.tv_usec;
+
 	if (!access_rok(ctx, sizeof(*ctx)) ||
 	    __xn_get_user(tx->modes, &ctx->modes) ||
 	    __xn_get_user(tx->offset, &ctx->offset) ||
@@ -113,8 +123,6 @@ int sys32_get_timex(struct timex *tx,
 	    __xn_get_user(tx->constant, &ctx->constant) ||
 	    __xn_get_user(tx->precision, &ctx->precision) ||
 	    __xn_get_user(tx->tolerance, &ctx->tolerance) ||
-	    __xn_get_user(tx->time.tv_sec, &ctx->time.tv_sec) ||
-	    __xn_get_user(tx->time.tv_usec, &ctx->time.tv_usec) ||
 	    __xn_get_user(tx->tick, &ctx->tick) ||
 	    __xn_get_user(tx->ppsfreq, &ctx->ppsfreq) ||
 	    __xn_get_user(tx->jitter, &ctx->jitter) ||
@@ -131,8 +139,18 @@ int sys32_get_timex(struct timex *tx,
 EXPORT_SYMBOL_GPL(sys32_get_timex);
 
 int sys32_put_timex(struct old_timex32 __user *ctx,
-		    const struct timex *tx)
+		    const struct __kernel_timex *tx)
 {
+	struct __kernel_old_timeval time;
+	int ret;
+
+	time.tv_sec = tx->time.tv_sec;
+	time.tv_usec = tx->time.tv_usec;
+
+	ret = sys32_put_timeval(&ctx->time, &time);
+	if (ret)
+		return ret;
+
 	if (!access_wok(ctx, sizeof(*ctx)) ||
 	    __xn_put_user(tx->modes, &ctx->modes) ||
 	    __xn_put_user(tx->offset, &ctx->offset) ||
@@ -143,8 +161,6 @@ int sys32_put_timex(struct old_timex32 __user *ctx,
 	    __xn_put_user(tx->constant, &ctx->constant) ||
 	    __xn_put_user(tx->precision, &ctx->precision) ||
 	    __xn_put_user(tx->tolerance, &ctx->tolerance) ||
-	    __xn_put_user(tx->time.tv_sec, &ctx->time.tv_sec) ||
-	    __xn_put_user(tx->time.tv_usec, &ctx->time.tv_usec) ||
 	    __xn_put_user(tx->tick, &ctx->tick) ||
 	    __xn_put_user(tx->ppsfreq, &ctx->ppsfreq) ||
 	    __xn_put_user(tx->jitter, &ctx->jitter) ||
diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
index 5c858806b..4f819e0e5 100644
--- a/kernel/cobalt/posix/syscall32.c
+++ b/kernel/cobalt/posix/syscall32.c
@@ -174,7 +174,7 @@ COBALT_SYSCALL32emu(clock_settime, current,
 COBALT_SYSCALL32emu(clock_adjtime, current,
 		    (clockid_t clock_id, struct old_timex32 __user *u_tx))
 {
-	struct timex tx;
+	struct __kernel_timex tx;
 	int ret;
 
 	ret = sys32_get_timex(&tx, u_tx);
diff --git a/kernel/cobalt/trace/cobalt-posix.h b/kernel/cobalt/trace/cobalt-posix.h
index 3a649a671..cff1bd9b7 100644
--- a/kernel/cobalt/trace/cobalt-posix.h
+++ b/kernel/cobalt/trace/cobalt-posix.h
@@ -764,12 +764,12 @@ DEFINE_EVENT(cobalt_clock_timespec, cobalt_clock_settime,
 );
 
 TRACE_EVENT(cobalt_clock_adjtime,
-	TP_PROTO(clockid_t clk_id, struct timex *tx),
+	TP_PROTO(clockid_t clk_id, struct __kernel_timex *tx),
 	TP_ARGS(clk_id, tx),
 
 	TP_STRUCT__entry(
 		__field(clockid_t, clk_id)
-		__field(struct timex *, tx)
+		__field(struct __kernel_timex *, tx)
 	),
 
 	TP_fast_assign(
-- 
2.26.2



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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-02-20 15:18 ` [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64 Philippe Gerum
@ 2021-02-21  2:17   ` chensong
  2021-02-21 15:27     ` Philippe Gerum
  2021-03-03 10:05   ` florian.bezdeka
  2021-03-03 14:36   ` florian.bezdeka
  2 siblings, 1 reply; 57+ messages in thread
From: chensong @ 2021-02-21  2:17 UTC (permalink / raw)
  To: xenomai



On 2021年02月20日 23:18, Philippe Gerum via Xenomai wrote:
> From: Philippe Gerum <rpm@xenomai.org>
>
> As internal interfaces are gradually being made y2038-safe, the
> timespec64 type should be used internally by the kernel to represent
> time values. Apply the same reasoning to Cobalt.
>
> We still use a legacy y2038-unsafe timespec type at the kernel<->user
> interface boundary (struct __user_old_timespec) until libcobalt is
> y2038-safe.
>
> Signed-off-by: Philippe Gerum <rpm@xenomai.org>
> ---
>   include/cobalt/kernel/clock.h                 |  6 +-
>   include/cobalt/kernel/compat.h                |  4 +-
>   .../cobalt/kernel/dovetail/pipeline/clock.h   |  4 +-
>   include/cobalt/kernel/ipipe/pipeline/clock.h  |  4 +-
>   include/cobalt/kernel/rtdm/fd.h               |  2 +-
>   include/cobalt/uapi/kernel/types.h            | 10 ++++
>   include/cobalt/uapi/sched.h                   | 12 ++--
>   .../include/asm-generic/xenomai/syscall.h     | 58 +++++++++++++++++++
>   kernel/cobalt/ipipe/clock.c                   |  2 +-
>   kernel/cobalt/posix/clock.c                   | 38 ++++++------
>   kernel/cobalt/posix/clock.h                   | 39 +++++++++----
>   kernel/cobalt/posix/compat.c                  | 46 ++++++++++-----
>   kernel/cobalt/posix/cond.c                    | 11 ++--
>   kernel/cobalt/posix/cond.h                    |  4 +-
>   kernel/cobalt/posix/event.c                   |  8 +--
>   kernel/cobalt/posix/event.h                   |  4 +-
>   kernel/cobalt/posix/io.c                      |  6 +-
>   kernel/cobalt/posix/io.h                      |  2 +-
>   kernel/cobalt/posix/monitor.c                 |  8 +--
>   kernel/cobalt/posix/monitor.h                 |  4 +-
>   kernel/cobalt/posix/mqueue.c                  | 18 +++---
>   kernel/cobalt/posix/mqueue.h                  |  8 +--
>   kernel/cobalt/posix/mutex.c                   | 10 ++--
>   kernel/cobalt/posix/mutex.h                   |  6 +-
>   kernel/cobalt/posix/sched.c                   | 16 ++---
>   kernel/cobalt/posix/sem.c                     |  8 +--
>   kernel/cobalt/posix/sem.h                     |  4 +-
>   kernel/cobalt/posix/signal.c                  |  6 +-
>   kernel/cobalt/posix/signal.h                  |  4 +-
>   kernel/cobalt/posix/syscall32.c               | 26 ++++-----
>   kernel/cobalt/posix/syscall32.h               |  2 +-
>   kernel/cobalt/posix/thread.c                  |  6 +-
>   kernel/cobalt/rtdm/fd.c                       |  4 +-
>   kernel/cobalt/trace/cobalt-posix.h            | 30 +++++-----
>   34 files changed, 260 insertions(+), 160 deletions(-)
>
> diff --git a/include/cobalt/kernel/clock.h b/include/cobalt/kernel/clock.h
> index bbf34c53c..1c99173ff 100644
> --- a/include/cobalt/kernel/clock.h
> +++ b/include/cobalt/kernel/clock.h
> @@ -54,7 +54,7 @@ struct xnclock {
>   		xnticks_t (*read_raw)(struct xnclock *clock);
>   		xnticks_t (*read_monotonic)(struct xnclock *clock);
>   		int (*set_time)(struct xnclock *clock,
> -				const struct timespec *ts);
> +				const struct timespec64 *ts);
>   		xnsticks_t (*ns_to_ticks)(struct xnclock *clock,
>   					  xnsticks_t ns);
>   		xnsticks_t (*ticks_to_ns)(struct xnclock *clock,
> @@ -211,7 +211,7 @@ static inline xnticks_t xnclock_read_monotonic(struct xnclock *clock)
>   }
>
>   static inline int xnclock_set_time(struct xnclock *clock,
> -				   const struct timespec *ts)
> +				   const struct timespec64 *ts)
>   {
>   	if (likely(clock == &nkclock))
>   		return -EINVAL;
> @@ -264,7 +264,7 @@ static inline xnticks_t xnclock_read_monotonic(struct xnclock *clock)
>   }
>
>   static inline int xnclock_set_time(struct xnclock *clock,
> -				   const struct timespec *ts)
> +				   const struct timespec64 *ts)
>   {
>   	/*
>   	 * There is no way to change the core clock's idea of time.
> diff --git a/include/cobalt/kernel/compat.h b/include/cobalt/kernel/compat.h
> index 313b6251b..c57ef6532 100644
> --- a/include/cobalt/kernel/compat.h
> +++ b/include/cobalt/kernel/compat.h
> @@ -86,11 +86,11 @@ struct compat_rtdm_mmap_request {
>   	int flags;
>   };
>
> -int sys32_get_timespec(struct timespec *ts,
> +int sys32_get_timespec(struct timespec64 *ts,
>   		       const struct compat_timespec __user *cts);
>
>   int sys32_put_timespec(struct compat_timespec __user *cts,
> -		       const struct timespec *ts);
> +		       const struct timespec64 *ts);
>
>   int sys32_get_itimerspec(struct itimerspec *its,
>   			 const struct compat_itimerspec __user *cits);
> diff --git a/include/cobalt/kernel/dovetail/pipeline/clock.h b/include/cobalt/kernel/dovetail/pipeline/clock.h
> index 933e100ba..19e3d8986 100644
> --- a/include/cobalt/kernel/dovetail/pipeline/clock.h
> +++ b/include/cobalt/kernel/dovetail/pipeline/clock.h
> @@ -8,7 +8,7 @@
>   #include <cobalt/uapi/kernel/types.h>
>   #include <cobalt/kernel/assert.h>
>
> -struct timespec;
> +struct timespec64;
>
>   static inline u64 pipeline_read_cycle_counter(void)
>   {
> @@ -49,7 +49,7 @@ static inline const char *pipeline_clock_name(void)
>   	return "?";
>   }
>
> -static inline int pipeline_get_host_time(struct timespec *tp)
> +static inline int pipeline_get_host_time(struct timespec64 *tp)
>   {
>   	/* Convert ktime_get_real_fast_ns() to timespec. */
>   	TODO();
> diff --git a/include/cobalt/kernel/ipipe/pipeline/clock.h b/include/cobalt/kernel/ipipe/pipeline/clock.h
> index fa7ac2a5e..d35aea17b 100644
> --- a/include/cobalt/kernel/ipipe/pipeline/clock.h
> +++ b/include/cobalt/kernel/ipipe/pipeline/clock.h
> @@ -7,7 +7,7 @@
>
>   #include <linux/ipipe_tickdev.h>
>
> -struct timespec;
> +struct timespec64;
>
>   static inline u64 pipeline_read_cycle_counter(void)
>   {
> @@ -31,7 +31,7 @@ static inline const char *pipeline_clock_name(void)
>   	return ipipe_clock_name();
>   }
>
> -int pipeline_get_host_time(struct timespec *tp);
> +int pipeline_get_host_time(struct timespec64 *tp);
>
>   void pipeline_update_clock_freq(unsigned long long freq);
>
> diff --git a/include/cobalt/kernel/rtdm/fd.h b/include/cobalt/kernel/rtdm/fd.h
> index 289065082..37a09c43e 100644
> --- a/include/cobalt/kernel/rtdm/fd.h
> +++ b/include/cobalt/kernel/rtdm/fd.h
> @@ -380,7 +380,7 @@ int __rtdm_fd_recvmmsg(int ufd, void __user *u_msgvec, unsigned int vlen,
>   		       unsigned int flags, void __user *u_timeout,
>   		       int (*get_mmsg)(struct mmsghdr *mmsg, void __user *u_mmsg),
>   		       int (*put_mmsg)(void __user **u_mmsg_p, const struct mmsghdr *mmsg),
> -		       int (*get_timespec)(struct timespec *ts, const void __user *u_ts));
> +		       int (*get_timespec)(struct timespec64 *ts, const void __user *u_ts));
>
>   ssize_t rtdm_fd_sendmsg(int ufd, const struct user_msghdr *msg,
>   			int flags);
> diff --git a/include/cobalt/uapi/kernel/types.h b/include/cobalt/uapi/kernel/types.h
> index ee5bbadca..8ce9b03df 100644
> --- a/include/cobalt/uapi/kernel/types.h
> +++ b/include/cobalt/uapi/kernel/types.h
> @@ -57,4 +57,14 @@ static inline xnhandle_t xnhandle_get_id(xnhandle_t handle)
>   	return handle & ~XN_HANDLE_TRANSIENT_MASK;
>   }
>
> +/*
> + * Our representation of time at the kernel<->user interface boundary
> + * at the moment, until we have fully transitioned to a y2038-safe
> + * implementation in libcobalt.
> + */
> +struct __user_old_timespec {
> +	long  tv_sec;
> +	long  tv_nsec;
> +};

why not use old_timespec32, which is timespec32 representation defined 
in include/linux/time32?

> +
>   #endif /* !_COBALT_UAPI_KERNEL_TYPES_H */
> diff --git a/include/cobalt/uapi/sched.h b/include/cobalt/uapi/sched.h
> index b672095c3..14095870f 100644
> --- a/include/cobalt/uapi/sched.h
> +++ b/include/cobalt/uapi/sched.h
> @@ -18,6 +18,8 @@
>   #ifndef _COBALT_UAPI_SCHED_H
>   #define _COBALT_UAPI_SCHED_H
>
> +#include <cobalt/uapi/kernel/types.h>
> +
>   #define SCHED_COBALT		42
>   #define SCHED_WEAK		43
>
> @@ -31,15 +33,15 @@
>
>   struct __sched_ss_param {
>   	int __sched_low_priority;
> -	struct timespec __sched_repl_period;
> -	struct timespec __sched_init_budget;
> +	struct __user_old_timespec __sched_repl_period;
> +	struct __user_old_timespec __sched_init_budget;
>   	int __sched_max_repl;
>   };
>
>   #define sched_rr_quantum	sched_u.rr.__sched_rr_quantum
>
>   struct __sched_rr_param {
> -	struct timespec __sched_rr_quantum;
> +	struct __user_old_timespec __sched_rr_quantum;
>   };
>
>   #ifndef SCHED_TP
> @@ -52,8 +54,8 @@ struct __sched_tp_param {
>   };
>
>   struct sched_tp_window {
> -	struct timespec offset;
> -	struct timespec duration;
> +	struct __user_old_timespec offset;
> +	struct __user_old_timespec duration;
>   	int ptid;
>   };
>
> diff --git a/kernel/cobalt/include/asm-generic/xenomai/syscall.h b/kernel/cobalt/include/asm-generic/xenomai/syscall.h
> index 0d50d4107..05a7d2868 100644
> --- a/kernel/cobalt/include/asm-generic/xenomai/syscall.h
> +++ b/kernel/cobalt/include/asm-generic/xenomai/syscall.h
> @@ -26,6 +26,7 @@
>   #include <asm/xenomai/wrappers.h>
>   #include <asm/xenomai/machine.h>
>   #include <cobalt/uapi/asm-generic/syscall.h>
> +#include <cobalt/uapi/kernel/types.h>
>
>   #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
>   #define access_rok(addr, size)	access_ok((addr), (size))
> @@ -81,6 +82,63 @@ static inline int cobalt_strncpy_from_user(char *dst, const char __user *src,
>   	return __xn_strncpy_from_user(dst, src, count);
>   }
>
> +#if __BITS_PER_LONG == 64
> +
> +/*
> + * NOTE: those copy helpers won't work in compat mode: use
> + * sys32_get_timespec(), sys32_put_timespec() instead.
> + */
> +
> +static inline int cobalt_get_u_timespec(struct timespec64 *dst,
> +			const struct __user_old_timespec __user *src)
> +{
> +	return cobalt_copy_from_user(dst, src, sizeof(*dst));
> +}
> +
> +static inline int cobalt_put_u_timespec(
> +	struct __user_old_timespec __user *dst,
> +	const struct timespec64 *src)
> +{
> +	return cobalt_copy_to_user(dst, src, sizeof(*dst));
> +}
> +
> +#else /* __BITS_PER_LONG == 32 */
> +
> +static inline int cobalt_get_u_timespec(struct timespec64 *dst,
> +			const struct __user_old_timespec __user *src)
> +{
> +	struct __user_old_timespec u_ts;
> +	int ret;
> +
> +	ret = cobalt_copy_from_user(&u_ts, src, sizeof(u_ts));
> +	if (ret)
> +		return ret;
> +
> +	dst->tv_sec = u_ts.tv_sec;
> +	dst->tv_nsec = u_ts.tv_nsec;
> +
> +	return 0;
> +}
> +
> +static inline int cobalt_put_u_timespec(
> +	struct __user_old_timespec __user *dst,
> +	const struct timespec64 *src)
> +{
> +	struct __user_old_timespec u_ts;
> +	int ret;
> +
> +	u_ts.tv_sec = src->tv_sec;
> +	u_ts.tv_nsec = src->tv_nsec;
> +
> +	ret = cobalt_copy_to_user(dst, &u_ts, sizeof(*dst));
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +#endif
> +
>   /* 32bit syscall emulation */
>   #define __COBALT_COMPAT_BIT	0x1
>   /* 32bit syscall emulation - extended form */
> diff --git a/kernel/cobalt/ipipe/clock.c b/kernel/cobalt/ipipe/clock.c
> index 606c6bf8c..d40b0ac89 100644
> --- a/kernel/cobalt/ipipe/clock.c
> +++ b/kernel/cobalt/ipipe/clock.c
> @@ -67,7 +67,7 @@ EXPORT_SYMBOL_GPL(xnclock_core_ticks_to_ns);
>   EXPORT_SYMBOL_GPL(xnclock_core_ticks_to_ns_rounded);
>   EXPORT_SYMBOL_GPL(xnclock_core_ns_to_ticks);
>
> -int pipeline_get_host_time(struct timespec *tp)
> +int pipeline_get_host_time(struct timespec64 *tp)
>   {
>   #ifdef CONFIG_IPIPE_HAVE_HOSTRT
>   	struct xnvdso_hostrt_data *hostrt_data;
> diff --git a/kernel/cobalt/posix/clock.c b/kernel/cobalt/posix/clock.c
> index e957dd956..4a3365d2a 100644
> --- a/kernel/cobalt/posix/clock.c
> +++ b/kernel/cobalt/posix/clock.c
> @@ -51,7 +51,7 @@ DECLARE_BITMAP(cobalt_clock_extids, COBALT_MAX_EXTCLOCKS);
>   	__val;							\
>   })
>
> -int __cobalt_clock_getres(clockid_t clock_id, struct timespec *ts)
> +int __cobalt_clock_getres(clockid_t clock_id, struct timespec64 *ts)
>   {
>   	xnticks_t ns;
>   	int ret;
> @@ -75,16 +75,16 @@ int __cobalt_clock_getres(clockid_t clock_id, struct timespec *ts)
>   }
>
>   COBALT_SYSCALL(clock_getres, current,
> -	       (clockid_t clock_id, struct timespec __user *u_ts))
> +	       (clockid_t clock_id, struct __user_old_timespec __user *u_ts))
>   {
> -	struct timespec ts;
> +	struct timespec64 ts;
>   	int ret;
>
>   	ret = __cobalt_clock_getres(clock_id, &ts);
>   	if (ret)
>   		return ret;
>
> -	if (u_ts && cobalt_copy_to_user(u_ts, &ts, sizeof(ts)))
> +	if (u_ts && cobalt_put_u_timespec(u_ts, &ts))
>   		return -EFAULT;
>
>   	trace_cobalt_clock_getres(clock_id, &ts);
> @@ -92,7 +92,7 @@ COBALT_SYSCALL(clock_getres, current,
>   	return 0;
>   }
>
> -int __cobalt_clock_gettime(clockid_t clock_id, struct timespec *ts)
> +int __cobalt_clock_gettime(clockid_t clock_id, struct timespec64 *ts)
>   {
>   	xnticks_t ns;
>   	int ret;
> @@ -122,16 +122,16 @@ int __cobalt_clock_gettime(clockid_t clock_id, struct timespec *ts)
>   }
>
>   COBALT_SYSCALL(clock_gettime, current,
> -	       (clockid_t clock_id, struct timespec __user *u_ts))
> +	       (clockid_t clock_id, struct __user_old_timespec __user *u_ts))
>   {
> -	struct timespec ts;
> +	struct timespec64 ts;
>   	int ret;
>
>   	ret = __cobalt_clock_gettime(clock_id, &ts);
>   	if (ret)
>   		return ret;
>
> -	if (cobalt_copy_to_user(u_ts, &ts, sizeof(*u_ts)))
> +	if (cobalt_put_u_timespec(u_ts, &ts))
>   		return -EFAULT;
>
>   	trace_cobalt_clock_gettime(clock_id, &ts);
> @@ -139,7 +139,7 @@ COBALT_SYSCALL(clock_gettime, current,
>   	return 0;
>   }
>
> -int __cobalt_clock_settime(clockid_t clock_id, const struct timespec *ts)
> +int __cobalt_clock_settime(clockid_t clock_id, const struct timespec64 *ts)
>   {
>   	int _ret, ret = 0;
>   	xnticks_t now;
> @@ -188,11 +188,11 @@ int __cobalt_clock_adjtime(clockid_t clock_id, struct timex *tx)
>   }
>
>   COBALT_SYSCALL(clock_settime, current,
> -	       (clockid_t clock_id, const struct timespec __user *u_ts))
> +	       (clockid_t clock_id, const struct __user_old_timespec __user *u_ts))

I planned to still use timespec as the argument, tv_sec is defined as 
long, 32bit long in 32bit system, 64bit long in 64bit system, use 
timespec64 in implementation.

>   {
> -	struct timespec ts;
> +	struct timespec64 ts;
>
> -	if (cobalt_copy_from_user(&ts, u_ts, sizeof(ts)))
> +	if (cobalt_get_u_timespec(&ts, u_ts))
>   		return -EFAULT;
>
>   	return __cobalt_clock_settime(clock_id, &ts);
> @@ -215,8 +215,8 @@ COBALT_SYSCALL(clock_adjtime, current,
>   }
>
>   int __cobalt_clock_nanosleep(clockid_t clock_id, int flags,
> -			     const struct timespec *rqt,
> -			     struct timespec *rmt)
> +			     const struct timespec64 *rqt,
> +			     struct timespec64 *rmt)
>   {
>   	struct restart_block *restart;
>   	struct xnthread *cur;
> @@ -296,21 +296,21 @@ int __cobalt_clock_nanosleep(clockid_t clock_id, int flags,
>
>   COBALT_SYSCALL(clock_nanosleep, primary,
>   	       (clockid_t clock_id, int flags,
> -		const struct timespec __user *u_rqt,
> -		struct timespec __user *u_rmt))
> +		const struct __user_old_timespec __user *u_rqt,
> +		struct __user_old_timespec __user *u_rmt))
>   {
> -	struct timespec rqt, rmt, *rmtp = NULL;
> +	struct timespec64 rqt, rmt, *rmtp = NULL;
>   	int ret;
>
>   	if (u_rmt)
>   		rmtp = &rmt;
>
> -	if (cobalt_copy_from_user(&rqt, u_rqt, sizeof(rqt)))
> +	if (cobalt_get_u_timespec(&rqt, u_rqt))
>   		return -EFAULT;
>
>   	ret = __cobalt_clock_nanosleep(clock_id, flags, &rqt, rmtp);
>   	if (ret == -EINTR && flags == 0 && rmtp) {
> -		if (cobalt_copy_to_user(u_rmt, rmtp, sizeof(*u_rmt)))
> +		if (cobalt_put_u_timespec(u_rmt, rmtp))
>   			return -EFAULT;
>   	}
>
> diff --git a/kernel/cobalt/posix/clock.h b/kernel/cobalt/posix/clock.h
> index 7cb161df2..7e45fdcc6 100644
> --- a/kernel/cobalt/posix/clock.h
> +++ b/kernel/cobalt/posix/clock.h
> @@ -28,12 +28,27 @@
>
>   struct xnclock;
>
> -static inline void ns2ts(struct timespec *ts, xnticks_t nsecs)
> +static inline void ns2ts(struct timespec64 *ts, xnticks_t nsecs)
>   {
>   	ts->tv_sec = xnclock_divrem_billion(nsecs, &ts->tv_nsec);
>   }
>
> -static inline xnticks_t ts2ns(const struct timespec *ts)
> +static inline void u_ns2ts(struct __user_old_timespec *ts, xnticks_t nsecs)
> +{
> +	ts->tv_sec = xnclock_divrem_billion(nsecs, &ts->tv_nsec);
> +}
> +
> +static inline xnticks_t ts2ns(const struct timespec64 *ts)
> +{
> +	xnticks_t nsecs = ts->tv_nsec;
> +
> +	if (ts->tv_sec)
> +		nsecs += (xnticks_t)ts->tv_sec * ONE_BILLION;
> +
> +	return nsecs;
> +}
> +
> +static inline xnticks_t u_ts2ns(const struct __user_old_timespec *ts)
>   {
>   	xnticks_t nsecs = ts->tv_nsec;
>
> @@ -80,37 +95,37 @@ static inline int clock_flag(int flag, clockid_t clock_id)
>   }
>
>   int __cobalt_clock_getres(clockid_t clock_id,
> -			  struct timespec *ts);
> +			  struct timespec64 *ts);
>
>   int __cobalt_clock_gettime(clockid_t clock_id,
> -			   struct timespec *ts);
> +			   struct timespec64 *ts);
>
>   int __cobalt_clock_settime(clockid_t clock_id,
> -			   const struct timespec *ts);
> +			   const struct timespec64 *ts);
>
>   int __cobalt_clock_adjtime(clockid_t clock_id,
>   			   struct timex *tx);
>
>   int __cobalt_clock_nanosleep(clockid_t clock_id, int flags,
> -			     const struct timespec *rqt,
> -			     struct timespec *rmt);
> +			     const struct timespec64 *rqt,
> +			     struct timespec64 *rmt);
>
>   COBALT_SYSCALL_DECL(clock_getres,
> -		    (clockid_t clock_id, struct timespec __user *u_ts));
> +		    (clockid_t clock_id, struct __user_old_timespec __user *u_ts));
>
>   COBALT_SYSCALL_DECL(clock_gettime,
> -		    (clockid_t clock_id, struct timespec __user *u_ts));
> +		    (clockid_t clock_id, struct __user_old_timespec __user *u_ts));
>
>   COBALT_SYSCALL_DECL(clock_settime,
> -		    (clockid_t clock_id, const struct timespec __user *u_ts));
> +		    (clockid_t clock_id, const struct __user_old_timespec __user *u_ts));
>
>   COBALT_SYSCALL_DECL(clock_adjtime,
>   		    (clockid_t clock_id, struct timex __user *u_tx));
>
>   COBALT_SYSCALL_DECL(clock_nanosleep,
>   		    (clockid_t clock_id, int flags,
> -		     const struct timespec __user *u_rqt,
> -		     struct timespec __user *u_rmt));
> +		     const struct __user_old_timespec __user *u_rqt,
> +		     struct __user_old_timespec __user *u_rmt));
>
>   int cobalt_clock_register(struct xnclock *clock,
>   			  const cpumask_t *affinity,
> diff --git a/kernel/cobalt/posix/compat.c b/kernel/cobalt/posix/compat.c
> index 2ffc0dbdf..185295082 100644
> --- a/kernel/cobalt/posix/compat.c
> +++ b/kernel/cobalt/posix/compat.c
> @@ -22,23 +22,41 @@
>   #include <asm/xenomai/syscall.h>
>   #include <xenomai/posix/mqueue.h>
>
> -int sys32_get_timespec(struct timespec *ts,
> -		       const struct compat_timespec __user *cts)
> +int sys32_get_timespec(struct timespec64 *ts,
> +		       const struct compat_timespec __user *u_cts)
>   {
> -	return (cts == NULL ||
> -		!access_rok(cts, sizeof(*cts)) ||
> -		__xn_get_user(ts->tv_sec, &cts->tv_sec) ||
> -		__xn_get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
> +	struct compat_timespec cts;
> +
> +	if (u_cts == NULL || !access_rok(u_cts, sizeof(*u_cts)))
> +		return -EFAULT;
> +
> +	if (__xn_get_user(cts.tv_sec, &u_cts->tv_sec) ||
> +		__xn_get_user(cts.tv_nsec, &u_cts->tv_nsec))
> +		return -EFAULT;
> +
> +	ts->tv_sec = cts.tv_sec;
> +	ts->tv_nsec = cts.tv_nsec;
> +
> +	return 0;
>   }
>   EXPORT_SYMBOL_GPL(sys32_get_timespec);
>
> -int sys32_put_timespec(struct compat_timespec __user *cts,
> -		       const struct timespec *ts)
> +int sys32_put_timespec(struct compat_timespec __user *u_cts,
> +		       const struct timespec64 *ts)
>   {
> -	return (cts == NULL ||
> -		!access_wok(cts, sizeof(*cts)) ||
> -		__xn_put_user(ts->tv_sec, &cts->tv_sec) ||
> -		__xn_put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
> +	struct compat_timespec cts;
> +
> +	if (u_cts == NULL || !access_wok(u_cts, sizeof(*u_cts)))
> +		return -EFAULT;
> +
> +	cts.tv_sec = ts->tv_sec;
> +	cts.tv_nsec = ts->tv_nsec;
> +
> +	if (__xn_put_user(cts.tv_sec, &u_cts->tv_sec) ||
> +	    __xn_put_user(cts.tv_nsec, &u_cts->tv_nsec))
> +		return -EFAULT;
> +
> +	return 0;
>   }
>   EXPORT_SYMBOL_GPL(sys32_put_timespec);
>
> @@ -478,7 +496,7 @@ int sys32_get_iovec(struct iovec *iov,
>   	const struct compat_iovec __user *p;
>   	struct compat_iovec ciov;
>   	int ret, n;
> -	
> +
>   	for (n = 0, p = u_ciov; n < ciovlen; n++, p++) {
>   		ret = cobalt_copy_from_user(&ciov, p, sizeof(ciov));
>   		if (ret)
> @@ -498,7 +516,7 @@ int sys32_put_iovec(struct compat_iovec __user *u_ciov,
>   	struct compat_iovec __user *p;
>   	struct compat_iovec ciov;
>   	int ret, n;
> -	
> +
>   	for (n = 0, p = u_ciov; n < iovlen; n++, p++) {
>   		ciov.iov_base = ptr_to_compat(iov[n].iov_base);
>   		ciov.iov_len = iov[n].iov_len;
> diff --git a/kernel/cobalt/posix/cond.c b/kernel/cobalt/posix/cond.c
> index 35a8f7176..bb18fe316 100644
> --- a/kernel/cobalt/posix/cond.c
> +++ b/kernel/cobalt/posix/cond.c
> @@ -270,25 +270,24 @@ struct us_cond_data {
>   	int err;
>   };
>
> -static inline int cond_fetch_timeout(struct timespec *ts,
> +static inline int cond_fetch_timeout(struct timespec64 *ts,
>   				     const void __user *u_ts)
>   {
> -	return u_ts == NULL ? -EFAULT :
> -		cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
> +	return u_ts == NULL ? -EFAULT :	cobalt_get_u_timespec(ts, u_ts);
>   }
>
>   int __cobalt_cond_wait_prologue(struct cobalt_cond_shadow __user *u_cnd,
>   				struct cobalt_mutex_shadow __user *u_mx,
>   				int *u_err,
>   				void __user *u_ts,
> -				int (*fetch_timeout)(struct timespec *ts,
> +				int (*fetch_timeout)(struct timespec64 *ts,
>   						     const void __user *u_ts))
>   {
>   	struct xnthread *cur = xnthread_current();
>   	struct cobalt_cond *cond;
>   	struct cobalt_mutex *mx;
>   	struct us_cond_data d;
> -	struct timespec ts;
> +	struct timespec64 ts;
>   	xnhandle_t handle;
>   	int err, perr = 0;
>   	__u32 offset;
> @@ -349,7 +348,7 @@ COBALT_SYSCALL(cond_wait_prologue, nonrestartable,
>   		struct cobalt_mutex_shadow __user *u_mx,
>   		int *u_err,
>   		unsigned int timed,
> -		struct timespec __user *u_ts))
> +		struct __user_old_timespec __user *u_ts))
>   {
>   	return __cobalt_cond_wait_prologue(u_cnd, u_mx, u_err, u_ts,
>   					   timed ? cond_fetch_timeout : NULL);
> diff --git a/kernel/cobalt/posix/cond.h b/kernel/cobalt/posix/cond.h
> index c7a9be451..7bec2a649 100644
> --- a/kernel/cobalt/posix/cond.h
> +++ b/kernel/cobalt/posix/cond.h
> @@ -43,7 +43,7 @@ int __cobalt_cond_wait_prologue(struct cobalt_cond_shadow __user *u_cnd,
>   				struct cobalt_mutex_shadow __user *u_mx,
>   				int *u_err,
>   				void __user *u_ts,
> -				int (*fetch_timeout)(struct timespec *ts,
> +				int (*fetch_timeout)(struct timespec64 *ts,
>   						     const void __user *u_ts));
>   COBALT_SYSCALL_DECL(cond_init,
>   		    (struct cobalt_cond_shadow __user *u_cnd,
> @@ -57,7 +57,7 @@ COBALT_SYSCALL_DECL(cond_wait_prologue,
>   		     struct cobalt_mutex_shadow __user *u_mx,
>   		     int *u_err,
>   		     unsigned int timed,
> -		     struct timespec __user *u_ts));
> +		     struct __user_old_timespec __user *u_ts));
>
>   COBALT_SYSCALL_DECL(cond_wait_epilogue,
>   		    (struct cobalt_cond_shadow __user *u_cnd,
> diff --git a/kernel/cobalt/posix/event.c b/kernel/cobalt/posix/event.c
> index c566a09e3..3712154f5 100644
> --- a/kernel/cobalt/posix/event.c
> +++ b/kernel/cobalt/posix/event.c
> @@ -104,7 +104,7 @@ COBALT_SYSCALL(event_init, current,
>   int __cobalt_event_wait(struct cobalt_event_shadow __user *u_event,
>   			unsigned int bits,
>   			unsigned int __user *u_bits_r,
> -			int mode, const struct timespec *ts)
> +			int mode, const struct timespec64 *ts)
>   {
>   	unsigned int rbits = 0, testval;
>   	xnticks_t timeout = XN_INFINITE;
> @@ -193,14 +193,14 @@ COBALT_SYSCALL(event_wait, primary,
>   	       (struct cobalt_event_shadow __user *u_event,
>   		unsigned int bits,
>   		unsigned int __user *u_bits_r,
> -		int mode, const struct timespec __user *u_ts))
> +		int mode, const struct __user_old_timespec __user *u_ts))
>   {
> -	struct timespec ts, *tsp = NULL;
> +	struct timespec64 ts, *tsp = NULL;
>   	int ret;
>
>   	if (u_ts) {
>   		tsp = &ts;
> -		ret = cobalt_copy_from_user(&ts, u_ts, sizeof(ts));
> +		ret = cobalt_get_u_timespec(&ts, u_ts);
>   		if (ret)
>   			return ret;
>   	}
> diff --git a/kernel/cobalt/posix/event.h b/kernel/cobalt/posix/event.h
> index 28d4516ac..ef592f72c 100644
> --- a/kernel/cobalt/posix/event.h
> +++ b/kernel/cobalt/posix/event.h
> @@ -39,7 +39,7 @@ struct cobalt_event {
>   int __cobalt_event_wait(struct cobalt_event_shadow __user *u_event,
>   			unsigned int bits,
>   			unsigned int __user *u_bits_r,
> -			int mode, const struct timespec *ts);
> +			int mode, const struct timespec64 *ts);
>
>   COBALT_SYSCALL_DECL(event_init,
>   		    (struct cobalt_event_shadow __user *u_evtsh,
> @@ -51,7 +51,7 @@ COBALT_SYSCALL_DECL(event_wait,
>   		     unsigned int bits,
>   		     unsigned int __user *u_bits_r,
>   		     int mode,
> -		     const struct timespec __user *u_ts));
> +		     const struct __user_old_timespec __user *u_ts));
>
>   COBALT_SYSCALL_DECL(event_sync,
>   		    (struct cobalt_event_shadow __user *u_evtsh));
> diff --git a/kernel/cobalt/posix/io.c b/kernel/cobalt/posix/io.c
> index e9908feeb..97a1f6afc 100644
> --- a/kernel/cobalt/posix/io.c
> +++ b/kernel/cobalt/posix/io.c
> @@ -93,10 +93,10 @@ COBALT_SYSCALL(recvmsg, handover,
>   	return cobalt_copy_to_user(umsg, &m, sizeof(*umsg)) ?: ret;
>   }
>
> -static int get_timespec(struct timespec *ts,
> +static int get_timespec(struct timespec64 *ts,
>   			const void __user *u_ts)
>   {
> -	return cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
> +	return cobalt_get_u_timespec(ts, u_ts);
>   }
>
>   static int get_mmsg(struct mmsghdr *mmsg, void __user *u_mmsg)
> @@ -114,7 +114,7 @@ static int put_mmsg(void __user **u_mmsg_p, const struct mmsghdr *mmsg)
>
>   COBALT_SYSCALL(recvmmsg, primary,
>   	       (int fd, struct mmsghdr __user *u_msgvec, unsigned int vlen,
> -		unsigned int flags, struct timespec *u_timeout))
> +		unsigned int flags, struct __user_old_timespec __user *u_timeout))
>   {
>   	return __rtdm_fd_recvmmsg(fd, u_msgvec, vlen, flags, u_timeout,
>   				  get_mmsg, put_mmsg, get_timespec);
> diff --git a/kernel/cobalt/posix/io.h b/kernel/cobalt/posix/io.h
> index 82187cc7b..e4f7d4d51 100644
> --- a/kernel/cobalt/posix/io.h
> +++ b/kernel/cobalt/posix/io.h
> @@ -53,7 +53,7 @@ COBALT_SYSCALL_DECL(recvmsg,
>
>   COBALT_SYSCALL_DECL(recvmmsg,
>   		    (int fd, struct mmsghdr __user *u_msgvec, unsigned int vlen,
> -		     unsigned int flags, struct timespec *u_timeout));
> +		     unsigned int flags, struct __user_old_timespec __user *u_timeout));
>
>   COBALT_SYSCALL_DECL(sendmsg,
>   		    (int fd, struct user_msghdr __user *umsg, int flags));
> diff --git a/kernel/cobalt/posix/monitor.c b/kernel/cobalt/posix/monitor.c
> index 5237545be..b907e0050 100644
> --- a/kernel/cobalt/posix/monitor.c
> +++ b/kernel/cobalt/posix/monitor.c
> @@ -203,7 +203,7 @@ drain:
>   }
>
>   int __cobalt_monitor_wait(struct cobalt_monitor_shadow __user *u_mon,
> -			  int event, const struct timespec *ts,
> +			  int event, const struct timespec64 *ts,
>   			  int __user *u_ret)
>   {
>   	struct cobalt_thread *curr = cobalt_current_thread();
> @@ -291,15 +291,15 @@ out:
>
>   COBALT_SYSCALL(monitor_wait, nonrestartable,
>   	       (struct cobalt_monitor_shadow __user *u_mon,
> -	       int event, const struct timespec __user *u_ts,
> +	       int event, const struct __user_old_timespec __user *u_ts,
>   	       int __user *u_ret))
>   {
> -	struct timespec ts, *tsp = NULL;
> +	struct timespec64 ts, *tsp = NULL;
>   	int ret;
>
>   	if (u_ts) {
>   		tsp = &ts;
> -		ret = cobalt_copy_from_user(&ts, u_ts, sizeof(ts));
> +		ret = cobalt_get_u_timespec(&ts, u_ts);
>   		if (ret)
>   			return ret;
>   	}
> diff --git a/kernel/cobalt/posix/monitor.h b/kernel/cobalt/posix/monitor.h
> index 8b321aaec..d4a4aa24e 100644
> --- a/kernel/cobalt/posix/monitor.h
> +++ b/kernel/cobalt/posix/monitor.h
> @@ -39,7 +39,7 @@ struct cobalt_monitor {
>   };
>
>   int __cobalt_monitor_wait(struct cobalt_monitor_shadow __user *u_mon,
> -			  int event, const struct timespec *ts,
> +			  int event, const struct timespec64 *ts,
>   			  int __user *u_ret);
>
>   COBALT_SYSCALL_DECL(monitor_init,
> @@ -58,7 +58,7 @@ COBALT_SYSCALL_DECL(monitor_exit,
>
>   COBALT_SYSCALL_DECL(monitor_wait,
>   		    (struct cobalt_monitor_shadow __user *u_monsh,
> -		     int event, const struct timespec __user *u_ts,
> +		     int event, const struct __user_old_timespec __user *u_ts,
>   		     int __user *u_ret));
>
>   COBALT_SYSCALL_DECL(monitor_destroy,
> diff --git a/kernel/cobalt/posix/mqueue.c b/kernel/cobalt/posix/mqueue.c
> index cd1cf3ce8..b2cf92e43 100644
> --- a/kernel/cobalt/posix/mqueue.c
> +++ b/kernel/cobalt/posix/mqueue.c
> @@ -468,13 +468,13 @@ mq_tryrcv(struct cobalt_mqd *mqd, size_t len)
>   static struct cobalt_msg *
>   mq_timedsend_inner(struct cobalt_mqd *mqd,
>   		   size_t len, const void __user *u_ts,
> -		   int (*fetch_timeout)(struct timespec *ts,
> +		   int (*fetch_timeout)(struct timespec64 *ts,
>   					const void __user *u_ts))
>   {
>   	struct cobalt_mqwait_context mwc;
>   	struct cobalt_msg *msg;
>   	struct cobalt_mq *mq;
> -	struct timespec ts;
> +	struct timespec64 ts;
>   	xntmode_t tmode;
>   	xnticks_t to;
>   	spl_t s;
> @@ -597,13 +597,13 @@ static struct cobalt_msg *
>   mq_timedrcv_inner(struct cobalt_mqd *mqd,
>   		  size_t len,
>   		  const void __user *u_ts,
> -		  int (*fetch_timeout)(struct timespec *ts,
> +		  int (*fetch_timeout)(struct timespec64 *ts,
>   				       const void __user *u_ts))
>   {
>   	struct cobalt_mqwait_context mwc;
>   	struct cobalt_msg *msg;
>   	struct cobalt_mq *mq;
> -	struct timespec ts;
> +	struct timespec64 ts;
>   	xntmode_t tmode;
>   	xnticks_t to;
>   	spl_t s;
> @@ -880,7 +880,7 @@ COBALT_SYSCALL(mq_getattr, current,
>   	return cobalt_copy_to_user(u_attr, &attr, sizeof(attr));
>   }
>
> -static inline int mq_fetch_timeout(struct timespec *ts,
> +static inline int mq_fetch_timeout(struct timespec64 *ts,
>   				   const void __user *u_ts)
>   {
>   	return u_ts == NULL ? -EFAULT :
> @@ -889,7 +889,7 @@ static inline int mq_fetch_timeout(struct timespec *ts,
>
>   int __cobalt_mq_timedsend(mqd_t uqd, const void __user *u_buf, size_t len,
>   			  unsigned int prio, const void __user *u_ts,
> -			  int (*fetch_timeout)(struct timespec *ts,
> +			  int (*fetch_timeout)(struct timespec64 *ts,
>   					       const void __user *u_ts))
>   {
>   	struct cobalt_msg *msg;
> @@ -933,7 +933,7 @@ out:
>
>   COBALT_SYSCALL(mq_timedsend, primary,
>   	       (mqd_t uqd, const void __user *u_buf, size_t len,
> -		unsigned int prio, const struct timespec __user *u_ts))
> +		unsigned int prio, const struct __user_old_timespec __user *u_ts))
>   {
>   	return __cobalt_mq_timedsend(uqd, u_buf, len, prio,
>   				     u_ts, u_ts ? mq_fetch_timeout : NULL);
> @@ -943,7 +943,7 @@ int __cobalt_mq_timedreceive(mqd_t uqd, void __user *u_buf,
>   			     ssize_t *lenp,
>   			     unsigned int __user *u_prio,
>   			     const void __user *u_ts,
> -			     int (*fetch_timeout)(struct timespec *ts,
> +			     int (*fetch_timeout)(struct timespec64 *ts,
>   						  const void __user *u_ts))
>   {
>   	struct cobalt_mqd *mqd;
> @@ -994,7 +994,7 @@ COBALT_SYSCALL(mq_timedreceive, primary,
>   	       (mqd_t uqd, void __user *u_buf,
>   		ssize_t __user *u_len,
>   		unsigned int __user *u_prio,
> -		const struct timespec __user *u_ts))
> +		const struct __user_old_timespec __user *u_ts))
>   {
>   	ssize_t len;
>   	int ret;
> diff --git a/kernel/cobalt/posix/mqueue.h b/kernel/cobalt/posix/mqueue.h
> index acae2a424..d33220227 100644
> --- a/kernel/cobalt/posix/mqueue.h
> +++ b/kernel/cobalt/posix/mqueue.h
> @@ -37,14 +37,14 @@ int __cobalt_mq_getattr(mqd_t uqd, struct mq_attr *attr);
>
>   int __cobalt_mq_timedsend(mqd_t uqd, const void __user *u_buf, size_t len,
>   			  unsigned int prio, const void __user *u_ts,
> -			  int (*fetch_timeout)(struct timespec *ts,
> +			  int (*fetch_timeout)(struct timespec64 *ts,
>   					       const void __user *u_ts));
>
>   int __cobalt_mq_timedreceive(mqd_t uqd, void __user *u_buf,
>   			     ssize_t *lenp,
>   			     unsigned int __user *u_prio,
>   			     const void __user *u_ts,
> -			     int (*fetch_timeout)(struct timespec *ts,
> +			     int (*fetch_timeout)(struct timespec64 *ts,
>   						  const void __user *u_ts));
>
>   int __cobalt_mq_notify(mqd_t fd, const struct sigevent *evp);
> @@ -61,12 +61,12 @@ COBALT_SYSCALL_DECL(mq_getattr, (mqd_t uqd, struct mq_attr __user *u_attr));
>
>   COBALT_SYSCALL_DECL(mq_timedsend,
>   		    (mqd_t uqd, const void __user *u_buf, size_t len,
> -		     unsigned int prio, const struct timespec __user *u_ts));
> +		     unsigned int prio, const struct __user_old_timespec __user *u_ts));
>
>   COBALT_SYSCALL_DECL(mq_timedreceive,
>   		    (mqd_t uqd, void __user *u_buf, ssize_t __user *u_len,
>   		     unsigned int __user *u_prio,
> -		     const struct timespec __user *u_ts));
> +		     const struct __user_old_timespec __user *u_ts));
>
>   COBALT_SYSCALL_DECL(mq_notify,
>   		    (mqd_t fd, const struct sigevent *__user evp));
> diff --git a/kernel/cobalt/posix/mutex.c b/kernel/cobalt/posix/mutex.c
> index 79260b544..d43a747b3 100644
> --- a/kernel/cobalt/posix/mutex.c
> +++ b/kernel/cobalt/posix/mutex.c
> @@ -71,7 +71,7 @@ static int cobalt_mutex_init_inner(struct cobalt_mutex_shadow *shadow,
>   /* must be called with nklock locked, interrupts off. */
>   int __cobalt_mutex_acquire_unchecked(struct xnthread *cur,
>   				     struct cobalt_mutex *mutex,
> -				     const struct timespec *ts)
> +				     const struct timespec64 *ts)
>   {
>   	int ret;
>
> @@ -134,11 +134,11 @@ int cobalt_mutex_release(struct xnthread *curr,
>
>   int __cobalt_mutex_timedlock_break(struct cobalt_mutex_shadow __user *u_mx,
>   				   const void __user *u_ts,
> -				   int (*fetch_timeout)(struct timespec *ts,
> +				   int (*fetch_timeout)(struct timespec64 *ts,
>   							const void __user *u_ts))
>   {
>   	struct xnthread *curr = xnthread_current();
> -	struct timespec ts, *tsp = NULL;
> +	struct timespec64 ts, *tsp = NULL;
>   	struct cobalt_mutex *mutex;
>   	xnhandle_t handle;
>   	spl_t s;
> @@ -346,7 +346,7 @@ COBALT_SYSCALL(mutex_lock, primary,
>   	return __cobalt_mutex_timedlock_break(u_mx, NULL, NULL);
>   }
>
> -static inline int mutex_fetch_timeout(struct timespec *ts,
> +static inline int mutex_fetch_timeout(struct timespec64 *ts,
>   				      const void __user *u_ts)
>   {
>   	return u_ts == NULL ? -EFAULT :
> @@ -355,7 +355,7 @@ static inline int mutex_fetch_timeout(struct timespec *ts,
>
>   COBALT_SYSCALL(mutex_timedlock, primary,
>   	       (struct cobalt_mutex_shadow __user *u_mx,
> -		const struct timespec __user *u_ts))
> +		const struct __user_old_timespec __user *u_ts))
>   {
>   	return __cobalt_mutex_timedlock_break(u_mx, u_ts, mutex_fetch_timeout);
>   }
> diff --git a/kernel/cobalt/posix/mutex.h b/kernel/cobalt/posix/mutex.h
> index ac1c50291..d76f2a9ea 100644
> --- a/kernel/cobalt/posix/mutex.h
> +++ b/kernel/cobalt/posix/mutex.h
> @@ -37,12 +37,12 @@ struct cobalt_mutex {
>
>   int __cobalt_mutex_timedlock_break(struct cobalt_mutex_shadow __user *u_mx,
>   				   const void __user *u_ts,
> -				   int (*fetch_timeout)(struct timespec *ts,
> +				   int (*fetch_timeout)(struct timespec64 *ts,
>   							const void __user *u_ts));
>
>   int __cobalt_mutex_acquire_unchecked(struct xnthread *cur,
>   				     struct cobalt_mutex *mutex,
> -				     const struct timespec *ts);
> +				     const struct timespec64 *ts);
>
>   COBALT_SYSCALL_DECL(mutex_check_init,
>   		    (struct cobalt_mutex_shadow __user *u_mx));
> @@ -62,7 +62,7 @@ COBALT_SYSCALL_DECL(mutex_lock,
>
>   COBALT_SYSCALL_DECL(mutex_timedlock,
>   		    (struct cobalt_mutex_shadow __user *u_mx,
> -		     const struct timespec __user *u_ts));
> +		     const struct __user_old_timespec __user *u_ts));
>
>   COBALT_SYSCALL_DECL(mutex_unlock,
>   		    (struct cobalt_mutex_shadow __user *u_mx));
> diff --git a/kernel/cobalt/posix/sched.c b/kernel/cobalt/posix/sched.c
> index 798a172d7..4fd9c2b46 100644
> --- a/kernel/cobalt/posix/sched.c
> +++ b/kernel/cobalt/posix/sched.c
> @@ -73,7 +73,7 @@ cobalt_sched_policy_param(union xnsched_policy_param *param,
>   		break;
>   	case SCHED_RR:
>   		/* if unspecified, use current one. */
> -		tslice = ts2ns(&param_ex->sched_rr_quantum);
> +		tslice = u_ts2ns(&param_ex->sched_rr_quantum);
>   		if (tslice == XN_INFINITE && tslice_r)
>   			tslice = *tslice_r;
>   		/* fallthrough */
> @@ -92,8 +92,8 @@ cobalt_sched_policy_param(union xnsched_policy_param *param,
>   		param->pss.normal_prio = param_ex->sched_priority;
>   		param->pss.low_prio = param_ex->sched_ss_low_priority;
>   		param->pss.current_prio = param->pss.normal_prio;
> -		param->pss.init_budget = ts2ns(&param_ex->sched_ss_init_budget);
> -		param->pss.repl_period = ts2ns(&param_ex->sched_ss_repl_period);
> +		param->pss.init_budget = u_ts2ns(&param_ex->sched_ss_init_budget);
> +		param->pss.repl_period = u_ts2ns(&param_ex->sched_ss_repl_period);
>   		param->pss.max_repl = param_ex->sched_ss_max_repl;
>   		sched_class = &xnsched_class_sporadic;
>   		break;
> @@ -280,11 +280,11 @@ int set_tp_config(int cpu, union sched_config *config, size_t len)
>   		 * be defined using windows assigned to the pseudo
>   		 * partition #-1.
>   		 */
> -		offset = ts2ns(&p->offset);
> +		offset = u_ts2ns(&p->offset);
>   		if (offset != next_offset)
>   			goto cleanup_and_fail;
>
> -		duration = ts2ns(&p->duration);
> +		duration = u_ts2ns(&p->duration);
>   		if (duration <= 0)
>   			goto cleanup_and_fail;
>
> @@ -357,11 +357,11 @@ ssize_t get_tp_config(int cpu, void __user *u_config, size_t len,
>   	config->tp.nr_windows = gps->pwin_nr;
>   	for (n = 0, pp = p = config->tp.windows, pw = w = gps->pwins;
>   	     n < gps->pwin_nr; pp = p, p++, pw = w, w++, n++) {
> -		ns2ts(&p->offset, w->w_offset);
> -		ns2ts(&pp->duration, w->w_offset - pw->w_offset);
> +		u_ns2ts(&p->offset, w->w_offset);
> +		u_ns2ts(&pp->duration, w->w_offset - pw->w_offset);
>   		p->ptid = w->w_part;
>   	}
> -	ns2ts(&pp->duration, gps->tf_duration - pw->w_offset);
> +	u_ns2ts(&pp->duration, gps->tf_duration - pw->w_offset);
>   	ret = put_config(SCHED_TP, u_config, len, config, elen);
>   	xnfree(config);
>   out:
> diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
> index 05a861dfe..467a9b7dd 100644
> --- a/kernel/cobalt/posix/sem.c
> +++ b/kernel/cobalt/posix/sem.c
> @@ -267,7 +267,7 @@ out:
>   	return ret;
>   }
>
> -static inline int sem_fetch_timeout(struct timespec *ts,
> +static inline int sem_fetch_timeout(struct timespec64 *ts,
>   				    const void __user *u_ts)
>   {
>   	return u_ts == NULL ? -EFAULT :
> @@ -276,10 +276,10 @@ static inline int sem_fetch_timeout(struct timespec *ts,
>
>   int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
>   			   const void __user *u_ts,
> -			   int (*fetch_timeout)(struct timespec *ts,
> +			   int (*fetch_timeout)(struct timespec64 *ts,
>   						const void __user *u_ts))
>   {
> -	struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
> +	struct timespec64 ts = { .tv_sec = 0, .tv_nsec = 0 };
>   	int pull_ts = 1, ret, info;
>   	struct cobalt_sem *sem;
>   	xnhandle_t handle;
> @@ -434,7 +434,7 @@ COBALT_SYSCALL(sem_wait, primary,
>
>   COBALT_SYSCALL(sem_timedwait, primary,
>   	       (struct cobalt_sem_shadow __user *u_sem,
> -		struct timespec __user *u_ts))
> +		struct __user_old_timespec __user *u_ts))
>   {
>   	return __cobalt_sem_timedwait(u_sem, u_ts, sem_fetch_timeout);
>   }
> diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h
> index 17238078e..d17299495 100644
> --- a/kernel/cobalt/posix/sem.h
> +++ b/kernel/cobalt/posix/sem.h
> @@ -65,7 +65,7 @@ __cobalt_sem_open(struct cobalt_sem_shadow __user *usm,
>
>   int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
>   			   const void __user *u_ts,
> -			   int (*fetch_timeout)(struct timespec *ts,
> +			   int (*fetch_timeout)(struct timespec64 *ts,
>   						const void __user *u_ts));
>
>   int __cobalt_sem_destroy(xnhandle_t handle);
> @@ -91,7 +91,7 @@ COBALT_SYSCALL_DECL(sem_wait,
>
>   COBALT_SYSCALL_DECL(sem_timedwait,
>   		    (struct cobalt_sem_shadow __user *u_sem,
> -		     struct timespec __user *u_ts));
> +		     struct __user_old_timespec __user *u_ts));
>
>   COBALT_SYSCALL_DECL(sem_trywait,
>   		    (struct cobalt_sem_shadow __user *u_sem));
> diff --git a/kernel/cobalt/posix/signal.c b/kernel/cobalt/posix/signal.c
> index 862a644c0..0b43b5fcf 100644
> --- a/kernel/cobalt/posix/signal.c
> +++ b/kernel/cobalt/posix/signal.c
> @@ -407,7 +407,7 @@ COBALT_SYSCALL(sigwait, primary,
>   }
>
>   int __cobalt_sigtimedwait(sigset_t *set,
> -			  const struct timespec *timeout,
> +			  const struct timespec64 *timeout,
>   			  void __user *u_si,
>   			  bool compat)
>   {
> @@ -426,9 +426,9 @@ int __cobalt_sigtimedwait(sigset_t *set,
>   COBALT_SYSCALL(sigtimedwait, nonrestartable,
>   	       (const sigset_t __user *u_set,
>   		struct siginfo __user *u_si,
> -		const struct timespec __user *u_timeout))
> +		const struct __user_old_timespec __user *u_timeout))
>   {
> -	struct timespec timeout;
> +	struct timespec64 timeout;
>   	sigset_t set;
>
>   	if (cobalt_copy_from_user(&set, u_set, sizeof(set)))
> diff --git a/kernel/cobalt/posix/signal.h b/kernel/cobalt/posix/signal.h
> index 7a0b4b22b..fc26ad065 100644
> --- a/kernel/cobalt/posix/signal.h
> +++ b/kernel/cobalt/posix/signal.h
> @@ -59,7 +59,7 @@ void cobalt_copy_siginfo(int code,
>   int __cobalt_sigwait(sigset_t *set);
>
>   int __cobalt_sigtimedwait(sigset_t *set,
> -			  const struct timespec *timeout,
> +			  const struct timespec64 *timeout,
>   			  void __user *u_si,
>   			  bool compat);
>
> @@ -94,7 +94,7 @@ COBALT_SYSCALL_DECL(sigwait,
>   COBALT_SYSCALL_DECL(sigtimedwait,
>   		    (const sigset_t __user *u_set,
>   		     struct siginfo __user *u_si,
> -		     const struct timespec __user *u_timeout));
> +		     const struct __user_old_timespec __user *u_timeout));
>
>   COBALT_SYSCALL_DECL(sigwaitinfo,
>   		    (const sigset_t __user *u_set,
> diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
> index cb02dacd3..ae25a6e74 100644
> --- a/kernel/cobalt/posix/syscall32.c
> +++ b/kernel/cobalt/posix/syscall32.c
> @@ -97,7 +97,7 @@ COBALT_SYSCALL32emu(thread_setschedprio, conforming,
>   	return cobalt_thread_setschedprio(pth, prio, u_winoff, u_promoted);
>   }
>
> -static inline int sys32_fetch_timeout(struct timespec *ts,
> +static inline int sys32_fetch_timeout(struct timespec64 *ts,
>   				      const void __user *u_ts)
>   {
>   	return u_ts == NULL ? -EFAULT :
> @@ -133,7 +133,7 @@ COBALT_SYSCALL32emu(clock_getres, current,
>   		    (clockid_t clock_id,
>   		     struct compat_timespec __user *u_ts))
>   {
> -	struct timespec ts;
> +	struct timespec64 ts;
>   	int ret;
>
>   	ret = __cobalt_clock_getres(clock_id, &ts);
> @@ -147,7 +147,7 @@ COBALT_SYSCALL32emu(clock_gettime, current,
>   		    (clockid_t clock_id,
>   		     struct compat_timespec __user *u_ts))
>   {
> -	struct timespec ts;
> +	struct timespec64 ts;
>   	int ret;
>
>   	ret = __cobalt_clock_gettime(clock_id, &ts);
> @@ -161,7 +161,7 @@ COBALT_SYSCALL32emu(clock_settime, current,
>   		    (clockid_t clock_id,
>   		     const struct compat_timespec __user *u_ts))
>   {
> -	struct timespec ts;
> +	struct timespec64 ts;
>   	int ret;
>
>   	ret = sys32_get_timespec(&ts, u_ts);
> @@ -193,7 +193,7 @@ COBALT_SYSCALL32emu(clock_nanosleep, nonrestartable,
>   		     const struct compat_timespec __user *u_rqt,
>   		     struct compat_timespec __user *u_rmt))
>   {
> -	struct timespec rqt, rmt, *rmtp = NULL;
> +	struct timespec64 rqt, rmt, *rmtp = NULL;
>   	int ret;
>
>   	if (u_rmt)
> @@ -289,12 +289,10 @@ COBALT_SYSCALL32emu(mq_timedreceive, primary,
>   	return ret ?: cobalt_copy_to_user(u_len, &clen, sizeof(*u_len));
>   }
>
> -static inline int mq_fetch_timeout(struct timespec *ts,
> +static inline int mq_fetch_timeout(struct timespec64 *ts,
>   				   const void __user *u_ts)
>   {
> -	return u_ts == NULL ? -EFAULT :
> -		cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
> -
> +	return u_ts == NULL ? -EFAULT : cobalt_get_u_timespec(ts, u_ts);
>   }
>
>   COBALT_SYSCALL32emu(mq_notify, primary,
> @@ -610,7 +608,7 @@ COBALT_SYSCALL32emu(sigtimedwait, nonrestartable,
>   		     struct compat_siginfo __user *u_si,
>   		     const struct compat_timespec __user *u_timeout))
>   {
> -	struct timespec timeout;
> +	struct timespec64 timeout;
>   	sigset_t set;
>   	int ret;
>
> @@ -663,7 +661,7 @@ COBALT_SYSCALL32emu(monitor_wait, nonrestartable,
>   		     int event, const struct compat_timespec __user *u_ts,
>   		     int __user *u_ret))
>   {
> -	struct timespec ts, *tsp = NULL;
> +	struct timespec64 ts, *tsp = NULL;
>   	int ret;
>
>   	if (u_ts) {
> @@ -682,7 +680,7 @@ COBALT_SYSCALL32emu(event_wait, primary,
>   		     unsigned int __user *u_bits_r,
>   		     int mode, const struct compat_timespec __user *u_ts))
>   {
> -	struct timespec ts, *tsp = NULL;
> +	struct timespec64 ts, *tsp = NULL;
>   	int ret;
>
>   	if (u_ts) {
> @@ -810,7 +808,7 @@ COBALT_SYSCALL32emu(recvmsg, handover,
>   	return sys32_put_msghdr(umsg, &m) ?: ret;
>   }
>
> -static int get_timespec32(struct timespec *ts,
> +static int get_timespec32(struct timespec64 *ts,
>   			  const void __user *u_ts)
>   {
>   	return sys32_get_timespec(ts, u_ts);
> @@ -924,7 +922,7 @@ COBALT_SYSCALL32x(mq_timedreceive, primary,
>   		  (mqd_t uqd, void __user *u_buf,
>   		   compat_ssize_t __user *u_len,
>   		   unsigned int __user *u_prio,
> -		   const struct timespec __user *u_ts))
> +		   const struct __user_old_timespec __user *u_ts))
>   {
>   	compat_ssize_t clen;
>   	ssize_t len;
> diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h
> index eb3e4bd30..9da405229 100644
> --- a/kernel/cobalt/posix/syscall32.h
> +++ b/kernel/cobalt/posix/syscall32.h
> @@ -105,7 +105,7 @@ COBALT_SYSCALL32x_DECL(mq_timedreceive,
>   		       (mqd_t uqd, void __user *u_buf,
>   			compat_ssize_t __user *u_len,
>   			unsigned int __user *u_prio,
> -			const struct timespec __user *u_ts));
> +			const struct __user_old_timespec __user *u_ts));
>
>   COBALT_SYSCALL32emu_DECL(mq_notify,
>   			 (mqd_t fd, const struct compat_sigevent *__user u_cev));
> diff --git a/kernel/cobalt/posix/thread.c b/kernel/cobalt/posix/thread.c
> index bf9c08212..cdeb66d4f 100644
> --- a/kernel/cobalt/posix/thread.c
> +++ b/kernel/cobalt/posix/thread.c
> @@ -302,7 +302,7 @@ int __cobalt_thread_getschedparam_ex(struct cobalt_thread *thread,
>
>   	if (base_class == &xnsched_class_rt) {
>   		if (xnthread_test_state(base_thread, XNRRB)) {
> -			ns2ts(&param_ex->sched_rr_quantum, base_thread->rrperiod);
> +			u_ns2ts(&param_ex->sched_rr_quantum, base_thread->rrperiod);
>   			*policy_r = SCHED_RR;
>   		}
>   		goto out;
> @@ -318,8 +318,8 @@ int __cobalt_thread_getschedparam_ex(struct cobalt_thread *thread,
>   #ifdef CONFIG_XENO_OPT_SCHED_SPORADIC
>   	if (base_class == &xnsched_class_sporadic) {
>   		param_ex->sched_ss_low_priority = base_thread->pss->param.low_prio;
> -		ns2ts(&param_ex->sched_ss_repl_period, base_thread->pss->param.repl_period);
> -		ns2ts(&param_ex->sched_ss_init_budget, base_thread->pss->param.init_budget);
> +		u_ns2ts(&param_ex->sched_ss_repl_period, base_thread->pss->param.repl_period);
> +		u_ns2ts(&param_ex->sched_ss_init_budget, base_thread->pss->param.init_budget);
>   		param_ex->sched_ss_max_repl = base_thread->pss->param.max_repl;
>   		goto out;
>   	}
> diff --git a/kernel/cobalt/rtdm/fd.c b/kernel/cobalt/rtdm/fd.c
> index 7956a8800..038247d54 100644
> --- a/kernel/cobalt/rtdm/fd.c
> +++ b/kernel/cobalt/rtdm/fd.c
> @@ -650,11 +650,11 @@ int __rtdm_fd_recvmmsg(int ufd, void __user *u_msgvec, unsigned int vlen,
>   		       unsigned int flags, void __user *u_timeout,
>   		       int (*get_mmsg)(struct mmsghdr *mmsg, void __user *u_mmsg),
>   		       int (*put_mmsg)(void __user **u_mmsg_p, const struct mmsghdr *mmsg),
> -		       int (*get_timespec)(struct timespec *ts, const void __user *u_ts))
> +		       int (*get_timespec)(struct timespec64 *ts, const void __user *u_ts))
>   {
>   	struct cobalt_recvmmsg_timer rq;
>   	xntmode_t tmode = XN_RELATIVE;
> -	struct timespec ts = { 0 };
> +	struct timespec64 ts = { 0 };
>   	int ret = 0, datagrams = 0;
>   	xnticks_t timeout = 0;
>   	struct mmsghdr mmsg;
> diff --git a/kernel/cobalt/trace/cobalt-posix.h b/kernel/cobalt/trace/cobalt-posix.h
> index aa78efbc0..3a649a671 100644
> --- a/kernel/cobalt/trace/cobalt-posix.h
> +++ b/kernel/cobalt/trace/cobalt-posix.h
> @@ -30,7 +30,7 @@
>   #include <xenomai/posix/event.h>
>
>   #define __timespec_fields(__name)				\
> -	__field(__kernel_time_t, tv_sec_##__name)		\
> +	__field(time64_t, tv_sec_##__name)			\
>   	__field(long, tv_nsec_##__name)
>
>   #define __assign_timespec(__to, __from)				\
> @@ -40,7 +40,7 @@
>   	} while (0)
>
>   #define __timespec_args(__name)					\
> -	__entry->tv_sec_##__name, __entry->tv_nsec_##__name
> +	(long long)__entry->tv_sec_##__name, __entry->tv_nsec_##__name
>
>   #ifdef CONFIG_X86_X32
>   #define __sc_x32(__name)	, { sc_cobalt_##__name + __COBALT_X32_BASE, "x32-" #__name }
> @@ -729,7 +729,7 @@ TRACE_EVENT(cobalt_psem_unlink,
>   );
>
>   DECLARE_EVENT_CLASS(cobalt_clock_timespec,
> -	TP_PROTO(clockid_t clk_id, const struct timespec *val),
> +	TP_PROTO(clockid_t clk_id, const struct timespec64 *val),
>   	TP_ARGS(clk_id, val),
>
>   	TP_STRUCT__entry(
> @@ -742,24 +742,24 @@ DECLARE_EVENT_CLASS(cobalt_clock_timespec,
>   		__assign_timespec(val, val);
>   	),
>
> -	TP_printk("clock_id=%d timeval=(%ld.%09ld)",
> +	TP_printk("clock_id=%d timeval=(%lld.%09ld)",
>   		  __entry->clk_id,
>   		  __timespec_args(val)
>   	)
>   );
>
>   DEFINE_EVENT(cobalt_clock_timespec, cobalt_clock_getres,
> -	TP_PROTO(clockid_t clk_id, const struct timespec *res),
> +	TP_PROTO(clockid_t clk_id, const struct timespec64 *res),
>   	TP_ARGS(clk_id, res)
>   );
>
>   DEFINE_EVENT(cobalt_clock_timespec, cobalt_clock_gettime,
> -	TP_PROTO(clockid_t clk_id, const struct timespec *time),
> +	TP_PROTO(clockid_t clk_id, const struct timespec64 *time),
>   	TP_ARGS(clk_id, time)
>   );
>
>   DEFINE_EVENT(cobalt_clock_timespec, cobalt_clock_settime,
> -	TP_PROTO(clockid_t clk_id, const struct timespec *time),
> +	TP_PROTO(clockid_t clk_id, const struct timespec64 *time),
>   	TP_ARGS(clk_id, time)
>   );
>
> @@ -788,7 +788,7 @@ TRACE_EVENT(cobalt_clock_adjtime,
>   		      {TIMER_ABSTIME, "TIMER_ABSTIME"})
>
>   TRACE_EVENT(cobalt_clock_nanosleep,
> -	TP_PROTO(clockid_t clk_id, int flags, const struct timespec *time),
> +	TP_PROTO(clockid_t clk_id, int flags, const struct timespec64 *time),
>   	TP_ARGS(clk_id, flags, time),
>
>   	TP_STRUCT__entry(
> @@ -803,7 +803,7 @@ TRACE_EVENT(cobalt_clock_nanosleep,
>   		__assign_timespec(time, time);
>   	),
>
> -	TP_printk("clock_id=%d flags=%#x(%s) rqt=(%ld.%09ld)",
> +	TP_printk("clock_id=%d flags=%#x(%s) rqt=(%lld.%09ld)",
>   		  __entry->clk_id,
>   		  __entry->flags, cobalt_print_timer_flags(__entry->flags),
>   		  __timespec_args(time)
> @@ -875,7 +875,7 @@ TRACE_EVENT(cobalt_cond_destroy,
>   TRACE_EVENT(cobalt_cond_timedwait,
>   	TP_PROTO(const struct cobalt_cond_shadow __user *u_cnd,
>   		 const struct cobalt_mutex_shadow __user *u_mx,
> -		 const struct timespec *timeout),
> +		 const struct timespec64 *timeout),
>   	TP_ARGS(u_cnd, u_mx, timeout),
>   	TP_STRUCT__entry(
>   		__field(const struct cobalt_cond_shadow __user *, u_cnd)
> @@ -887,7 +887,7 @@ TRACE_EVENT(cobalt_cond_timedwait,
>   		__entry->u_mx = u_mx;
>   		__assign_timespec(timeout, timeout);
>   	),
> -	TP_printk("cond=%p, mutex=%p, timeout=(%ld.%09ld)",
> +	TP_printk("cond=%p, mutex=%p, timeout=(%lld.%09ld)",
>   		  __entry->u_cnd, __entry->u_mx, __timespec_args(timeout))
>   );
>
> @@ -1001,7 +1001,7 @@ TRACE_EVENT(cobalt_mq_send,
>
>   TRACE_EVENT(cobalt_mq_timedreceive,
>   	TP_PROTO(mqd_t mqd, const void __user *u_buf, size_t len,
> -		 const struct timespec *timeout),
> +		 const struct timespec64 *timeout),
>   	TP_ARGS(mqd, u_buf, len, timeout),
>   	TP_STRUCT__entry(
>   		__field(mqd_t, mqd)
> @@ -1015,7 +1015,7 @@ TRACE_EVENT(cobalt_mq_timedreceive,
>   		__entry->len = len;
>   		__assign_timespec(timeout, timeout);
>   	),
> -	TP_printk("mqd=%d buf=%p len=%zu timeout=(%ld.%09ld)",
> +	TP_printk("mqd=%d buf=%p len=%zu timeout=(%lld.%09ld)",
>   		  __entry->mqd, __entry->u_buf, __entry->len,
>   		  __timespec_args(timeout))
>   );
> @@ -1105,7 +1105,7 @@ TRACE_EVENT(cobalt_event_init,
>   TRACE_EVENT(cobalt_event_timedwait,
>   	TP_PROTO(const struct cobalt_event_shadow __user *u_event,
>   		 unsigned long bits, int mode,
> -		 const struct timespec *timeout),
> +		 const struct timespec64 *timeout),
>   	TP_ARGS(u_event, bits, mode, timeout),
>   	TP_STRUCT__entry(
>   		__field(const struct cobalt_event_shadow __user *, u_event)
> @@ -1119,7 +1119,7 @@ TRACE_EVENT(cobalt_event_timedwait,
>   		__entry->mode = mode;
>   		__assign_timespec(timeout, timeout);
>   	),
> -	TP_printk("event=%p bits=%#lx mode=%#x(%s) timeout=(%ld.%09ld)",
> +	TP_printk("event=%p bits=%#lx mode=%#x(%s) timeout=(%lld.%09ld)",
>   		  __entry->u_event, __entry->bits, __entry->mode,
>   		  cobalt_print_evmode(__entry->mode),
>   		  __timespec_args(timeout))
>


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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-02-21  2:17   ` chensong
@ 2021-02-21 15:27     ` Philippe Gerum
  2021-02-22  1:04       ` chensong
  2021-02-22  8:21       ` florian.bezdeka
  0 siblings, 2 replies; 57+ messages in thread
From: Philippe Gerum @ 2021-02-21 15:27 UTC (permalink / raw)
  To: chensong; +Cc: xenomai


chensong via Xenomai <xenomai@xenomai.org> writes:

>> +/*
>> + * Our representation of time at the kernel<->user interface boundary
>> + * at the moment, until we have fully transitioned to a y2038-safe
>> + * implementation in libcobalt.
>> + */
>> +struct __user_old_timespec {
>> +	long  tv_sec;
>> +	long  tv_nsec;
>> +};
>
> why not use old_timespec32, which is timespec32 representation defined
> in include/linux/time32?
>

Using old_timespec32 in this context would mean that any time value
received from userland by the core should be restricted to 32bit time_t,
which is not what we want, at least for 64bit platforms:

include/vdso/time32.h:

struct old_timespec32 {
	old_time32_t	tv_sec;
	s32		tv_nsec;
};

__user_old_timespec conveys the notion that we are generically talking
about "the old timespec type which has a y2038 problem"; this is not
specifically about the legacy timespec type on 32bit machines.

Since v5.4-rc6, we do have __kernel_old_timespec though, which could
have been used instead of __user_old_timespec:

include/uapi/asm-generic/posix_types.h:

typedef long __kernel_long_t;

include/uapi/linux/time_types.h:

struct __kernel_old_timespec {
	__kernel_long_t		tv_sec;		/* seconds */
	long			tv_nsec;	/* nanoseconds */
};

However, older (non-x86) toolchains do not define __kernel_old_timespec,
so I went for adding __user_old_timespec to the Cobalt UAPI. This may be
seen as a temporary option until stricter requirements on the minimum
toolchain support for building Cobalt is decided.

>>
>>   COBALT_SYSCALL(clock_settime, current,
>> -	       (clockid_t clock_id, const struct timespec __user *u_ts))
>> +	       (clockid_t clock_id, const struct __user_old_timespec __user *u_ts))
>
> I planned to still use timespec as the argument, tv_sec is defined as
> long, 32bit long in 32bit system, 64bit long in 64bit system, use 
> timespec64 in implementation.
>

Keeping struct timespec for the argument does not seem the right thing
to do, as this type has been phased out from recent kernels, precisely
to stop spreading ambiguity wrt 32/64 bit time_t. It is only available
from the UAPI section as a compat tweak for user code, not for kernel
code.

What should be done wrt addressing the y2038 issue fully is beyond this
patch series. __user_old_timespec is merely an annotation on the
existing implementation in order to highlight the kernel<->user
interface boundary, which may help in fully addressing y2038 later on.

Eventually, it should be decided whether a legacy timespec32 should
still be supported for 32bit applications building in dual-time
configurations (time32_t and time64_t), or single-time configuration
should be the norm with user-space using time64_t exclusively. This is
beyond the scope of this patch series to decide of the way to go.

-- 
Philippe.


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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-02-21 15:27     ` Philippe Gerum
@ 2021-02-22  1:04       ` chensong
  2021-02-22  8:21       ` florian.bezdeka
  1 sibling, 0 replies; 57+ messages in thread
From: chensong @ 2021-02-22  1:04 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai



On 2021年02月21日 23:27, Philippe Gerum wrote:
>
> chensong via Xenomai <xenomai@xenomai.org> writes:
>
>>> +/*
>>> + * Our representation of time at the kernel<->user interface boundary
>>> + * at the moment, until we have fully transitioned to a y2038-safe
>>> + * implementation in libcobalt.
>>> + */
>>> +struct __user_old_timespec {
>>> +	long  tv_sec;
>>> +	long  tv_nsec;
>>> +};
>>
>> why not use old_timespec32, which is timespec32 representation defined
>> in include/linux/time32?
>>
>
> Using old_timespec32 in this context would mean that any time value
> received from userland by the core should be restricted to 32bit time_t,
> which is not what we want, at least for 64bit platforms:
>
> include/vdso/time32.h:
>
> struct old_timespec32 {
> 	old_time32_t	tv_sec;
> 	s32		tv_nsec;
> };
>
> __user_old_timespec conveys the notion that we are generically talking
> about "the old timespec type which has a y2038 problem"; this is not
> specifically about the legacy timespec type on 32bit machines.
>
> Since v5.4-rc6, we do have __kernel_old_timespec though, which could
> have been used instead of __user_old_timespec:
>
> include/uapi/asm-generic/posix_types.h:
>
> typedef long __kernel_long_t;
>
> include/uapi/linux/time_types.h:
>
> struct __kernel_old_timespec {
> 	__kernel_long_t		tv_sec;		/* seconds */
> 	long			tv_nsec;	/* nanoseconds */
> };
>
> However, older (non-x86) toolchains do not define __kernel_old_timespec,
> so I went for adding __user_old_timespec to the Cobalt UAPI. This may be
> seen as a temporary option until stricter requirements on the minimum
> toolchain support for building Cobalt is decided.

what if we define __kernel_old_timespec in 
./kernel/cobalt/include/asm-generic/xenomai/wrappers.h, like we always 
do. we don't have to introduce a new struct.


>
>>>
>>>    COBALT_SYSCALL(clock_settime, current,
>>> -	       (clockid_t clock_id, const struct timespec __user *u_ts))
>>> +	       (clockid_t clock_id, const struct __user_old_timespec __user *u_ts))
>>
>> I planned to still use timespec as the argument, tv_sec is defined as
>> long, 32bit long in 32bit system, 64bit long in 64bit system, use
>> timespec64 in implementation.
>>

same with above, like "__kernel_old_timespec __user *u_ts",.

>
> Keeping struct timespec for the argument does not seem the right thing
> to do, as this type has been phased out from recent kernels, precisely
> to stop spreading ambiguity wrt 32/64 bit time_t. It is only available
> from the UAPI section as a compat tweak for user code, not for kernel
> code.
>
agree, in linux kernel, __kernel_timespec is specific for 64bit and 
old_timespec32 is specific for 32bit, clear. but we kind of need a 
blurry timespec, that's why we planed to keep timespec. 
__kernel_old_timespec looks like a good solution in this case.

> What should be done wrt addressing the y2038 issue fully is beyond this
> patch series. __user_old_timespec is merely an annotation on the
> existing implementation in order to highlight the kernel<->user
> interface boundary, which may help in fully addressing y2038 later on.
>
> Eventually, it should be decided whether a legacy timespec32 should
> still be supported for 32bit applications building in dual-time
> configurations (time32_t and time64_t), or single-time configuration
> should be the norm with user-space using time64_t exclusively. This is
> beyond the scope of this patch series to decide of the way to go.
>


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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-02-21 15:27     ` Philippe Gerum
  2021-02-22  1:04       ` chensong
@ 2021-02-22  8:21       ` florian.bezdeka
  2021-02-22  9:08         ` Philippe Gerum
  1 sibling, 1 reply; 57+ messages in thread
From: florian.bezdeka @ 2021-02-22  8:21 UTC (permalink / raw)
  To: rpm, chensong; +Cc: xenomai

On Sun, 2021-02-21 at 16:27 +0100, Philippe Gerum via Xenomai wrote:
> chensong via Xenomai <xenomai@xenomai.org> writes:
> 
> > > +/*
> > > + * Our representation of time at the kernel<->user interface boundary
> > > + * at the moment, until we have fully transitioned to a y2038-safe
> > > + * implementation in libcobalt.
> > > + */
> > > +struct __user_old_timespec {
> > > +	long  tv_sec;
> > > +	long  tv_nsec;
> > > +};
> > 
> > why not use old_timespec32, which is timespec32 representation defined
> > in include/linux/time32?
> > 
> 
> Using old_timespec32 in this context would mean that any time value
> received from userland by the core should be restricted to 32bit time_t,
> which is not what we want, at least for 64bit platforms:
> 
> include/vdso/time32.h:
> 
> struct old_timespec32 {
> 	old_time32_t	tv_sec;
> 	s32		tv_nsec;
> };
> 
> __user_old_timespec conveys the notion that we are generically talking
> about "the old timespec type which has a y2038 problem"; this is not
> specifically about the legacy timespec type on 32bit machines.
> 
> Since v5.4-rc6, we do have __kernel_old_timespec though, which could
> have been used instead of __user_old_timespec:

According to my information (based on
https://elixir.bootlin.com/linux/v5.5-rc1/A/ident/__kernel_old_timespec
) this is available since v5.5-rc1.

> 
> include/uapi/asm-generic/posix_types.h:
> 
> typedef long __kernel_long_t;
> 
> include/uapi/linux/time_types.h:
> 
> struct __kernel_old_timespec {
> 	__kernel_long_t		tv_sec;		/* seconds */
> 	long			tv_nsec;	/* nanoseconds */
> };
>  
> so I went for adding __user_old_timespec to the Cobalt UAPI. This may be
> seen as a temporary option until stricter requirements on the minimum
> toolchain support for building Cobalt is decided.

__kernel_old_timespec is part of the "common" Linux uapi, so not x86
specific. Could you explain the problem you know of (or even see) with
some of the toolchains? Sounds strange...

> 
> > > 
> > >   COBALT_SYSCALL(clock_settime, current,
> > > -	       (clockid_t clock_id, const struct timespec __user *u_ts))
> > > +	       (clockid_t clock_id, const struct __user_old_timespec __user *u_ts))
> > 
> > I planned to still use timespec as the argument, tv_sec is defined as
> > long, 32bit long in 32bit system, 64bit long in 64bit system, use 
> > timespec64 in implementation.
> > 
> 
> Keeping struct timespec for the argument does not seem the right thing
> to do, as this type has been phased out from recent kernels, precisely
> to stop spreading ambiguity wrt 32/64 bit time_t. It is only available
> from the UAPI section as a compat tweak for user code, not for kernel
> code.

We would need a definition for older kernels anyway, but why are we not
allowed to re-use the definition from the uapi here?

> 
> What should be done wrt addressing the y2038 issue fully is beyond this
> patch series. __user_old_timespec is merely an annotation on the
> existing implementation in order to highlight the kernel<->user
> interface boundary, which may help in fully addressing y2038 later on.
> 
> Eventually, it should be decided whether a legacy timespec32 should
> still be supported for 32bit applications building in dual-time
> configurations (time32_t and time64_t), or single-time configuration
> should be the norm with user-space using time64_t exclusively. This is
> beyond the scope of this patch series to decide of the way to go.

Let's discuss that within the next Community Meeting Minutes. When we
started scanning the code base to get an overview of all the things
that have to be done we assumed that we would need to stay fully
backward compatible and "single time_t" defined by the libc that is
beeing used. That may have changed in the meantime and we could take
other patterns into account as well.


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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-02-22  8:21       ` florian.bezdeka
@ 2021-02-22  9:08         ` Philippe Gerum
  2021-03-08 12:19           ` Jan Kiszka
  0 siblings, 1 reply; 57+ messages in thread
From: Philippe Gerum @ 2021-02-22  9:08 UTC (permalink / raw)
  To: florian.bezdeka; +Cc: chensong, xenomai


florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:

> On Sun, 2021-02-21 at 16:27 +0100, Philippe Gerum via Xenomai wrote:
>> chensong via Xenomai <xenomai@xenomai.org> writes:
>> 
>> > > +/*
>> > > + * Our representation of time at the kernel<->user interface boundary
>> > > + * at the moment, until we have fully transitioned to a y2038-safe
>> > > + * implementation in libcobalt.
>> > > + */
>> > > +struct __user_old_timespec {
>> > > +	long  tv_sec;
>> > > +	long  tv_nsec;
>> > > +};
>> > 
>> > why not use old_timespec32, which is timespec32 representation defined
>> > in include/linux/time32?
>> > 
>> 
>> Using old_timespec32 in this context would mean that any time value
>> received from userland by the core should be restricted to 32bit time_t,
>> which is not what we want, at least for 64bit platforms:
>> 
>> include/vdso/time32.h:
>> 
>> struct old_timespec32 {
>> 	old_time32_t	tv_sec;
>> 	s32		tv_nsec;
>> };
>> 
>> __user_old_timespec conveys the notion that we are generically talking
>> about "the old timespec type which has a y2038 problem"; this is not
>> specifically about the legacy timespec type on 32bit machines.
>> 
>> Since v5.4-rc6, we do have __kernel_old_timespec though, which could
>> have been used instead of __user_old_timespec:
>
> According to my information (based on
> https://elixir.bootlin.com/linux/v5.5-rc1/A/ident/__kernel_old_timespec
> ) this is available since v5.5-rc1.
>

This disagrees with the git history then:

commit 94c467ddb273dc9a6a4fb09aef392c119b151edb
Author: Arnd Bergmann <arnd@arndb.de>

    y2038: add __kernel_old_timespec and __kernel_old_time_t

$ git describe 94c467ddb273dc9a6a4fb09aef392c119b151edb
v5.4-rc6-2-g94c467ddb273dc9

>> 
>> include/uapi/asm-generic/posix_types.h:
>> 
>> typedef long __kernel_long_t;
>> 
>> include/uapi/linux/time_types.h:
>> 
>> struct __kernel_old_timespec {
>> 	__kernel_long_t		tv_sec;		/* seconds */
>> 	long			tv_nsec;	/* nanoseconds */
>> };
>>  
>> so I went for adding __user_old_timespec to the Cobalt UAPI. This may be
>> seen as a temporary option until stricter requirements on the minimum
>> toolchain support for building Cobalt is decided.
>
> __kernel_old_timespec is part of the "common" Linux uapi, so not x86
> specific. Could you explain the problem you know of (or even see) with
> some of the toolchains? Sounds strange...
>

(Cross) toolchains use a snapshot of the linux UAPI taken at some point
in time. If a toolchain is somewhat outdated compared to the current
state of the kernel UAPI, then there is a problem with using the types
it defines. e.g. recent linaro toolchains for aarch32, aarch64 do not
provide any definition for __kernel_old_timespec, yet.

Now, as Song suggested, I could have defined __kernel_old_timespec in
the Cobalt UAPI to address this, instead of defining
__user_old_timespec. I found an upside in clearly stating this
particular interface boundary for time values Cobalt-wise, using a
Cobalt-specific type. What this should become in a subsequent series of
patches addressing the y2038 issue fully is beyond the scope of the
current series.

>> 
>> > > 
>> > >   COBALT_SYSCALL(clock_settime, current,
>> > > -	       (clockid_t clock_id, const struct timespec __user *u_ts))
>> > > +	       (clockid_t clock_id, const struct __user_old_timespec __user *u_ts))
>> > 
>> > I planned to still use timespec as the argument, tv_sec is defined as
>> > long, 32bit long in 32bit system, 64bit long in 64bit system, use 
>> > timespec64 in implementation.
>> > 
>> 
>> Keeping struct timespec for the argument does not seem the right thing
>> to do, as this type has been phased out from recent kernels, precisely
>> to stop spreading ambiguity wrt 32/64 bit time_t. It is only available
>> from the UAPI section as a compat tweak for user code, not for kernel
>> code.
>
> We would need a definition for older kernels anyway, but why are we not
> allowed to re-use the definition from the uapi here?
>

Because the timespec type along with all other ambiguous types are now
hidden from the kernel code in recent mainline releases:

commit c766d1472c70d25ad475cf56042af1652e792b23
Author: Arnd Bergmann <arnd@arndb.de>

    y2038: hide timeval/timespec/itimerval/itimerspec types
    
Which gives, in include/uapi/linux/time.h:

#ifndef __KERNEL__
#ifndef _STRUCT_TIMESPEC
#define _STRUCT_TIMESPEC
struct timespec {
	__kernel_old_time_t	tv_sec;		/* seconds */
	long			tv_nsec;	/* nanoseconds */
};
#endif

struct timeval {
	__kernel_old_time_t	tv_sec;		/* seconds */
	__kernel_suseconds_t	tv_usec;	/* microseconds */
};

struct itimerspec {
	struct timespec it_interval;/* timer period */
	struct timespec it_value;	/* timer expiration */
};

struct itimerval {
	struct timeval it_interval;/* timer interval */
	struct timeval it_value;	/* current value */
};
#endif

>> 
>> What should be done wrt addressing the y2038 issue fully is beyond this
>> patch series. __user_old_timespec is merely an annotation on the
>> existing implementation in order to highlight the kernel<->user
>> interface boundary, which may help in fully addressing y2038 later on.
>> 
>> Eventually, it should be decided whether a legacy timespec32 should
>> still be supported for 32bit applications building in dual-time
>> configurations (time32_t and time64_t), or single-time configuration
>> should be the norm with user-space using time64_t exclusively. This is
>> beyond the scope of this patch series to decide of the way to go.
>
> Let's discuss that within the next Community Meeting Minutes. When we
> started scanning the code base to get an overview of all the things
> that have to be done we assumed that we would need to stay fully
> backward compatible and "single time_t" defined by the libc that is
> beeing used. That may have changed in the meantime and we could take
> other patterns into account as well.

-- 
Philippe.


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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-02-20 15:18 ` [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64 Philippe Gerum
  2021-02-21  2:17   ` chensong
@ 2021-03-03 10:05   ` florian.bezdeka
  2021-03-04  9:35     ` Philippe Gerum
  2021-03-03 14:36   ` florian.bezdeka
  2 siblings, 1 reply; 57+ messages in thread
From: florian.bezdeka @ 2021-03-03 10:05 UTC (permalink / raw)
  To: rpm, jan.kiszka; +Cc: xenomai, chensong

On Sat, 2021-02-20 at 16:18 +0100, Philippe Gerum via Xenomai wrote:
[snip]
> diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
> index 05a861dfe..467a9b7dd 100644
> --- a/kernel/cobalt/posix/sem.c
> +++ b/kernel/cobalt/posix/sem.c
> @@ -267,7 +267,7 @@ out:
>  	return ret;
>  }
>  
> -static inline int sem_fetch_timeout(struct timespec *ts,
> +static inline int sem_fetch_timeout(struct timespec64 *ts,
>  				    const void __user *u_ts)

Handle the following with care, maybe my understanding of
CONFIG_XENO_ARCH_SYS3264 is wrong. See below...

My understanding is that this is a breaking change for 32 bit kernels.
The broken part is hidden here, but sem_fetch_timeout() now assumes
that the user provided timespec64, which is not be the case for 32 bit
applications running on a 32 bit kernel.


>  {
>  	return u_ts == NULL ? -EFAULT :
> @@ -276,10 +276,10 @@ static inline int sem_fetch_timeout(struct timespec *ts,
>  
>  int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
>  			   const void __user *u_ts,
> -			   int (*fetch_timeout)(struct timespec *ts,
> +			   int (*fetch_timeout)(struct timespec64 *ts,
>  						const void __user *u_ts))
>  {
> -	struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
> +	struct timespec64 ts = { .tv_sec = 0, .tv_nsec = 0 };
>  	int pull_ts = 1, ret, info;
>  	struct cobalt_sem *sem;
>  	xnhandle_t handle;
> @@ -434,7 +434,7 @@ COBALT_SYSCALL(sem_wait, primary,
>  
>  COBALT_SYSCALL(sem_timedwait, primary,
>  	       (struct cobalt_sem_shadow __user *u_sem,
> -		struct timespec __user *u_ts))
> +		struct __user_old_timespec __user *u_ts))

This change is still correct, but this is where the journey begins. If
my understanding of CONFIG_XENO_ARCH_SYS3264 is correct, this syscall
is being used on 32 bit kernels as well. Is that understanding correct?

>  {
>  	return __cobalt_sem_timedwait(u_sem, u_ts, sem_fetch_timeout);
>  }


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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-02-20 15:18 ` [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64 Philippe Gerum
  2021-02-21  2:17   ` chensong
  2021-03-03 10:05   ` florian.bezdeka
@ 2021-03-03 14:36   ` florian.bezdeka
  2021-03-04  9:44     ` Philippe Gerum
  2 siblings, 1 reply; 57+ messages in thread
From: florian.bezdeka @ 2021-03-03 14:36 UTC (permalink / raw)
  To: rpm, jan.kiszka; +Cc: xenomai

On Sat, 2021-02-20 at 16:18 +0100, Philippe Gerum via Xenomai wrote:
[snip]
> +#if __BITS_PER_LONG == 64

That might be a beginner question, but I'm learning from the best ;-)

Do we really care about each single assignment (two per timespec) and
each object on the stack that it is worth duplicating all this helpers?
We could use the __BITS_PER_LONG == 32 version for both worlds,
couldn't we?

Thanks in advance...

> +
> +/*
> + * NOTE: those copy helpers won't work in compat mode: use
> + * sys32_get_timespec(), sys32_put_timespec() instead.
> + */
> +
> +static inline int cobalt_get_u_timespec(struct timespec64 *dst,
> +			const struct __user_old_timespec __user *src)
> +{
> +	return cobalt_copy_from_user(dst, src, sizeof(*dst));
> +}
> +
> +static inline int cobalt_put_u_timespec(
> +	struct __user_old_timespec __user *dst,
> +	const struct timespec64 *src)
> +{
> +	return cobalt_copy_to_user(dst, src, sizeof(*dst));
> +}
> +
> +#else /* __BITS_PER_LONG == 32 */
> +
> +static inline int cobalt_get_u_timespec(struct timespec64 *dst,
> +			const struct __user_old_timespec __user *src)
> +{
> +	struct __user_old_timespec u_ts;
> +	int ret;
> +
> +	ret = cobalt_copy_from_user(&u_ts, src, sizeof(u_ts));
> +	if (ret)
> +		return ret;
> +
> +	dst->tv_sec = u_ts.tv_sec;
> +	dst->tv_nsec = u_ts.tv_nsec;
> +
> +	return 0;
> +}
> +
> +static inline int cobalt_put_u_timespec(
> +	struct __user_old_timespec __user *dst,
> +	const struct timespec64 *src)
> +{
> +	struct __user_old_timespec u_ts;
> +	int ret;
> +
> +	u_ts.tv_sec = src->tv_sec;
> +	u_ts.tv_nsec = src->tv_nsec;
> +
> +	ret = cobalt_copy_to_user(dst, &u_ts, sizeof(*dst));
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +#endif

[snip]


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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-03-03 10:05   ` florian.bezdeka
@ 2021-03-04  9:35     ` Philippe Gerum
  2021-03-04  9:49       ` florian.bezdeka
  0 siblings, 1 reply; 57+ messages in thread
From: Philippe Gerum @ 2021-03-04  9:35 UTC (permalink / raw)
  To: florian.bezdeka; +Cc: jan.kiszka, xenomai, chensong


florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:

> On Sat, 2021-02-20 at 16:18 +0100, Philippe Gerum via Xenomai wrote:
> [snip]
>> diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
>> index 05a861dfe..467a9b7dd 100644
>> --- a/kernel/cobalt/posix/sem.c
>> +++ b/kernel/cobalt/posix/sem.c
>> @@ -267,7 +267,7 @@ out:
>>  	return ret;
>>  }
>>  
>> -static inline int sem_fetch_timeout(struct timespec *ts,
>> +static inline int sem_fetch_timeout(struct timespec64 *ts,
>>  				    const void __user *u_ts)
>
> Handle the following with care, maybe my understanding of
> CONFIG_XENO_ARCH_SYS3264 is wrong. See below...
>
> My understanding is that this is a breaking change for 32 bit kernels.
> The broken part is hidden here, but sem_fetch_timeout() now assumes
> that the user provided timespec64, which is not be the case for 32 bit
> applications running on a 32 bit kernel.
>

The user-provided memory is referred to by u_ts, not ts, which receives
the timestamp fetch_timeout() is supposed to return. The change should
only affect the return type, not the source one. sys32_fetch_timeout()
should still do the right thing via sys32_get_timespec().

Did you observe a manifest breakage with 32_64 setups?

>
>>  {
>>  	return u_ts == NULL ? -EFAULT :
>> @@ -276,10 +276,10 @@ static inline int sem_fetch_timeout(struct timespec *ts,
>>  
>>  int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
>>  			   const void __user *u_ts,
>> -			   int (*fetch_timeout)(struct timespec *ts,
>> +			   int (*fetch_timeout)(struct timespec64 *ts,
>>  						const void __user *u_ts))
>>  {
>> -	struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
>> +	struct timespec64 ts = { .tv_sec = 0, .tv_nsec = 0 };
>>  	int pull_ts = 1, ret, info;
>>  	struct cobalt_sem *sem;
>>  	xnhandle_t handle;
>> @@ -434,7 +434,7 @@ COBALT_SYSCALL(sem_wait, primary,
>>  
>>  COBALT_SYSCALL(sem_timedwait, primary,
>>  	       (struct cobalt_sem_shadow __user *u_sem,
>> -		struct timespec __user *u_ts))
>> +		struct __user_old_timespec __user *u_ts))
>
> This change is still correct, but this is where the journey begins. If
> my understanding of CONFIG_XENO_ARCH_SYS3264 is correct, this syscall
> is being used on 32 bit kernels as well. Is that understanding correct?

COBALT_SYSCALL(sem_timedwait, ...) is only used in native (e.g. mere
64bit, or 32bit) mode. The following one is used in 32bit over 64bit
mode specifically:

COBALT_SYSCALL32emu(sem_timedwait, primary,
		    (struct cobalt_sem_shadow __user *u_sem,
		     struct old_timespec32 __user *u_ts))


-- 
Philippe.


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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-03-03 14:36   ` florian.bezdeka
@ 2021-03-04  9:44     ` Philippe Gerum
  2021-03-04  9:57       ` florian.bezdeka
  0 siblings, 1 reply; 57+ messages in thread
From: Philippe Gerum @ 2021-03-04  9:44 UTC (permalink / raw)
  To: florian.bezdeka; +Cc: jan.kiszka, xenomai


florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:

> On Sat, 2021-02-20 at 16:18 +0100, Philippe Gerum via Xenomai wrote:
> [snip]
>> +#if __BITS_PER_LONG == 64
>
> That might be a beginner question, but I'm learning from the best ;-)
>
> Do we really care about each single assignment (two per timespec) and
> each object on the stack that it is worth duplicating all this helpers?
> We could use the __BITS_PER_LONG == 32 version for both worlds,
> couldn't we?

Yes, this would work as well. I agree that the very limited gain is not
worth the code duplication.

-- 
Philippe.


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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-03-04  9:35     ` Philippe Gerum
@ 2021-03-04  9:49       ` florian.bezdeka
  2021-03-04  9:55         ` Philippe Gerum
  0 siblings, 1 reply; 57+ messages in thread
From: florian.bezdeka @ 2021-03-04  9:49 UTC (permalink / raw)
  To: rpm; +Cc: xenomai, jan.kiszka, chensong

On Thu, 2021-03-04 at 10:35 +0100, Philippe Gerum wrote:
> florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:
> 
> > On Sat, 2021-02-20 at 16:18 +0100, Philippe Gerum via Xenomai wrote:
> > [snip]
> > > diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
> > > index 05a861dfe..467a9b7dd 100644
> > > --- a/kernel/cobalt/posix/sem.c
> > > +++ b/kernel/cobalt/posix/sem.c
> > > @@ -267,7 +267,7 @@ out:
> > >  	return ret;
> > >  }
> > >  
> > > 
> > > 
> > > 
> > > -static inline int sem_fetch_timeout(struct timespec *ts,
> > > +static inline int sem_fetch_timeout(struct timespec64 *ts,
> > >  				    const void __user *u_ts)
> > 
> > Handle the following with care, maybe my understanding of
> > CONFIG_XENO_ARCH_SYS3264 is wrong. See below...
> > 
> > My understanding is that this is a breaking change for 32 bit kernels.
> > The broken part is hidden here, but sem_fetch_timeout() now assumes
> > that the user provided timespec64, which is not be the case for 32 bit
> > applications running on a 32 bit kernel.
> > 
> 
> The user-provided memory is referred to by u_ts, not ts, which receives
> the timestamp fetch_timeout() is supposed to return. The change should
> only affect the return type, not the source one. sys32_fetch_timeout()
> should still do the right thing via sys32_get_timespec().

Adding the full code:

static inline int sem_fetch_timeout(struct timespec64 *ts,
				    const void __user *u_ts)
{
	return u_ts == NULL ? -EFAULT :
		cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
}

Copying sizeof(*ts) is to much if the application provided
"__old_time_t" (sizeof(time_t) =4) only. Isn't it? I would expect the
result (in ts) to be garbage. Due to different padding the "sec" field
(in ts) would now contain the nsec value from u_ts as well.

I will come up with a proposal to fix that. We need some discussion
anyway...

> 
> Did you observe a manifest breakage with 32_64 setups?
> 
> > 
> > >  {
> > >  	return u_ts == NULL ? -EFAULT :
> > > @@ -276,10 +276,10 @@ static inline int sem_fetch_timeout(struct timespec *ts,
> > >  
> > > 
> > > 
> > > 
> > >  int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
> > >  			   const void __user *u_ts,
> > > -			   int (*fetch_timeout)(struct timespec *ts,
> > > +			   int (*fetch_timeout)(struct timespec64 *ts,
> > >  						const void __user *u_ts))
> > >  {
> > > -	struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
> > > +	struct timespec64 ts = { .tv_sec = 0, .tv_nsec = 0 };
> > >  	int pull_ts = 1, ret, info;
> > >  	struct cobalt_sem *sem;
> > >  	xnhandle_t handle;
> > > @@ -434,7 +434,7 @@ COBALT_SYSCALL(sem_wait, primary,
> > >  
> > > 
> > > 
> > > 
> > >  COBALT_SYSCALL(sem_timedwait, primary,
> > >  	       (struct cobalt_sem_shadow __user *u_sem,
> > > -		struct timespec __user *u_ts))
> > > +		struct __user_old_timespec __user *u_ts))
> > 
> > This change is still correct, but this is where the journey begins. If
> > my understanding of CONFIG_XENO_ARCH_SYS3264 is correct, this syscall
> > is being used on 32 bit kernels as well. Is that understanding correct?
> 
> COBALT_SYSCALL(sem_timedwait, ...) is only used in native (e.g. mere
> 64bit, or 32bit) mode. The following one is used in 32bit over 64bit
> mode specifically:
> 
> COBALT_SYSCALL32emu(sem_timedwait, primary,
> 		    (struct cobalt_sem_shadow __user *u_sem,
> 		     struct old_timespec32 __user *u_ts))
> 
> 


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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-03-04  9:49       ` florian.bezdeka
@ 2021-03-04  9:55         ` Philippe Gerum
  2021-03-04  9:59           ` florian.bezdeka
  2021-03-04 10:08           ` Philippe Gerum
  0 siblings, 2 replies; 57+ messages in thread
From: Philippe Gerum @ 2021-03-04  9:55 UTC (permalink / raw)
  To: florian.bezdeka; +Cc: xenomai, jan.kiszka, chensong


florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:

> On Thu, 2021-03-04 at 10:35 +0100, Philippe Gerum wrote:
>> florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:
>> 
>> > On Sat, 2021-02-20 at 16:18 +0100, Philippe Gerum via Xenomai wrote:
>> > [snip]
>> > > diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
>> > > index 05a861dfe..467a9b7dd 100644
>> > > --- a/kernel/cobalt/posix/sem.c
>> > > +++ b/kernel/cobalt/posix/sem.c
>> > > @@ -267,7 +267,7 @@ out:
>> > >  	return ret;
>> > >  }
>> > >  
>> > > 
>> > > 
>> > > 
>> > > -static inline int sem_fetch_timeout(struct timespec *ts,
>> > > +static inline int sem_fetch_timeout(struct timespec64 *ts,
>> > >  				    const void __user *u_ts)
>> > 
>> > Handle the following with care, maybe my understanding of
>> > CONFIG_XENO_ARCH_SYS3264 is wrong. See below...
>> > 
>> > My understanding is that this is a breaking change for 32 bit kernels.
>> > The broken part is hidden here, but sem_fetch_timeout() now assumes
>> > that the user provided timespec64, which is not be the case for 32 bit
>> > applications running on a 32 bit kernel.
>> > 
>> 
>> The user-provided memory is referred to by u_ts, not ts, which receives
>> the timestamp fetch_timeout() is supposed to return. The change should
>> only affect the return type, not the source one. sys32_fetch_timeout()
>> should still do the right thing via sys32_get_timespec().
>
> Adding the full code:
>
> static inline int sem_fetch_timeout(struct timespec64 *ts,
> 				    const void __user *u_ts)
> {
> 	return u_ts == NULL ? -EFAULT :
> 		cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
> }
>
> Copying sizeof(*ts) is to much if the application provided
> "__old_time_t" (sizeof(time_t) =4) only. Isn't it? I would expect the
> result (in ts) to be garbage. Due to different padding the "sec" field
> (in ts) would now contain the nsec value from u_ts as well.
>

Ah, I was looking at the wrong path (32emu). Yes, this is broken for
mere 32bit now (i.e. natively 32bit platform).

-- 
Philippe.


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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-03-04  9:44     ` Philippe Gerum
@ 2021-03-04  9:57       ` florian.bezdeka
  0 siblings, 0 replies; 57+ messages in thread
From: florian.bezdeka @ 2021-03-04  9:57 UTC (permalink / raw)
  To: rpm; +Cc: xenomai, jan.kiszka

On Thu, 2021-03-04 at 10:44 +0100, Philippe Gerum wrote:
> florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:
> 
> > On Sat, 2021-02-20 at 16:18 +0100, Philippe Gerum via Xenomai wrote:
> > [snip]
> > > +#if __BITS_PER_LONG == 64
> > 
> > That might be a beginner question, but I'm learning from the best ;-)
> > 
> > Do we really care about each single assignment (two per timespec) and
> > each object on the stack that it is worth duplicating all this helpers?
> > We could use the __BITS_PER_LONG == 32 version for both worlds,
> > couldn't we?
> 
> Yes, this would work as well. I agree that the very limited gain is not
> worth the code duplication.
> 

I (or Song) will take care of it. No need to interrupt dovetail
stuff...

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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-03-04  9:55         ` Philippe Gerum
@ 2021-03-04  9:59           ` florian.bezdeka
  2021-03-04 10:08           ` Philippe Gerum
  1 sibling, 0 replies; 57+ messages in thread
From: florian.bezdeka @ 2021-03-04  9:59 UTC (permalink / raw)
  To: rpm; +Cc: xenomai, jan.kiszka, chensong

On Thu, 2021-03-04 at 10:55 +0100, Philippe Gerum wrote:
> 
> > 
> > Adding the full code:
> > 
> > static inline int sem_fetch_timeout(struct timespec64 *ts,
> > 				    const void __user *u_ts)
> > {
> > 	return u_ts == NULL ? -EFAULT :
> > 		cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
> > }
> > 
> > Copying sizeof(*ts) is to much if the application provided
> > "__old_time_t" (sizeof(time_t) =4) only. Isn't it? I would expect the
> > result (in ts) to be garbage. Due to different padding the "sec" field
> > (in ts) would now contain the nsec value from u_ts as well.
> > 
> 
> Ah, I was looking at the wrong path (32emu). Yes, this is broken for
> mere 32bit now (i.e. natively 32bit platform).
> 

I already prepared a patch. That's useful for some further discussion
as well. Coming soon, no need to interrupt dovetail porting ;-)

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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-03-04  9:55         ` Philippe Gerum
  2021-03-04  9:59           ` florian.bezdeka
@ 2021-03-04 10:08           ` Philippe Gerum
  2021-03-04 11:36             ` [y2038][RFC PATCH 0/2] Pattern for implementing y2038 syscalls Florian Bezdeka
                               ` (2 more replies)
  1 sibling, 3 replies; 57+ messages in thread
From: Philippe Gerum @ 2021-03-04 10:08 UTC (permalink / raw)
  To: florian.bezdeka; +Cc: xenomai, jan.kiszka, chensong


Philippe Gerum <rpm@xenomai.org> writes:

> florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:
>
>> On Thu, 2021-03-04 at 10:35 +0100, Philippe Gerum wrote:
>>> florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:
>>> 
>>> > On Sat, 2021-02-20 at 16:18 +0100, Philippe Gerum via Xenomai wrote:
>>> > [snip]
>>> > > diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
>>> > > index 05a861dfe..467a9b7dd 100644
>>> > > --- a/kernel/cobalt/posix/sem.c
>>> > > +++ b/kernel/cobalt/posix/sem.c
>>> > > @@ -267,7 +267,7 @@ out:
>>> > >  	return ret;
>>> > >  }
>>> > >  
>>> > > 
>>> > > 
>>> > > 
>>> > > -static inline int sem_fetch_timeout(struct timespec *ts,
>>> > > +static inline int sem_fetch_timeout(struct timespec64 *ts,
>>> > >  				    const void __user *u_ts)
>>> > 
>>> > Handle the following with care, maybe my understanding of
>>> > CONFIG_XENO_ARCH_SYS3264 is wrong. See below...
>>> > 
>>> > My understanding is that this is a breaking change for 32 bit kernels.
>>> > The broken part is hidden here, but sem_fetch_timeout() now assumes
>>> > that the user provided timespec64, which is not be the case for 32 bit
>>> > applications running on a 32 bit kernel.
>>> > 
>>> 
>>> The user-provided memory is referred to by u_ts, not ts, which receives
>>> the timestamp fetch_timeout() is supposed to return. The change should
>>> only affect the return type, not the source one. sys32_fetch_timeout()
>>> should still do the right thing via sys32_get_timespec().
>>
>> Adding the full code:
>>
>> static inline int sem_fetch_timeout(struct timespec64 *ts,
>> 				    const void __user *u_ts)
>> {
>> 	return u_ts == NULL ? -EFAULT :
>> 		cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
>> }
>>
>> Copying sizeof(*ts) is to much if the application provided
>> "__old_time_t" (sizeof(time_t) =4) only. Isn't it? I would expect the
>> result (in ts) to be garbage. Due to different padding the "sec" field
>> (in ts) would now contain the nsec value from u_ts as well.
>>
>
> Ah, I was looking at the wrong path (32emu). Yes, this is broken for
> mere 32bit now (i.e. natively 32bit platform).

We could simply use cobalt_get_u_timespec() instead of open coding the
call to cobalt_copy_from_user(). Condvars have this right already,
mutex, mq and sema4s have their fetch_timeout() helper broken
indeed. Good spot.

-- 
Philippe.


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

* [y2038][RFC PATCH 0/2] Pattern for implementing y2038 syscalls
  2021-03-04 10:08           ` Philippe Gerum
@ 2021-03-04 11:36             ` Florian Bezdeka
  2021-03-04 11:36               ` [y2038][RFC PATCH 1/2] y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
  2021-03-04 11:36               ` [y2038][RFC PATCH 2/2] y2038: Adding sem_timedwait_time64 Florian Bezdeka
  2021-03-08 12:59             ` [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64 Jan Kiszka
  2021-03-10 17:52             ` florian.bezdeka
  2 siblings, 2 replies; 57+ messages in thread
From: Florian Bezdeka @ 2021-03-04 11:36 UTC (permalink / raw)
  To: xenomai, jan.kiszka, rpm, chensong

Hi!

A small RFC series for establishing / discussing a pattern for the 
implementation of y2038 syscalls. 

"The Linux pattern":
Convert the time_t related data structures to time64_t directly in the
syscall handler and pass it to the time64_t based internal APIs. 

We can follow this pattern, which allows us to re-use most of the code
that is needed for all the syscall implementations, including the
compat or ia32 / x32 ones. 

But: Some of the syscalls are calling cobalt_copy_from_user() just 
before using the value the first time. As some syscalls (like 
sc_cobalt_sem_timedwait) might not need the value in all code paths
we would end up with a couple of instructions that were "wasted". 
Would that be acceptable for us? 

If we can not follow this pattern I guess we have to duplicate all the
helpers in use to get time_t as well as time64_t support. Mainly because
we share a single syscall table between different entry points on x86.


"The syscall integration topic":
We need:
 - a new native syscall for each time_t affected syscall
 - a new compat/emulation syscall to get 32 bit applications running on 
   64 bit kernels done (so far only x86 is implemented)

As 64 bit kernels are currently using the same syscall tables as 32 bit
kernels we would end up with one superflous entry in the table for 64
bit kernels. Is that acceptable?


"The syscall naming topic":
My proposal is adding "_time64" to all y2038 safe syscalls. We can't
really use "_time32" for the "affected" ones because for 64i bit kernels
they are y2038 safe already. Further ideas?

Best regards,
Florian

Florian Bezdeka (2):
  y2038: Fixing the sem_timedwait syscall for 32 bit systems
  y2038: Adding sem_timedwait_time64

 include/cobalt/uapi/syscall.h   |  1 +
 kernel/cobalt/posix/sem.c       | 49 +++++++++++++++++----------------
 kernel/cobalt/posix/sem.h       | 10 ++++---
 kernel/cobalt/posix/syscall32.c | 23 ++++++++++++++--
 kernel/cobalt/posix/syscall32.h |  6 +++-
 5 files changed, 59 insertions(+), 30 deletions(-)

-- 
2.29.2



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

* [y2038][RFC PATCH 1/2] y2038: Fixing the sem_timedwait syscall for 32 bit systems
  2021-03-04 11:36             ` [y2038][RFC PATCH 0/2] Pattern for implementing y2038 syscalls Florian Bezdeka
@ 2021-03-04 11:36               ` Florian Bezdeka
  2021-03-04 15:11                 ` Philippe Gerum
  2021-03-04 11:36               ` [y2038][RFC PATCH 2/2] y2038: Adding sem_timedwait_time64 Florian Bezdeka
  1 sibling, 1 reply; 57+ messages in thread
From: Florian Bezdeka @ 2021-03-04 11:36 UTC (permalink / raw)
  To: xenomai, jan.kiszka, rpm, chensong

On systems using 32 bit for time_t the sem_timedwait syscall was broken
because the function used for copying the timeout value from userspace
to kernel (=sem_fetch_timeout()) was always copying
sizeof(struct timespec64).

A 32 bit application (or more specific an application with 4 byte
time_t) would only provide sizeof(struct old_timespec32).

Notable changes:
  - The copy operation from userspace to kernel is now already done in
    the syscall handler. So it is always done. Previously it was copied
    over and validated before the first use (when used at all).
    So we have some additional instructions now that may be
    unnecessary, but that simplifies the code.

  - Validation: Switched to timespec64_valid() instead of our own
    check.

Fixes: 8043eccd232d ("cobalt/kernel: y2038: convert struct timespec to timespec64")
Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
 kernel/cobalt/posix/sem.c       | 37 +++++++++++++--------------------
 kernel/cobalt/posix/sem.h       |  6 ++----
 kernel/cobalt/posix/syscall32.c | 11 ++++++++--
 kernel/cobalt/posix/syscall32.h |  2 +-
 4 files changed, 26 insertions(+), 30 deletions(-)

diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
index 467a9b7dd..a0565e9f8 100644
--- a/kernel/cobalt/posix/sem.c
+++ b/kernel/cobalt/posix/sem.c
@@ -267,20 +267,11 @@ out:
 	return ret;
 }
 
-static inline int sem_fetch_timeout(struct timespec64 *ts,
-				    const void __user *u_ts)
-{
-	return u_ts == NULL ? -EFAULT :
-		cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
-}
-
 int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
-			   const void __user *u_ts,
-			   int (*fetch_timeout)(struct timespec64 *ts,
-						const void __user *u_ts))
+			   const struct timespec64 *ts)
 {
-	struct timespec64 ts = { .tv_sec = 0, .tv_nsec = 0 };
-	int pull_ts = 1, ret, info;
+	int ret, info;
+	bool validate_ts = true;
 	struct cobalt_sem *sem;
 	xnhandle_t handle;
 	xntmode_t tmode;
@@ -304,24 +295,19 @@ int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
 		 * it's actually more complex, to keep some
 		 * applications ported to Linux happy.
 		 */
-		if (pull_ts) {
+		if (validate_ts) {
 			atomic_inc(&sem->state->value);
-			xnlock_put_irqrestore(&nklock, s);
-			ret = fetch_timeout(&ts, u_ts);
-			xnlock_get_irqsave(&nklock, s);
-			if (ret)
-				break;
-			if (ts.tv_nsec >= ONE_BILLION) {
+			if (!timespec64_valid(ts)) {
 				ret = -EINVAL;
 				break;
 			}
-			pull_ts = 0;
+			validate_ts = false;
 			continue;
 		}
 
 		ret = 0;
 		tmode = sem->flags & SEM_RAWCLOCK ? XN_ABSOLUTE : XN_REALTIME;
-		info = xnsynch_sleep_on(&sem->synchbase, ts2ns(&ts) + 1, tmode);
+		info = xnsynch_sleep_on(&sem->synchbase, ts2ns(ts) + 1, tmode);
 		if (info & XNRMID)
 			ret = -EINVAL;
 		else if (info & (XNBREAK|XNTIMEO)) {
@@ -434,9 +420,14 @@ COBALT_SYSCALL(sem_wait, primary,
 
 COBALT_SYSCALL(sem_timedwait, primary,
 	       (struct cobalt_sem_shadow __user *u_sem,
-		struct __user_old_timespec __user *u_ts))
+		const struct __user_old_timespec __user *u_ts))
 {
-	return __cobalt_sem_timedwait(u_sem, u_ts, sem_fetch_timeout);
+	struct timespec64 ts64;
+
+	if (cobalt_get_u_timespec(&ts64, u_ts))
+		return -EFAULT;
+
+	return __cobalt_sem_timedwait(u_sem, &ts64);
 }
 
 COBALT_SYSCALL(sem_trywait, primary,
diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h
index d17299495..658e11f7a 100644
--- a/kernel/cobalt/posix/sem.h
+++ b/kernel/cobalt/posix/sem.h
@@ -64,9 +64,7 @@ __cobalt_sem_open(struct cobalt_sem_shadow __user *usm,
 		  int oflags, mode_t mode, unsigned int value);
 
 int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
-			   const void __user *u_ts,
-			   int (*fetch_timeout)(struct timespec64 *ts,
-						const void __user *u_ts));
+			   const struct timespec64 *ts);
 
 int __cobalt_sem_destroy(xnhandle_t handle);
 
@@ -91,7 +89,7 @@ COBALT_SYSCALL_DECL(sem_wait,
 
 COBALT_SYSCALL_DECL(sem_timedwait,
 		    (struct cobalt_sem_shadow __user *u_sem,
-		     struct __user_old_timespec __user *u_ts));
+		     const struct __user_old_timespec __user *u_ts));
 
 COBALT_SYSCALL_DECL(sem_trywait,
 		    (struct cobalt_sem_shadow __user *u_sem));
diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
index 57aa7251a..c2a2423ed 100644
--- a/kernel/cobalt/posix/syscall32.c
+++ b/kernel/cobalt/posix/syscall32.c
@@ -124,9 +124,16 @@ COBALT_SYSCALL32emu(sem_open, lostage,
 
 COBALT_SYSCALL32emu(sem_timedwait, primary,
 		    (struct cobalt_sem_shadow __user *u_sem,
-		     struct old_timespec32 __user *u_ts))
+		     const struct old_timespec32 __user *u_ts))
 {
-	return __cobalt_sem_timedwait(u_sem, u_ts, sys32_fetch_timeout);
+	int ret;
+	struct timespec64 ts64;
+
+	ret = sys32_fetch_timeout(&ts64, u_ts);
+	if (ret)
+		return ret;
+
+	return __cobalt_sem_timedwait(u_sem, &ts64);
 }
 
 COBALT_SYSCALL32emu(clock_getres, current,
diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h
index 66cd2a5d2..d72fd2022 100644
--- a/kernel/cobalt/posix/syscall32.h
+++ b/kernel/cobalt/posix/syscall32.h
@@ -229,6 +229,6 @@ COBALT_SYSCALL32emu_DECL(sem_open,
 
 COBALT_SYSCALL32emu_DECL(sem_timedwait,
 			 (struct cobalt_sem_shadow __user *u_sem,
-			  struct old_timespec32 __user *u_ts));
+			  const struct old_timespec32 __user *u_ts));
 
 #endif /* !_COBALT_POSIX_SYSCALL32_H */
-- 
2.29.2



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

* [y2038][RFC PATCH 2/2] y2038: Adding sem_timedwait_time64
  2021-03-04 11:36             ` [y2038][RFC PATCH 0/2] Pattern for implementing y2038 syscalls Florian Bezdeka
  2021-03-04 11:36               ` [y2038][RFC PATCH 1/2] y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
@ 2021-03-04 11:36               ` Florian Bezdeka
  2021-03-05  5:49                 ` chensong
  1 sibling, 1 reply; 57+ messages in thread
From: Florian Bezdeka @ 2021-03-04 11:36 UTC (permalink / raw)
  To: xenomai, jan.kiszka, rpm, chensong

Implementation is heavily inspired by the sem_timedwait syscall,
but expecting time64 based timespec / timeout.

We need two new syscall handlers:
  - The native one (COBALT_SYSCALL()) to get 32 bit kernels time64
    aware. This handler is added for 64 bit kernels as well, but not
    used. As we don't have separate syscall tables for this both
    worlds we have to add it.

 - The compat handler (COBALT_SYSCALL32emu()) for x32 or x86
   applications running on an x86_64 kernel. Otherwise the redirection
   to the compat / emulation syscalls is broken.

Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
 include/cobalt/uapi/syscall.h   |  1 +
 kernel/cobalt/posix/sem.c       | 12 ++++++++++++
 kernel/cobalt/posix/sem.h       |  4 ++++
 kernel/cobalt/posix/syscall32.c | 12 ++++++++++++
 kernel/cobalt/posix/syscall32.h |  4 ++++
 5 files changed, 33 insertions(+)

diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
index aa3c308d0..9b005da47 100644
--- a/include/cobalt/uapi/syscall.h
+++ b/include/cobalt/uapi/syscall.h
@@ -122,6 +122,7 @@
 #define sc_cobalt_sendmmsg			99
 #define sc_cobalt_clock_adjtime			100
 #define sc_cobalt_thread_setschedprio		101
+#define sc_cobalt_sem_timedwait_time64		102
 
 #define __NR_COBALT_SYSCALLS			128 /* Power of 2 */
 
diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
index a0565e9f8..a2211af36 100644
--- a/kernel/cobalt/posix/sem.c
+++ b/kernel/cobalt/posix/sem.c
@@ -430,6 +430,18 @@ COBALT_SYSCALL(sem_timedwait, primary,
 	return __cobalt_sem_timedwait(u_sem, &ts64);
 }
 
+COBALT_SYSCALL(sem_timedwait_time64, primary,
+	       (struct cobalt_sem_shadow __user *u_sem,
+		const struct __kernel_timespec __user *u_ts))
+{
+	struct timespec64 ts64;
+
+	if (get_timespec64(&ts64, u_ts))
+		return -EFAULT;
+
+	return __cobalt_sem_timedwait(u_sem, &ts64);
+}
+
 COBALT_SYSCALL(sem_trywait, primary,
 	       (struct cobalt_sem_shadow __user *u_sem))
 {
diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h
index 658e11f7a..8491b69ba 100644
--- a/kernel/cobalt/posix/sem.h
+++ b/kernel/cobalt/posix/sem.h
@@ -66,6 +66,10 @@ __cobalt_sem_open(struct cobalt_sem_shadow __user *usm,
 int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
 			   const struct timespec64 *ts);
 
+COBALT_SYSCALL_DECL(sem_timedwait_time64,
+		    (struct cobalt_sem_shadow __user *u_sem,
+		     const struct __kernel_timespec __user *u_ts));
+
 int __cobalt_sem_destroy(xnhandle_t handle);
 
 void cobalt_nsem_reclaim(struct cobalt_process *process);
diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
index c2a2423ed..d50532952 100644
--- a/kernel/cobalt/posix/syscall32.c
+++ b/kernel/cobalt/posix/syscall32.c
@@ -136,6 +136,18 @@ COBALT_SYSCALL32emu(sem_timedwait, primary,
 	return __cobalt_sem_timedwait(u_sem, &ts64);
 }
 
+COBALT_SYSCALL32emu(sem_timedwait_time64, primary,
+		    (struct cobalt_sem_shadow __user *u_sem,
+		     const struct __kernel_timespec __user *u_ts))
+{
+	struct timespec64 ts64;
+
+	if (get_timespec64(&ts64, u_ts))
+		return -EFAULT;
+
+	return __cobalt_sem_timedwait(u_sem, &ts64);
+}
+
 COBALT_SYSCALL32emu(clock_getres, current,
 		    (clockid_t clock_id,
 		     struct old_timespec32 __user *u_ts))
diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h
index d72fd2022..3612bf751 100644
--- a/kernel/cobalt/posix/syscall32.h
+++ b/kernel/cobalt/posix/syscall32.h
@@ -231,4 +231,8 @@ COBALT_SYSCALL32emu_DECL(sem_timedwait,
 			 (struct cobalt_sem_shadow __user *u_sem,
 			  const struct old_timespec32 __user *u_ts));
 
+COBALT_SYSCALL32emu_DECL(sem_timedwait_time64,
+			 (struct cobalt_sem_shadow __user * u_sem,
+			  const struct __kernel_timespec __user *u_ts));
+
 #endif /* !_COBALT_POSIX_SYSCALL32_H */
-- 
2.29.2



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

* Re: [y2038][RFC PATCH 1/2] y2038: Fixing the sem_timedwait syscall for 32 bit systems
  2021-03-04 11:36               ` [y2038][RFC PATCH 1/2] y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
@ 2021-03-04 15:11                 ` Philippe Gerum
  2021-03-04 15:22                   ` florian.bezdeka
  0 siblings, 1 reply; 57+ messages in thread
From: Philippe Gerum @ 2021-03-04 15:11 UTC (permalink / raw)
  To: Florian Bezdeka; +Cc: xenomai, jan.kiszka, chensong


Florian Bezdeka <florian.bezdeka@siemens.com> writes:

> On systems using 32 bit for time_t the sem_timedwait syscall was broken
> because the function used for copying the timeout value from userspace
> to kernel (=sem_fetch_timeout()) was always copying
> sizeof(struct timespec64).
>
> A 32 bit application (or more specific an application with 4 byte
> time_t) would only provide sizeof(struct old_timespec32).
>
> Notable changes:
>   - The copy operation from userspace to kernel is now already done in
>     the syscall handler. So it is always done. Previously it was copied
>     over and validated before the first use (when used at all).
>     So we have some additional instructions now that may be
>     unnecessary, but that simplifies the code.

Nack, there is a reason for this postponed copy of timespecs up to the
point where they are actually needed. This patch would break POSIX
compliance for some users. Please see the last sentence in the
Description of sem_timedwait()
https://pubs.opengroup.org/onlinepubs/009696699/functions/sem_timedwait.html

I agree that the standard says "need not be checked", not "must not be
checked" which may make this implementation-defined, but some test
suites Xenomai runs against do expect this to pass.

-- 
Philippe.


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

* Re: [y2038][RFC PATCH 1/2] y2038: Fixing the sem_timedwait syscall for 32 bit systems
  2021-03-04 15:11                 ` Philippe Gerum
@ 2021-03-04 15:22                   ` florian.bezdeka
  2021-03-04 15:42                     ` Philippe Gerum
  0 siblings, 1 reply; 57+ messages in thread
From: florian.bezdeka @ 2021-03-04 15:22 UTC (permalink / raw)
  To: rpm; +Cc: xenomai, jan.kiszka, chensong

On Thu, 2021-03-04 at 16:11 +0100, Philippe Gerum wrote:
> Florian Bezdeka <florian.bezdeka@siemens.com> writes:
> 
> > On systems using 32 bit for time_t the sem_timedwait syscall was broken
> > because the function used for copying the timeout value from userspace
> > to kernel (=sem_fetch_timeout()) was always copying
> > sizeof(struct timespec64).
> > 
> > A 32 bit application (or more specific an application with 4 byte
> > time_t) would only provide sizeof(struct old_timespec32).
> > 
> > Notable changes:
> >   - The copy operation from userspace to kernel is now already done in
> >     the syscall handler. So it is always done. Previously it was copied
> >     over and validated before the first use (when used at all).
> >     So we have some additional instructions now that may be
> >     unnecessary, but that simplifies the code.
> 
> Nack, there is a reason for this postponed copy of timespecs up to the
> point where they are actually needed. This patch would break POSIX
> compliance for some users. Please see the last sentence in the
> Description of sem_timedwait()
> https://pubs.opengroup.org/onlinepubs/009696699/functions/sem_timedwait.html

I can't find any comment regarding the point in time where we copy this
timespec to the kernel space. For the time of validation see below.
Could you point me to the failing tests or some more documentation?

> 
> I agree that the standard says "need not be checked", not "must not be
> checked" which may make this implementation-defined, but some test
> suites Xenomai runs against do expect this to pass.
> 

The validation did not change. It's done right before the first usage.
So if not needed (because sem could be taken without timeout) there is
still no validation.

Thanks for your feedback, Philippe!


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

* Re: [y2038][RFC PATCH 1/2] y2038: Fixing the sem_timedwait syscall for 32 bit systems
  2021-03-04 15:22                   ` florian.bezdeka
@ 2021-03-04 15:42                     ` Philippe Gerum
  2021-03-08 17:02                       ` [RFC PATCH v2 0/4] Pattern for implementing y2038 syscalls Florian Bezdeka
  0 siblings, 1 reply; 57+ messages in thread
From: Philippe Gerum @ 2021-03-04 15:42 UTC (permalink / raw)
  To: florian.bezdeka; +Cc: xenomai, jan.kiszka, chensong


florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:

> On Thu, 2021-03-04 at 16:11 +0100, Philippe Gerum wrote:
>> Florian Bezdeka <florian.bezdeka@siemens.com> writes:
>> 
>> > On systems using 32 bit for time_t the sem_timedwait syscall was broken
>> > because the function used for copying the timeout value from userspace
>> > to kernel (=sem_fetch_timeout()) was always copying
>> > sizeof(struct timespec64).
>> > 
>> > A 32 bit application (or more specific an application with 4 byte
>> > time_t) would only provide sizeof(struct old_timespec32).
>> > 
>> > Notable changes:
>> >   - The copy operation from userspace to kernel is now already done in
>> >     the syscall handler. So it is always done. Previously it was copied
>> >     over and validated before the first use (when used at all).
>> >     So we have some additional instructions now that may be
>> >     unnecessary, but that simplifies the code.
>> 
>> Nack, there is a reason for this postponed copy of timespecs up to the
>> point where they are actually needed. This patch would break POSIX
>> compliance for some users. Please see the last sentence in the
>> Description of sem_timedwait()
>> https://pubs.opengroup.org/onlinepubs/009696699/functions/sem_timedwait.html
>
> I can't find any comment regarding the point in time where we copy this
> timespec to the kernel space. For the time of validation see below.
> Could you point me to the failing tests or some more documentation?
>

Assuming single thread, doing that in sequence:

sem_t foo;

sem_init(&foo, 0, 0);
sem_post(&foo);
sem_timedwait(&foo, NULL); /* <= should be ok, because we surely won't block */

Disclaimer: I do find this fairly weird as well, but the privilege of
any standard is to do weird things pretending this is the sane way.

>> 
>> I agree that the standard says "need not be checked", not "must not be
>> checked" which may make this implementation-defined, but some test
>> suites Xenomai runs against do expect this to pass.
>> 
>
> The validation did not change. It's done right before the first usage.
> So if not needed (because sem could be taken without timeout) there is
> still no validation.
>
> Thanks for your feedback, Philippe!

The short log of the patch says that the copy of timespec is always done
from user->kernel, which is the issue I'm referring to. Whether the data
copied is sane is a different aspect.

-- 
Philippe.


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

* Re: [y2038][RFC PATCH 2/2] y2038: Adding sem_timedwait_time64
  2021-03-04 11:36               ` [y2038][RFC PATCH 2/2] y2038: Adding sem_timedwait_time64 Florian Bezdeka
@ 2021-03-05  5:49                 ` chensong
  2021-03-05  6:36                   ` florian.bezdeka
  0 siblings, 1 reply; 57+ messages in thread
From: chensong @ 2021-03-05  5:49 UTC (permalink / raw)
  To: Florian Bezdeka, xenomai, jan.kiszka, rpm, chensong



On 2021年03月04日 19:36, Florian Bezdeka via Xenomai wrote:
> Implementation is heavily inspired by the sem_timedwait syscall,
> but expecting time64 based timespec / timeout.
>
> We need two new syscall handlers:
>    - The native one (COBALT_SYSCALL()) to get 32 bit kernels time64
>      aware. This handler is added for 64 bit kernels as well, but not
>      used. As we don't have separate syscall tables for this both
>      worlds we have to add it.
>
>   - The compat handler (COBALT_SYSCALL32emu()) for x32 or x86
>     applications running on an x86_64 kernel. Otherwise the redirection
>     to the compat / emulation syscalls is broken.
>
> Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
> ---
>   include/cobalt/uapi/syscall.h   |  1 +
>   kernel/cobalt/posix/sem.c       | 12 ++++++++++++
>   kernel/cobalt/posix/sem.h       |  4 ++++
>   kernel/cobalt/posix/syscall32.c | 12 ++++++++++++
>   kernel/cobalt/posix/syscall32.h |  4 ++++
>   5 files changed, 33 insertions(+)
>
> diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
> index aa3c308d0..9b005da47 100644
> --- a/include/cobalt/uapi/syscall.h
> +++ b/include/cobalt/uapi/syscall.h
> @@ -122,6 +122,7 @@
>   #define sc_cobalt_sendmmsg			99
>   #define sc_cobalt_clock_adjtime			100
>   #define sc_cobalt_thread_setschedprio		101
> +#define sc_cobalt_sem_timedwait_time64		102
>
>   #define __NR_COBALT_SYSCALLS			128 /* Power of 2 */
>
> diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
> index a0565e9f8..a2211af36 100644
> --- a/kernel/cobalt/posix/sem.c
> +++ b/kernel/cobalt/posix/sem.c
> @@ -430,6 +430,18 @@ COBALT_SYSCALL(sem_timedwait, primary,
>   	return __cobalt_sem_timedwait(u_sem, &ts64);
>   }
>
> +COBALT_SYSCALL(sem_timedwait_time64, primary,
> +	       (struct cobalt_sem_shadow __user *u_sem,
> +		const struct __kernel_timespec __user *u_ts))
> +{
> +	struct timespec64 ts64;
> +
> +	if (get_timespec64(&ts64, u_ts))

get_timespec64 didn't exist until kernel 4.13, shall we take care of this?
get_timespec64 uses copy_from_user, is  there any side effect?

> +		return -EFAULT;
> +
> +	return __cobalt_sem_timedwait(u_sem, &ts64);
> +}
> +
>   COBALT_SYSCALL(sem_trywait, primary,
>   	       (struct cobalt_sem_shadow __user *u_sem))
>   {
> diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h
> index 658e11f7a..8491b69ba 100644
> --- a/kernel/cobalt/posix/sem.h
> +++ b/kernel/cobalt/posix/sem.h
> @@ -66,6 +66,10 @@ __cobalt_sem_open(struct cobalt_sem_shadow __user *usm,
>   int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
>   			   const struct timespec64 *ts);
>
> +COBALT_SYSCALL_DECL(sem_timedwait_time64,
> +		    (struct cobalt_sem_shadow __user *u_sem,
> +		     const struct __kernel_timespec __user *u_ts));
> +
>   int __cobalt_sem_destroy(xnhandle_t handle);
>
>   void cobalt_nsem_reclaim(struct cobalt_process *process);
> diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
> index c2a2423ed..d50532952 100644
> --- a/kernel/cobalt/posix/syscall32.c
> +++ b/kernel/cobalt/posix/syscall32.c
> @@ -136,6 +136,18 @@ COBALT_SYSCALL32emu(sem_timedwait, primary,
>   	return __cobalt_sem_timedwait(u_sem, &ts64);
>   }
>
> +COBALT_SYSCALL32emu(sem_timedwait_time64, primary,
> +		    (struct cobalt_sem_shadow __user *u_sem,
> +		     const struct __kernel_timespec __user *u_ts))
> +{
> +	struct timespec64 ts64;
> +
> +	if (get_timespec64(&ts64, u_ts))
> +		return -EFAULT;
> +
> +	return __cobalt_sem_timedwait(u_sem, &ts64);
> +}
> +
>   COBALT_SYSCALL32emu(clock_getres, current,
>   		    (clockid_t clock_id,
>   		     struct old_timespec32 __user *u_ts))
> diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h
> index d72fd2022..3612bf751 100644
> --- a/kernel/cobalt/posix/syscall32.h
> +++ b/kernel/cobalt/posix/syscall32.h
> @@ -231,4 +231,8 @@ COBALT_SYSCALL32emu_DECL(sem_timedwait,
>   			 (struct cobalt_sem_shadow __user *u_sem,
>   			  const struct old_timespec32 __user *u_ts));
>
> +COBALT_SYSCALL32emu_DECL(sem_timedwait_time64,
> +			 (struct cobalt_sem_shadow __user * u_sem,
> +			  const struct __kernel_timespec __user *u_ts));
> +
>   #endif /* !_COBALT_POSIX_SYSCALL32_H */
>




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

* Re: [y2038][RFC PATCH 2/2] y2038: Adding sem_timedwait_time64
  2021-03-05  5:49                 ` chensong
@ 2021-03-05  6:36                   ` florian.bezdeka
  2021-03-05  7:42                     ` chensong
  0 siblings, 1 reply; 57+ messages in thread
From: florian.bezdeka @ 2021-03-05  6:36 UTC (permalink / raw)
  To: chensong; +Cc: rpm, xenomai, jan.kiszka, chensong

On Fri, 2021-03-05 at 13:49 +0800, chensong wrote:
> 
> On 2021年03月04日 19:36, Florian Bezdeka via Xenomai wrote:
> > Implementation is heavily inspired by the sem_timedwait syscall,
> > but expecting time64 based timespec / timeout.
> > 
> > We need two new syscall handlers:
> >    - The native one (COBALT_SYSCALL()) to get 32 bit kernels time64
> >      aware. This handler is added for 64 bit kernels as well, but not
> >      used. As we don't have separate syscall tables for this both
> >      worlds we have to add it.
> > 
> >   - The compat handler (COBALT_SYSCALL32emu()) for x32 or x86
> >     applications running on an x86_64 kernel. Otherwise the redirection
> >     to the compat / emulation syscalls is broken.
> > 
> > Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
> > ---
> >   include/cobalt/uapi/syscall.h   |  1 +
> >   kernel/cobalt/posix/sem.c       | 12 ++++++++++++
> >   kernel/cobalt/posix/sem.h       |  4 ++++
> >   kernel/cobalt/posix/syscall32.c | 12 ++++++++++++
> >   kernel/cobalt/posix/syscall32.h |  4 ++++
> >   5 files changed, 33 insertions(+)
> > 
> > diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
> > index aa3c308d0..9b005da47 100644
> > --- a/include/cobalt/uapi/syscall.h
> > +++ b/include/cobalt/uapi/syscall.h
> > @@ -122,6 +122,7 @@
> >   #define sc_cobalt_sendmmsg			99
> >   #define sc_cobalt_clock_adjtime			100
> >   #define sc_cobalt_thread_setschedprio		101
> > +#define sc_cobalt_sem_timedwait_time64		102
> > 
> >   #define __NR_COBALT_SYSCALLS			128 /* Power of 2 */
> > 
> > diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
> > index a0565e9f8..a2211af36 100644
> > --- a/kernel/cobalt/posix/sem.c
> > +++ b/kernel/cobalt/posix/sem.c
> > @@ -430,6 +430,18 @@ COBALT_SYSCALL(sem_timedwait, primary,
> >   	return __cobalt_sem_timedwait(u_sem, &ts64);
> >   }
> > 
> > +COBALT_SYSCALL(sem_timedwait_time64, primary,
> > +	       (struct cobalt_sem_shadow __user *u_sem,
> > +		const struct __kernel_timespec __user *u_ts))
> > +{
> > +	struct timespec64 ts64;
> > +
> > +	if (get_timespec64(&ts64, u_ts))
> 
> get_timespec64 didn't exist until kernel 4.13, shall we take care of this?
> get_timespec64 uses copy_from_user, is  there any side effect?

Yes and yes. I already noticed it but did not send out v2 due to some
other this I have to address first. Still trying to find a way that
allows us to prevent duplication all the necessary helpers...

> 
> > +		return -EFAULT;
> > +
> > +	return __cobalt_sem_timedwait(u_sem, &ts64);
> > +}
> > +
> >   COBALT_SYSCALL(sem_trywait, primary,
> >   	       (struct cobalt_sem_shadow __user *u_sem))
> >   {
> > diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h
> > index 658e11f7a..8491b69ba 100644
> > --- a/kernel/cobalt/posix/sem.h
> > +++ b/kernel/cobalt/posix/sem.h
> > @@ -66,6 +66,10 @@ __cobalt_sem_open(struct cobalt_sem_shadow __user *usm,
> >   int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
> >   			   const struct timespec64 *ts);
> > 
> > +COBALT_SYSCALL_DECL(sem_timedwait_time64,
> > +		    (struct cobalt_sem_shadow __user *u_sem,
> > +		     const struct __kernel_timespec __user *u_ts));
> > +
> >   int __cobalt_sem_destroy(xnhandle_t handle);
> > 
> >   void cobalt_nsem_reclaim(struct cobalt_process *process);
> > diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
> > index c2a2423ed..d50532952 100644
> > --- a/kernel/cobalt/posix/syscall32.c
> > +++ b/kernel/cobalt/posix/syscall32.c
> > @@ -136,6 +136,18 @@ COBALT_SYSCALL32emu(sem_timedwait, primary,
> >   	return __cobalt_sem_timedwait(u_sem, &ts64);
> >   }
> > 
> > +COBALT_SYSCALL32emu(sem_timedwait_time64, primary,
> > +		    (struct cobalt_sem_shadow __user *u_sem,
> > +		     const struct __kernel_timespec __user *u_ts))
> > +{
> > +	struct timespec64 ts64;
> > +
> > +	if (get_timespec64(&ts64, u_ts))
> > +		return -EFAULT;
> > +
> > +	return __cobalt_sem_timedwait(u_sem, &ts64);
> > +}
> > +
> >   COBALT_SYSCALL32emu(clock_getres, current,
> >   		    (clockid_t clock_id,
> >   		     struct old_timespec32 __user *u_ts))
> > diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h
> > index d72fd2022..3612bf751 100644
> > --- a/kernel/cobalt/posix/syscall32.h
> > +++ b/kernel/cobalt/posix/syscall32.h
> > @@ -231,4 +231,8 @@ COBALT_SYSCALL32emu_DECL(sem_timedwait,
> >   			 (struct cobalt_sem_shadow __user *u_sem,
> >   			  const struct old_timespec32 __user *u_ts));
> > 
> > +COBALT_SYSCALL32emu_DECL(sem_timedwait_time64,
> > +			 (struct cobalt_sem_shadow __user * u_sem,
> > +			  const struct __kernel_timespec __user *u_ts));
> > +
> >   #endif /* !_COBALT_POSIX_SYSCALL32_H */
> > 
> 
> 


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

* Re: [y2038][RFC PATCH 2/2] y2038: Adding sem_timedwait_time64
  2021-03-05  6:36                   ` florian.bezdeka
@ 2021-03-05  7:42                     ` chensong
  2021-03-05  7:53                       ` florian.bezdeka
  0 siblings, 1 reply; 57+ messages in thread
From: chensong @ 2021-03-05  7:42 UTC (permalink / raw)
  To: florian.bezdeka; +Cc: rpm, xenomai, jan.kiszka, chensong



On 2021年03月05日 14:36, florian.bezdeka@siemens.com wrote:
> On Fri, 2021-03-05 at 13:49 +0800, chensong wrote:
>>
>> On 2021年03月04日 19:36, Florian Bezdeka via Xenomai wrote:
>>> Implementation is heavily inspired by the sem_timedwait syscall,
>>> but expecting time64 based timespec / timeout.
>>>
>>> We need two new syscall handlers:
>>>     - The native one (COBALT_SYSCALL()) to get 32 bit kernels time64
>>>       aware. This handler is added for 64 bit kernels as well, but not
>>>       used. As we don't have separate syscall tables for this both
>>>       worlds we have to add it.
>>>
>>>    - The compat handler (COBALT_SYSCALL32emu()) for x32 or x86
>>>      applications running on an x86_64 kernel. Otherwise the redirection
>>>      to the compat / emulation syscalls is broken.
>>>
>>> Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
>>> ---
>>>    include/cobalt/uapi/syscall.h   |  1 +
>>>    kernel/cobalt/posix/sem.c       | 12 ++++++++++++
>>>    kernel/cobalt/posix/sem.h       |  4 ++++
>>>    kernel/cobalt/posix/syscall32.c | 12 ++++++++++++
>>>    kernel/cobalt/posix/syscall32.h |  4 ++++
>>>    5 files changed, 33 insertions(+)
>>>
>>> diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
>>> index aa3c308d0..9b005da47 100644
>>> --- a/include/cobalt/uapi/syscall.h
>>> +++ b/include/cobalt/uapi/syscall.h
>>> @@ -122,6 +122,7 @@
>>>    #define sc_cobalt_sendmmsg			99
>>>    #define sc_cobalt_clock_adjtime			100
>>>    #define sc_cobalt_thread_setschedprio		101
>>> +#define sc_cobalt_sem_timedwait_time64		102
>>>
>>>    #define __NR_COBALT_SYSCALLS			128 /* Power of 2 */
>>>
>>> diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
>>> index a0565e9f8..a2211af36 100644
>>> --- a/kernel/cobalt/posix/sem.c
>>> +++ b/kernel/cobalt/posix/sem.c
>>> @@ -430,6 +430,18 @@ COBALT_SYSCALL(sem_timedwait, primary,
>>>    	return __cobalt_sem_timedwait(u_sem, &ts64);
>>>    }
>>>
>>> +COBALT_SYSCALL(sem_timedwait_time64, primary,
>>> +	       (struct cobalt_sem_shadow __user *u_sem,
>>> +		const struct __kernel_timespec __user *u_ts))
>>> +{
>>> +	struct timespec64 ts64;
>>> +
>>> +	if (get_timespec64(&ts64, u_ts))
>>
>> get_timespec64 didn't exist until kernel 4.13, shall we take care of this?
>> get_timespec64 uses copy_from_user, is  there any side effect?
>
> Yes and yes. I already noticed it but did not send out v2 due to some
> other this I have to address first. Still trying to find a way that
> allows us to prevent duplication all the necessary helpers...

Or we don't use helpers, like this
struct __kernel_timespec kts;
struct timespec64 ts64;

cobalt_copy_from_user(&kts, u_ts, sizeof(kts));

ts64.tv_sec = kts.tv_sec;

i'm working on clock.c, and will submit patches, please review.


>
>>
>>> +		return -EFAULT;
>>> +
>>> +	return __cobalt_sem_timedwait(u_sem, &ts64);
>>> +}
>>> +
>>>    COBALT_SYSCALL(sem_trywait, primary,
>>>    	       (struct cobalt_sem_shadow __user *u_sem))
>>>    {
>>> diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h
>>> index 658e11f7a..8491b69ba 100644
>>> --- a/kernel/cobalt/posix/sem.h
>>> +++ b/kernel/cobalt/posix/sem.h
>>> @@ -66,6 +66,10 @@ __cobalt_sem_open(struct cobalt_sem_shadow __user *usm,
>>>    int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
>>>    			   const struct timespec64 *ts);
>>>
>>> +COBALT_SYSCALL_DECL(sem_timedwait_time64,
>>> +		    (struct cobalt_sem_shadow __user *u_sem,
>>> +		     const struct __kernel_timespec __user *u_ts));
>>> +
>>>    int __cobalt_sem_destroy(xnhandle_t handle);
>>>
>>>    void cobalt_nsem_reclaim(struct cobalt_process *process);
>>> diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
>>> index c2a2423ed..d50532952 100644
>>> --- a/kernel/cobalt/posix/syscall32.c
>>> +++ b/kernel/cobalt/posix/syscall32.c
>>> @@ -136,6 +136,18 @@ COBALT_SYSCALL32emu(sem_timedwait, primary,
>>>    	return __cobalt_sem_timedwait(u_sem, &ts64);
>>>    }
>>>
>>> +COBALT_SYSCALL32emu(sem_timedwait_time64, primary,
>>> +		    (struct cobalt_sem_shadow __user *u_sem,
>>> +		     const struct __kernel_timespec __user *u_ts))
>>> +{
>>> +	struct timespec64 ts64;
>>> +
>>> +	if (get_timespec64(&ts64, u_ts))
>>> +		return -EFAULT;
>>> +
>>> +	return __cobalt_sem_timedwait(u_sem, &ts64);
>>> +}
>>> +
>>>    COBALT_SYSCALL32emu(clock_getres, current,
>>>    		    (clockid_t clock_id,
>>>    		     struct old_timespec32 __user *u_ts))
>>> diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h
>>> index d72fd2022..3612bf751 100644
>>> --- a/kernel/cobalt/posix/syscall32.h
>>> +++ b/kernel/cobalt/posix/syscall32.h
>>> @@ -231,4 +231,8 @@ COBALT_SYSCALL32emu_DECL(sem_timedwait,
>>>    			 (struct cobalt_sem_shadow __user *u_sem,
>>>    			  const struct old_timespec32 __user *u_ts));
>>>
>>> +COBALT_SYSCALL32emu_DECL(sem_timedwait_time64,
>>> +			 (struct cobalt_sem_shadow __user * u_sem,
>>> +			  const struct __kernel_timespec __user *u_ts));
>>> +
>>>    #endif /* !_COBALT_POSIX_SYSCALL32_H */
>>>
>>
>>
>




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

* Re: [y2038][RFC PATCH 2/2] y2038: Adding sem_timedwait_time64
  2021-03-05  7:42                     ` chensong
@ 2021-03-05  7:53                       ` florian.bezdeka
  0 siblings, 0 replies; 57+ messages in thread
From: florian.bezdeka @ 2021-03-05  7:53 UTC (permalink / raw)
  To: chensong; +Cc: rpm, xenomai, jan.kiszka, chensong

On Fri, 2021-03-05 at 15:42 +0800, chensong wrote:
> 
> > > > 
> > > > +COBALT_SYSCALL(sem_timedwait_time64, primary,
> > > > +	       (struct cobalt_sem_shadow __user *u_sem,
> > > > +		const struct __kernel_timespec __user *u_ts))
> > > > +{
> > > > +	struct timespec64 ts64;
> > > > +
> > > > +	if (get_timespec64(&ts64, u_ts))
> > > 
> > > get_timespec64 didn't exist until kernel 4.13, shall we take care of this?
> > > get_timespec64 uses copy_from_user, is  there any side effect?
> > 
> > Yes and yes. I already noticed it but did not send out v2 due to some
> > other this I have to address first. Still trying to find a way that
> > allows us to prevent duplication all the necessary helpers...
> 
> Or we don't use helpers, like this
> struct __kernel_timespec kts;
> struct timespec64 ts64;
> 
> cobalt_copy_from_user(&kts, u_ts, sizeof(kts));
> 
> ts64.tv_sec = kts.tv_sec;
> 
> i'm working on clock.c, and will submit patches, please review.

This is not correct in case of a compat syscall. We have different
padding between kernel and application which needs to be addressed.
That can be done nicely in a helper which can check the context it is
being called in. (See get_timespec64() of a kernel that has it)

As you pointed out we can not use get_timespec64() as is, we need a
cobalt version of it.

Please wait for v2, you will see...


> 

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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-02-22  9:08         ` Philippe Gerum
@ 2021-03-08 12:19           ` Jan Kiszka
  2021-03-08 14:01             ` Philippe Gerum
  0 siblings, 1 reply; 57+ messages in thread
From: Jan Kiszka @ 2021-03-08 12:19 UTC (permalink / raw)
  To: Philippe Gerum, florian.bezdeka; +Cc: xenomai

On 22.02.21 10:08, Philippe Gerum via Xenomai wrote:
> 
> florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:
> 
>> On Sun, 2021-02-21 at 16:27 +0100, Philippe Gerum via Xenomai wrote:
>>> chensong via Xenomai <xenomai@xenomai.org> writes:
>>>
>>>>> +/*
>>>>> + * Our representation of time at the kernel<->user interface boundary
>>>>> + * at the moment, until we have fully transitioned to a y2038-safe
>>>>> + * implementation in libcobalt.
>>>>> + */
>>>>> +struct __user_old_timespec {
>>>>> +	long  tv_sec;
>>>>> +	long  tv_nsec;
>>>>> +};
>>>>
>>>> why not use old_timespec32, which is timespec32 representation defined
>>>> in include/linux/time32?
>>>>
>>>
>>> Using old_timespec32 in this context would mean that any time value
>>> received from userland by the core should be restricted to 32bit time_t,
>>> which is not what we want, at least for 64bit platforms:
>>>
>>> include/vdso/time32.h:
>>>
>>> struct old_timespec32 {
>>> 	old_time32_t	tv_sec;
>>> 	s32		tv_nsec;
>>> };
>>>
>>> __user_old_timespec conveys the notion that we are generically talking
>>> about "the old timespec type which has a y2038 problem"; this is not
>>> specifically about the legacy timespec type on 32bit machines.
>>>
>>> Since v5.4-rc6, we do have __kernel_old_timespec though, which could
>>> have been used instead of __user_old_timespec:
>>
>> According to my information (based on
>> https://elixir.bootlin.com/linux/v5.5-rc1/A/ident/__kernel_old_timespec
>> ) this is available since v5.5-rc1.
>>
> 
> This disagrees with the git history then:
> 
> commit 94c467ddb273dc9a6a4fb09aef392c119b151edb
> Author: Arnd Bergmann <arnd@arndb.de>
> 
>     y2038: add __kernel_old_timespec and __kernel_old_time_t
> 
> $ git describe 94c467ddb273dc9a6a4fb09aef392c119b151edb
> v5.4-rc6-2-g94c467ddb273dc9
> 

This tells you *after* which tag it was applied, not when it was in and
tagged there. That was indeed v5.5-rc1 (seen via gitk, still looking for
a handy git command line to explore that).

Jan

-- 
Siemens AG, T RDA IOT
Corporate Competence Center Embedded Linux


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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-03-04 10:08           ` Philippe Gerum
  2021-03-04 11:36             ` [y2038][RFC PATCH 0/2] Pattern for implementing y2038 syscalls Florian Bezdeka
@ 2021-03-08 12:59             ` Jan Kiszka
  2021-03-10 17:52             ` florian.bezdeka
  2 siblings, 0 replies; 57+ messages in thread
From: Jan Kiszka @ 2021-03-08 12:59 UTC (permalink / raw)
  To: Philippe Gerum, florian.bezdeka; +Cc: xenomai, chensong

On 04.03.21 11:08, Philippe Gerum wrote:
> 
> Philippe Gerum <rpm@xenomai.org> writes:
> 
>> florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:
>>
>>> On Thu, 2021-03-04 at 10:35 +0100, Philippe Gerum wrote:
>>>> florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:
>>>>
>>>>> On Sat, 2021-02-20 at 16:18 +0100, Philippe Gerum via Xenomai wrote:
>>>>> [snip]
>>>>>> diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
>>>>>> index 05a861dfe..467a9b7dd 100644
>>>>>> --- a/kernel/cobalt/posix/sem.c
>>>>>> +++ b/kernel/cobalt/posix/sem.c
>>>>>> @@ -267,7 +267,7 @@ out:
>>>>>>  	return ret;
>>>>>>  }
>>>>>>  
>>>>>>
>>>>>>
>>>>>>
>>>>>> -static inline int sem_fetch_timeout(struct timespec *ts,
>>>>>> +static inline int sem_fetch_timeout(struct timespec64 *ts,
>>>>>>  				    const void __user *u_ts)
>>>>>
>>>>> Handle the following with care, maybe my understanding of
>>>>> CONFIG_XENO_ARCH_SYS3264 is wrong. See below...
>>>>>
>>>>> My understanding is that this is a breaking change for 32 bit kernels.
>>>>> The broken part is hidden here, but sem_fetch_timeout() now assumes
>>>>> that the user provided timespec64, which is not be the case for 32 bit
>>>>> applications running on a 32 bit kernel.
>>>>>
>>>>
>>>> The user-provided memory is referred to by u_ts, not ts, which receives
>>>> the timestamp fetch_timeout() is supposed to return. The change should
>>>> only affect the return type, not the source one. sys32_fetch_timeout()
>>>> should still do the right thing via sys32_get_timespec().
>>>
>>> Adding the full code:
>>>
>>> static inline int sem_fetch_timeout(struct timespec64 *ts,
>>> 				    const void __user *u_ts)
>>> {
>>> 	return u_ts == NULL ? -EFAULT :
>>> 		cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
>>> }
>>>
>>> Copying sizeof(*ts) is to much if the application provided
>>> "__old_time_t" (sizeof(time_t) =4) only. Isn't it? I would expect the
>>> result (in ts) to be garbage. Due to different padding the "sec" field
>>> (in ts) would now contain the nsec value from u_ts as well.
>>>
>>
>> Ah, I was looking at the wrong path (32emu). Yes, this is broken for
>> mere 32bit now (i.e. natively 32bit platform).
> 
> We could simply use cobalt_get_u_timespec() instead of open coding the
> call to cobalt_copy_from_user(). Condvars have this right already,
> mutex, mq and sema4s have their fetch_timeout() helper broken
> indeed. Good spot.
> 

Oops, missed this. Patch is in next (all 5, in fact, and all built
find), but I will revert things back to patch 1 only.

Jan

-- 
Siemens AG, T RDA IOT
Corporate Competence Center Embedded Linux


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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-03-08 12:19           ` Jan Kiszka
@ 2021-03-08 14:01             ` Philippe Gerum
  2021-03-08 14:03               ` Jan Kiszka
  0 siblings, 1 reply; 57+ messages in thread
From: Philippe Gerum @ 2021-03-08 14:01 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: florian.bezdeka, xenomai


Jan Kiszka <jan.kiszka@siemens.com> writes:

> On 22.02.21 10:08, Philippe Gerum via Xenomai wrote:
>> 
>> florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:
>> 
>>> On Sun, 2021-02-21 at 16:27 +0100, Philippe Gerum via Xenomai wrote:
>>>> chensong via Xenomai <xenomai@xenomai.org> writes:
>>>>
>>>>>> +/*
>>>>>> + * Our representation of time at the kernel<->user interface boundary
>>>>>> + * at the moment, until we have fully transitioned to a y2038-safe
>>>>>> + * implementation in libcobalt.
>>>>>> + */
>>>>>> +struct __user_old_timespec {
>>>>>> +	long  tv_sec;
>>>>>> +	long  tv_nsec;
>>>>>> +};
>>>>>
>>>>> why not use old_timespec32, which is timespec32 representation defined
>>>>> in include/linux/time32?
>>>>>
>>>>
>>>> Using old_timespec32 in this context would mean that any time value
>>>> received from userland by the core should be restricted to 32bit time_t,
>>>> which is not what we want, at least for 64bit platforms:
>>>>
>>>> include/vdso/time32.h:
>>>>
>>>> struct old_timespec32 {
>>>> 	old_time32_t	tv_sec;
>>>> 	s32		tv_nsec;
>>>> };
>>>>
>>>> __user_old_timespec conveys the notion that we are generically talking
>>>> about "the old timespec type which has a y2038 problem"; this is not
>>>> specifically about the legacy timespec type on 32bit machines.
>>>>
>>>> Since v5.4-rc6, we do have __kernel_old_timespec though, which could
>>>> have been used instead of __user_old_timespec:
>>>
>>> According to my information (based on
>>> https://elixir.bootlin.com/linux/v5.5-rc1/A/ident/__kernel_old_timespec
>>> ) this is available since v5.5-rc1.
>>>
>> 
>> This disagrees with the git history then:
>> 
>> commit 94c467ddb273dc9a6a4fb09aef392c119b151edb
>> Author: Arnd Bergmann <arnd@arndb.de>
>> 
>>     y2038: add __kernel_old_timespec and __kernel_old_time_t
>> 
>> $ git describe 94c467ddb273dc9a6a4fb09aef392c119b151edb
>> v5.4-rc6-2-g94c467ddb273dc9
>> 
>
> This tells you *after* which tag it was applied, not when it was in and
> tagged there.

That's right. My mistake.

> That was indeed v5.5-rc1 (seen via gitk, still looking for
> a handy git command line to explore that).
>

$ git describe --contains

-- 
Philippe.


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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-03-08 14:01             ` Philippe Gerum
@ 2021-03-08 14:03               ` Jan Kiszka
  0 siblings, 0 replies; 57+ messages in thread
From: Jan Kiszka @ 2021-03-08 14:03 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: florian.bezdeka, xenomai

On 08.03.21 15:01, Philippe Gerum wrote:
> 
> Jan Kiszka <jan.kiszka@siemens.com> writes:
> 
>> On 22.02.21 10:08, Philippe Gerum via Xenomai wrote:
>>>
>>> florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:
>>>
>>>> On Sun, 2021-02-21 at 16:27 +0100, Philippe Gerum via Xenomai wrote:
>>>>> chensong via Xenomai <xenomai@xenomai.org> writes:
>>>>>
>>>>>>> +/*
>>>>>>> + * Our representation of time at the kernel<->user interface boundary
>>>>>>> + * at the moment, until we have fully transitioned to a y2038-safe
>>>>>>> + * implementation in libcobalt.
>>>>>>> + */
>>>>>>> +struct __user_old_timespec {
>>>>>>> +	long  tv_sec;
>>>>>>> +	long  tv_nsec;
>>>>>>> +};
>>>>>>
>>>>>> why not use old_timespec32, which is timespec32 representation defined
>>>>>> in include/linux/time32?
>>>>>>
>>>>>
>>>>> Using old_timespec32 in this context would mean that any time value
>>>>> received from userland by the core should be restricted to 32bit time_t,
>>>>> which is not what we want, at least for 64bit platforms:
>>>>>
>>>>> include/vdso/time32.h:
>>>>>
>>>>> struct old_timespec32 {
>>>>> 	old_time32_t	tv_sec;
>>>>> 	s32		tv_nsec;
>>>>> };
>>>>>
>>>>> __user_old_timespec conveys the notion that we are generically talking
>>>>> about "the old timespec type which has a y2038 problem"; this is not
>>>>> specifically about the legacy timespec type on 32bit machines.
>>>>>
>>>>> Since v5.4-rc6, we do have __kernel_old_timespec though, which could
>>>>> have been used instead of __user_old_timespec:
>>>>
>>>> According to my information (based on
>>>> https://elixir.bootlin.com/linux/v5.5-rc1/A/ident/__kernel_old_timespec
>>>> ) this is available since v5.5-rc1.
>>>>
>>>
>>> This disagrees with the git history then:
>>>
>>> commit 94c467ddb273dc9a6a4fb09aef392c119b151edb
>>> Author: Arnd Bergmann <arnd@arndb.de>
>>>
>>>     y2038: add __kernel_old_timespec and __kernel_old_time_t
>>>
>>> $ git describe 94c467ddb273dc9a6a4fb09aef392c119b151edb
>>> v5.4-rc6-2-g94c467ddb273dc9
>>>
>>
>> This tells you *after* which tag it was applied, not when it was in and
>> tagged there.
> 
> That's right. My mistake.
> 
>> That was indeed v5.5-rc1 (seen via gitk, still looking for
>> a handy git command line to explore that).
>>
> 
> $ git describe --contains
> 

Ah, that is worth to remember!

Thanks,
Jan

-- 
Siemens AG, T RDA IOT
Corporate Competence Center Embedded Linux


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

* [RFC PATCH v2 0/4] Pattern for implementing y2038 syscalls
  2021-03-04 15:42                     ` Philippe Gerum
@ 2021-03-08 17:02                       ` Florian Bezdeka
  2021-03-08 17:02                         ` [RFC PATCH v2 1/4] y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
                                           ` (3 more replies)
  0 siblings, 4 replies; 57+ messages in thread
From: Florian Bezdeka @ 2021-03-08 17:02 UTC (permalink / raw)
  To: xenomai, jan.kiszka, rpm, chensong

Changes in v2:
  - Added a smokey plugin named y2038 for running Y2038 related tests
    (Should be extended with all related tests)
  - Review implementations (covered by tests now as well)
  - Drop support for kernel 4.4
  - Added the libcobalt part

Maintainers: Comments about naming / style welcome. That will speed up
the process when we just have to follow the right pattern.

Florian Bezdeka (4):
  y2038: Fixing the sem_timedwait syscall for 32 bit systems
  y2038: Adding sem_timedwait_time64
  y2038: Add tests for the sc_cobalt_sem_timedwait_time64 syscall
  y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait_time64

 configure.ac                                  |   1 +
 include/cobalt/uapi/syscall.h                 |   1 +
 .../include/asm-generic/xenomai/syscall.h     |  23 +++
 kernel/cobalt/posix/sem.c                     |  53 +++---
 kernel/cobalt/posix/sem.h                     |  10 +-
 kernel/cobalt/posix/syscall32.c               |  23 ++-
 kernel/cobalt/posix/syscall32.h               |   6 +-
 lib/cobalt/semaphore.c                        |   5 +
 testsuite/smokey/Makefile.am                  |   6 +-
 testsuite/smokey/y2038/Makefile.am            |  10 ++
 testsuite/smokey/y2038/syscall-tests.c        | 170 ++++++++++++++++++
 11 files changed, 277 insertions(+), 31 deletions(-)
 create mode 100644 testsuite/smokey/y2038/Makefile.am
 create mode 100644 testsuite/smokey/y2038/syscall-tests.c

-- 
2.29.2



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

* [RFC PATCH v2 1/4] y2038: Fixing the sem_timedwait syscall for 32 bit systems
  2021-03-08 17:02                       ` [RFC PATCH v2 0/4] Pattern for implementing y2038 syscalls Florian Bezdeka
@ 2021-03-08 17:02                         ` Florian Bezdeka
  2021-03-08 17:12                           ` Jan Kiszka
  2021-03-09  9:46                           ` Philippe Gerum
  2021-03-08 17:02                         ` [RFC PATCH v2 2/4] y2038: Adding sem_timedwait_time64 Florian Bezdeka
                                           ` (2 subsequent siblings)
  3 siblings, 2 replies; 57+ messages in thread
From: Florian Bezdeka @ 2021-03-08 17:02 UTC (permalink / raw)
  To: xenomai, jan.kiszka, rpm, chensong

On systems using 32 bit for time_t the sem_timedwait syscall was broken
because the function used for copying the timeout value from userspace
to kernel (=sem_fetch_timeout()) was always copying
sizeof(struct timespec64).

A 32 bit application (or more specific an application with 4 byte
time_t) would only provide sizeof(struct old_timespec32).

Notable changes:
  - The copy operation from userspace to kernel is now already done in
    the syscall handler. So it is always done. Previously it was copied
    over and validated before the first use (when used at all).
    So we have some additional instructions now that may be
    unnecessary, but that simplifies the code.

  - Validation: Switched to timespec64_valid() instead of our own
    check.

Fixes: 8043eccd232d ("cobalt/kernel: y2038: convert struct timespec to timespec64")
Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
 kernel/cobalt/posix/sem.c       | 40 +++++++++++++++------------------
 kernel/cobalt/posix/sem.h       |  6 ++---
 kernel/cobalt/posix/syscall32.c | 10 +++++++--
 kernel/cobalt/posix/syscall32.h |  2 +-
 4 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
index 467a9b7dd..827a4751a 100644
--- a/kernel/cobalt/posix/sem.c
+++ b/kernel/cobalt/posix/sem.c
@@ -267,20 +267,11 @@ out:
 	return ret;
 }
 
-static inline int sem_fetch_timeout(struct timespec64 *ts,
-				    const void __user *u_ts)
-{
-	return u_ts == NULL ? -EFAULT :
-		cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
-}
-
 int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
-			   const void __user *u_ts,
-			   int (*fetch_timeout)(struct timespec64 *ts,
-						const void __user *u_ts))
+			   const struct timespec64 *ts)
 {
-	struct timespec64 ts = { .tv_sec = 0, .tv_nsec = 0 };
-	int pull_ts = 1, ret, info;
+	int ret, info;
+	bool validate_ts = true;
 	struct cobalt_sem *sem;
 	xnhandle_t handle;
 	xntmode_t tmode;
@@ -304,24 +295,23 @@ int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
 		 * it's actually more complex, to keep some
 		 * applications ported to Linux happy.
 		 */
-		if (pull_ts) {
+		if (validate_ts) {
 			atomic_inc(&sem->state->value);
-			xnlock_put_irqrestore(&nklock, s);
-			ret = fetch_timeout(&ts, u_ts);
-			xnlock_get_irqsave(&nklock, s);
-			if (ret)
+			if (!ts) {
+				ret = -EFAULT;
 				break;
-			if (ts.tv_nsec >= ONE_BILLION) {
+			}
+			if (!timespec64_valid(ts)) {
 				ret = -EINVAL;
 				break;
 			}
-			pull_ts = 0;
+			validate_ts = false;
 			continue;
 		}
 
 		ret = 0;
 		tmode = sem->flags & SEM_RAWCLOCK ? XN_ABSOLUTE : XN_REALTIME;
-		info = xnsynch_sleep_on(&sem->synchbase, ts2ns(&ts) + 1, tmode);
+		info = xnsynch_sleep_on(&sem->synchbase, ts2ns(ts) + 1, tmode);
 		if (info & XNRMID)
 			ret = -EINVAL;
 		else if (info & (XNBREAK|XNTIMEO)) {
@@ -434,9 +424,15 @@ COBALT_SYSCALL(sem_wait, primary,
 
 COBALT_SYSCALL(sem_timedwait, primary,
 	       (struct cobalt_sem_shadow __user *u_sem,
-		struct __user_old_timespec __user *u_ts))
+		const struct __user_old_timespec __user *u_ts))
 {
-	return __cobalt_sem_timedwait(u_sem, u_ts, sem_fetch_timeout);
+	int ret = 1;
+	struct timespec64 ts64;
+
+	if (u_ts)
+		ret = cobalt_get_u_timespec(&ts64, u_ts);
+
+	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
 }
 
 COBALT_SYSCALL(sem_trywait, primary,
diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h
index d17299495..658e11f7a 100644
--- a/kernel/cobalt/posix/sem.h
+++ b/kernel/cobalt/posix/sem.h
@@ -64,9 +64,7 @@ __cobalt_sem_open(struct cobalt_sem_shadow __user *usm,
 		  int oflags, mode_t mode, unsigned int value);
 
 int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
-			   const void __user *u_ts,
-			   int (*fetch_timeout)(struct timespec64 *ts,
-						const void __user *u_ts));
+			   const struct timespec64 *ts);
 
 int __cobalt_sem_destroy(xnhandle_t handle);
 
@@ -91,7 +89,7 @@ COBALT_SYSCALL_DECL(sem_wait,
 
 COBALT_SYSCALL_DECL(sem_timedwait,
 		    (struct cobalt_sem_shadow __user *u_sem,
-		     struct __user_old_timespec __user *u_ts));
+		     const struct __user_old_timespec __user *u_ts));
 
 COBALT_SYSCALL_DECL(sem_trywait,
 		    (struct cobalt_sem_shadow __user *u_sem));
diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
index 57aa7251a..edac7ea4a 100644
--- a/kernel/cobalt/posix/syscall32.c
+++ b/kernel/cobalt/posix/syscall32.c
@@ -124,9 +124,15 @@ COBALT_SYSCALL32emu(sem_open, lostage,
 
 COBALT_SYSCALL32emu(sem_timedwait, primary,
 		    (struct cobalt_sem_shadow __user *u_sem,
-		     struct old_timespec32 __user *u_ts))
+		     const struct old_timespec32 __user *u_ts))
 {
-	return __cobalt_sem_timedwait(u_sem, u_ts, sys32_fetch_timeout);
+	int ret = 1;
+	struct timespec64 ts64;
+
+	if (u_ts)
+		ret = sys32_fetch_timeout(&ts64, u_ts);
+
+	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
 }
 
 COBALT_SYSCALL32emu(clock_getres, current,
diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h
index 66cd2a5d2..d72fd2022 100644
--- a/kernel/cobalt/posix/syscall32.h
+++ b/kernel/cobalt/posix/syscall32.h
@@ -229,6 +229,6 @@ COBALT_SYSCALL32emu_DECL(sem_open,
 
 COBALT_SYSCALL32emu_DECL(sem_timedwait,
 			 (struct cobalt_sem_shadow __user *u_sem,
-			  struct old_timespec32 __user *u_ts));
+			  const struct old_timespec32 __user *u_ts));
 
 #endif /* !_COBALT_POSIX_SYSCALL32_H */
-- 
2.29.2



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

* [RFC PATCH v2 2/4] y2038: Adding sem_timedwait_time64
  2021-03-08 17:02                       ` [RFC PATCH v2 0/4] Pattern for implementing y2038 syscalls Florian Bezdeka
  2021-03-08 17:02                         ` [RFC PATCH v2 1/4] y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
@ 2021-03-08 17:02                         ` Florian Bezdeka
  2021-03-08 18:28                           ` Jan Kiszka
  2021-03-08 17:02                         ` [RFC PATCH v2 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait_time64 syscall Florian Bezdeka
  2021-03-08 17:02                         ` [RFC PATCH v2 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait_time64 Florian Bezdeka
  3 siblings, 1 reply; 57+ messages in thread
From: Florian Bezdeka @ 2021-03-08 17:02 UTC (permalink / raw)
  To: xenomai, jan.kiszka, rpm, chensong

Implementation is heavily inspired by the sem_timedwait syscall,
but expecting time64 based timespec / timeout.

We need two new syscall handlers:
  - The native one (COBALT_SYSCALL()) to get 32 bit kernels time64
    aware. This handler is added for 64 bit kernels as well, but not
    used. As we don't have separate syscall tables for this both
    worlds we have to add it.

 - The compat handler (COBALT_SYSCALL32emu()) for x32 or x86
   applications running on an x86_64 kernel. Otherwise the redirection
   to the compat / emulation syscalls is broken.

Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
 include/cobalt/uapi/syscall.h                 |  1 +
 .../include/asm-generic/xenomai/syscall.h     | 23 +++++++++++++++++++
 kernel/cobalt/posix/sem.c                     | 13 +++++++++++
 kernel/cobalt/posix/sem.h                     |  4 ++++
 kernel/cobalt/posix/syscall32.c               | 13 +++++++++++
 kernel/cobalt/posix/syscall32.h               |  4 ++++
 6 files changed, 58 insertions(+)

diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
index aa3c308d0..9b005da47 100644
--- a/include/cobalt/uapi/syscall.h
+++ b/include/cobalt/uapi/syscall.h
@@ -122,6 +122,7 @@
 #define sc_cobalt_sendmmsg			99
 #define sc_cobalt_clock_adjtime			100
 #define sc_cobalt_thread_setschedprio		101
+#define sc_cobalt_sem_timedwait_time64		102
 
 #define __NR_COBALT_SYSCALLS			128 /* Power of 2 */
 
diff --git a/kernel/cobalt/include/asm-generic/xenomai/syscall.h b/kernel/cobalt/include/asm-generic/xenomai/syscall.h
index 91bbf3bfd..40d64b7a1 100644
--- a/kernel/cobalt/include/asm-generic/xenomai/syscall.h
+++ b/kernel/cobalt/include/asm-generic/xenomai/syscall.h
@@ -19,6 +19,7 @@
 #ifndef _COBALT_ASM_GENERIC_SYSCALL_H
 #define _COBALT_ASM_GENERIC_SYSCALL_H
 
+#include <linux/compat.h>
 #include <linux/types.h>
 #include <linux/version.h>
 #include <linux/uaccess.h>
@@ -82,6 +83,28 @@ static inline int cobalt_strncpy_from_user(char *dst, const char __user *src,
 	return __xn_strncpy_from_user(dst, src, count);
 }
 
+static inline int cobalt_get_timespec64(struct timespec64 *ts,
+				const struct __kernel_timespec __user *uts)
+{
+	struct __kernel_timespec kts;
+	int ret;
+
+	ret = cobalt_copy_from_user(&kts, uts, sizeof(kts));
+	if (ret)
+		return -EFAULT;
+
+	ts->tv_sec = kts.tv_sec;
+
+	/* Zero out the padding in compat mode */
+	if (in_compat_syscall())
+		kts.tv_nsec &= 0xFFFFFFFFUL;
+
+	/* In 32-bit mode, this drops the padding */
+	ts->tv_nsec = kts.tv_nsec;
+
+	return 0;
+}
+
 #if __BITS_PER_LONG == 64
 
 /*
diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
index 827a4751a..3055a456d 100644
--- a/kernel/cobalt/posix/sem.c
+++ b/kernel/cobalt/posix/sem.c
@@ -435,6 +435,19 @@ COBALT_SYSCALL(sem_timedwait, primary,
 	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
 }
 
+COBALT_SYSCALL(sem_timedwait_time64, primary,
+	       (struct cobalt_sem_shadow __user *u_sem,
+		const struct __kernel_timespec __user *u_ts))
+{
+	int ret = 1;
+	struct timespec64 ts64;
+
+	if (u_ts)
+		ret = cobalt_get_timespec64(&ts64, u_ts);
+
+	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
+}
+
 COBALT_SYSCALL(sem_trywait, primary,
 	       (struct cobalt_sem_shadow __user *u_sem))
 {
diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h
index 658e11f7a..8491b69ba 100644
--- a/kernel/cobalt/posix/sem.h
+++ b/kernel/cobalt/posix/sem.h
@@ -66,6 +66,10 @@ __cobalt_sem_open(struct cobalt_sem_shadow __user *usm,
 int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
 			   const struct timespec64 *ts);
 
+COBALT_SYSCALL_DECL(sem_timedwait_time64,
+		    (struct cobalt_sem_shadow __user *u_sem,
+		     const struct __kernel_timespec __user *u_ts));
+
 int __cobalt_sem_destroy(xnhandle_t handle);
 
 void cobalt_nsem_reclaim(struct cobalt_process *process);
diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
index edac7ea4a..f73bfcda3 100644
--- a/kernel/cobalt/posix/syscall32.c
+++ b/kernel/cobalt/posix/syscall32.c
@@ -135,6 +135,19 @@ COBALT_SYSCALL32emu(sem_timedwait, primary,
 	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
 }
 
+COBALT_SYSCALL32emu(sem_timedwait_time64, primary,
+		    (struct cobalt_sem_shadow __user *u_sem,
+		     const struct __kernel_timespec __user *u_ts))
+{
+	int ret = 1;
+	struct timespec64 ts64;
+
+	if (u_ts)
+		ret = cobalt_get_timespec64(&ts64, u_ts);
+
+	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
+}
+
 COBALT_SYSCALL32emu(clock_getres, current,
 		    (clockid_t clock_id,
 		     struct old_timespec32 __user *u_ts))
diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h
index d72fd2022..3612bf751 100644
--- a/kernel/cobalt/posix/syscall32.h
+++ b/kernel/cobalt/posix/syscall32.h
@@ -231,4 +231,8 @@ COBALT_SYSCALL32emu_DECL(sem_timedwait,
 			 (struct cobalt_sem_shadow __user *u_sem,
 			  const struct old_timespec32 __user *u_ts));
 
+COBALT_SYSCALL32emu_DECL(sem_timedwait_time64,
+			 (struct cobalt_sem_shadow __user * u_sem,
+			  const struct __kernel_timespec __user *u_ts));
+
 #endif /* !_COBALT_POSIX_SYSCALL32_H */
-- 
2.29.2



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

* [RFC PATCH v2 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait_time64 syscall
  2021-03-08 17:02                       ` [RFC PATCH v2 0/4] Pattern for implementing y2038 syscalls Florian Bezdeka
  2021-03-08 17:02                         ` [RFC PATCH v2 1/4] y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
  2021-03-08 17:02                         ` [RFC PATCH v2 2/4] y2038: Adding sem_timedwait_time64 Florian Bezdeka
@ 2021-03-08 17:02                         ` Florian Bezdeka
  2021-03-08 18:35                           ` Jan Kiszka
  2021-03-08 17:02                         ` [RFC PATCH v2 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait_time64 Florian Bezdeka
  3 siblings, 1 reply; 57+ messages in thread
From: Florian Bezdeka @ 2021-03-08 17:02 UTC (permalink / raw)
  To: xenomai, jan.kiszka, rpm, chensong

Introducing a new smokey plugin that can be extended for all kind of
y2038 tests.

Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
 configure.ac                           |   1 +
 testsuite/smokey/Makefile.am           |   6 +-
 testsuite/smokey/y2038/Makefile.am     |  10 ++
 testsuite/smokey/y2038/syscall-tests.c | 170 +++++++++++++++++++++++++
 4 files changed, 185 insertions(+), 2 deletions(-)
 create mode 100644 testsuite/smokey/y2038/Makefile.am
 create mode 100644 testsuite/smokey/y2038/syscall-tests.c

diff --git a/configure.ac b/configure.ac
index abe538dbd..bd5fd5ba9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -990,6 +990,7 @@ AC_CONFIG_FILES([ \
 	testsuite/smokey/net_common/Makefile \
 	testsuite/smokey/cpu-affinity/Makefile \
 	testsuite/smokey/gdb/Makefile \
+	testsuite/smokey/y2038/Makefile \
 	testsuite/clocktest/Makefile \
 	testsuite/xeno-test/Makefile \
 	utils/Makefile \
diff --git a/testsuite/smokey/Makefile.am b/testsuite/smokey/Makefile.am
index 02613c7dc..56c873026 100644
--- a/testsuite/smokey/Makefile.am
+++ b/testsuite/smokey/Makefile.am
@@ -38,7 +38,8 @@ COBALT_SUBDIRS = 	\
 	timerfd		\
 	tsc		\
 	vdso-access 	\
-	xddp
+	xddp		\
+	y2038
 
 MERCURY_SUBDIRS =	\
 	memory-heapmem	\
@@ -76,7 +77,8 @@ DIST_SUBDIRS = 		\
 	timerfd		\
 	tsc		\
 	vdso-access 	\
-	xddp
+	xddp		\
+	y2038
 
 if XENO_COBALT
 if CONFIG_XENO_LIBS_DLOPEN
diff --git a/testsuite/smokey/y2038/Makefile.am b/testsuite/smokey/y2038/Makefile.am
new file mode 100644
index 000000000..a97591aa2
--- /dev/null
+++ b/testsuite/smokey/y2038/Makefile.am
@@ -0,0 +1,10 @@
+
+noinst_LIBRARIES = liby2038.a
+
+liby2038_a_SOURCES = syscall-tests.c
+
+liby2038_a_CPPFLAGS = 	\
+	@XENO_USER_CFLAGS@	\
+	-I$(top_srcdir)		\
+	-I$(top_srcdir)/include
+
diff --git a/testsuite/smokey/y2038/syscall-tests.c b/testsuite/smokey/y2038/syscall-tests.c
new file mode 100644
index 000000000..0fc96374f
--- /dev/null
+++ b/testsuite/smokey/y2038/syscall-tests.c
@@ -0,0 +1,170 @@
+/*
+ * y2038 tests
+ *
+ * Copyright (c) Siemens AG 2021
+ *
+ * Authors:
+ *  Florian Bezdeka <florian.bezdeka@siemens.com>
+ *
+ * Released under the terms of GPLv2.
+ */
+#include <cobalt/uapi/syscall.h>
+#include <smokey/smokey.h>
+#include <semaphore.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <errno.h>
+
+smokey_test_plugin(y2038, SMOKEY_NOARGS, "Validate correct y2038 support");
+
+/*
+ * libc independent data type representing a time64_t based struct timespec
+ */
+struct xn_timespec64 {
+	int64_t tv_sec;
+	int64_t tv_nsec;
+};
+
+#define NSEC_PER_SEC 1000000000
+
+static void ts_normalise(struct xn_timespec64 *ts)
+{
+	while (ts->tv_nsec >= NSEC_PER_SEC) {
+		ts->tv_nsec += 1;
+		ts->tv_nsec -= NSEC_PER_SEC;
+	}
+
+	while (ts->tv_nsec <= -NSEC_PER_SEC) {
+		ts->tv_sec -= 1;
+		ts->tv_nsec += NSEC_PER_SEC;
+	}
+
+	if (ts->tv_nsec < 0) {
+		/*
+		 * Negative nanoseconds isn't valid according to POSIX.
+		 * Decrement tv_sec and roll tv_nsec over.
+		 */
+		ts->tv_sec -= 1;
+		ts->tv_nsec = (NSEC_PER_SEC + ts->tv_nsec);
+	}
+}
+
+static inline void ts_add_ns(struct xn_timespec64 *ts, int ns)
+{
+	ts->tv_nsec += ns;
+	ts_normalise(ts);
+}
+
+/**
+ * Compare two struct timespec instances
+ *
+ * @param a
+ * @param b
+ * @return True if a < b, false otherwise
+ */
+static inline bool ts_less(const struct xn_timespec64 *a,
+			   const struct xn_timespec64 *b)
+{
+	if (a->tv_sec < b->tv_sec)
+		return true;
+
+	if (a->tv_sec > b->tv_sec)
+		return false;
+
+	/* a->tv_sec == b->tv_sec */
+
+	if (a->tv_nsec < b->tv_nsec)
+		return true;
+
+	return false;
+}
+
+static int test_sc_cobalt_sem_timedwait_time64(void)
+{
+	long ret;
+	sem_t sem;
+	int code = __xn_syscode(sc_cobalt_sem_timedwait_time64);
+	struct xn_timespec64 ts64, ts_wu;
+	struct timespec ts_nat;
+
+	sem_init(&sem, 0, 0);
+
+	/*
+	 * TODO: Calling the syscall directly for now, as y2038 support is not
+	 * yet available in glibc. Once this is available we should use our
+	 * glibc wrappers provided by libcobalt.
+	 */
+
+	/* Make sure we don't crash because of NULL pointers */
+	ret = syscall(code, NULL, NULL);
+	if (ret == -1 && errno == ENOSYS)
+		return 0; // Not implemented, nothing to test, success
+	if (!smokey_assert(ret == -1) || !smokey_assert(errno == EINVAL))
+		return errno;
+
+	/* Timeout is never read by the kernel, so NULL should be OK */
+	sem_post(&sem);
+	ret = syscall(code, &sem, NULL);
+	if (!smokey_assert(!ret))
+		return errno;
+
+	/*
+	 * The semaphore is already exhausted, so calling again will validate
+	 * the provided timeout now. Providing NULL has to deliver EFAULT
+	 */
+	ret = syscall(code, &sem, NULL);
+	if (!smokey_assert(ret == -1) || !smokey_assert(errno == EFAULT))
+		return errno;
+
+	/*
+	 * The semaphore is still exhausted, calling again will validate the
+	 * timeout, providing an invalid timeout has to deliver EINVAL
+	 */
+	ts64.tv_sec = -1;
+	ret = syscall(code, &sem, &ts64);
+	if (!smokey_assert(ret == -1) || !smokey_assert(errno == EINVAL))
+		return errno;
+
+	/*
+	 * Providing a valid timeout, waiting for it to time out and check
+	 * that we didn't come back to early.
+	 */
+	ret = clock_gettime(CLOCK_MONOTONIC, &ts_nat);
+	if (ret)
+		return errno;
+
+	ts64.tv_sec = ts_nat.tv_sec;
+	ts64.tv_nsec = ts_nat.tv_nsec;
+	ts_add_ns(&ts64, 500000);
+
+	ret = syscall(code, &sem, &ts64);
+	if (!smokey_assert(ret == -1) || !smokey_assert(errno == ETIMEDOUT))
+		return errno;
+
+	ret = clock_gettime(CLOCK_MONOTONIC, &ts_nat);
+	if (ret)
+		return errno;
+
+	ts_wu.tv_sec = ts_nat.tv_sec;
+	ts_wu.tv_nsec = ts_nat.tv_nsec;
+
+	if (ts_less(&ts_wu, &ts64))
+		smokey_warning("sem_timedwait_time64 returned to early!\n"
+			       "Expected wakeup at: %lld sec %lld nsec\n"
+			       "Back at           : %lld sec %lld nsec\n",
+			       ts64.tv_sec, ts64.tv_nsec, ts_wu.tv_sec,
+			       ts_wu.tv_nsec);
+
+	return 0;
+}
+
+static int run_y2038(struct smokey_test *t, int argc, char *const argv[])
+{
+	int ret;
+
+	ret = test_sc_cobalt_sem_timedwait_time64();
+	if (ret)
+		return ret;
+
+	return 0;
+}
-- 
2.29.2



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

* [RFC PATCH v2 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait_time64
  2021-03-08 17:02                       ` [RFC PATCH v2 0/4] Pattern for implementing y2038 syscalls Florian Bezdeka
                                           ` (2 preceding siblings ...)
  2021-03-08 17:02                         ` [RFC PATCH v2 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait_time64 syscall Florian Bezdeka
@ 2021-03-08 17:02                         ` Florian Bezdeka
  2021-03-10 13:09                           ` [y2038][PATCH v3 0/4] Pattern for implementing y2038 syscalls Florian Bezdeka
  3 siblings, 1 reply; 57+ messages in thread
From: Florian Bezdeka @ 2021-03-08 17:02 UTC (permalink / raw)
  To: xenomai, jan.kiszka, rpm, chensong

In case libcobalt is build with -D_TIME_BITS=64
sc_cobalt_sem_timedwait_time64 will be used instead of
sc_cobalt_sem_timedwait.

Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
 lib/cobalt/semaphore.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lib/cobalt/semaphore.c b/lib/cobalt/semaphore.c
index 45705d48f..7e7e6c707 100644
--- a/lib/cobalt/semaphore.c
+++ b/lib/cobalt/semaphore.c
@@ -373,7 +373,12 @@ COBALT_IMPL(int, sem_timedwait, (sem_t *sem, const struct timespec *abs_timeout)
 
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
 
+#ifdef __USE_TIME_BITS64
+	ret = XENOMAI_SYSCALL2(sc_cobalt_sem_timedwait_time64, _sem,
+			       abs_timeout);
+#else
 	ret = XENOMAI_SYSCALL2(sc_cobalt_sem_timedwait, _sem, abs_timeout);
+#endif
 
 	pthread_setcanceltype(oldtype, NULL);
 
-- 
2.29.2



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

* Re: [RFC PATCH v2 1/4] y2038: Fixing the sem_timedwait syscall for 32 bit systems
  2021-03-08 17:02                         ` [RFC PATCH v2 1/4] y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
@ 2021-03-08 17:12                           ` Jan Kiszka
  2021-03-08 18:11                             ` florian.bezdeka
  2021-03-09  9:46                           ` Philippe Gerum
  1 sibling, 1 reply; 57+ messages in thread
From: Jan Kiszka @ 2021-03-08 17:12 UTC (permalink / raw)
  To: Florian Bezdeka, xenomai, rpm, chensong

On 08.03.21 18:02, Florian Bezdeka wrote:
> On systems using 32 bit for time_t the sem_timedwait syscall was broken
> because the function used for copying the timeout value from userspace
> to kernel (=sem_fetch_timeout()) was always copying
> sizeof(struct timespec64).
> 
> A 32 bit application (or more specific an application with 4 byte
> time_t) would only provide sizeof(struct old_timespec32).
> 
> Notable changes:
>   - The copy operation from userspace to kernel is now already done in
>     the syscall handler. So it is always done. Previously it was copied
>     over and validated before the first use (when used at all).
>     So we have some additional instructions now that may be
>     unnecessary, but that simplifies the code.
> 
>   - Validation: Switched to timespec64_valid() instead of our own
>     check.
> 
> Fixes: 8043eccd232d ("cobalt/kernel: y2038: convert struct timespec to timespec64")

This patch was dropped from next again (and that sha was never applied).
We should go a for fixed version of that series (patches 2..5, only
patch 1 is now applied).

Jan

-- 
Siemens AG, T RDA IOT
Corporate Competence Center Embedded Linux


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

* Re: [RFC PATCH v2 1/4] y2038: Fixing the sem_timedwait syscall for 32 bit systems
  2021-03-08 17:12                           ` Jan Kiszka
@ 2021-03-08 18:11                             ` florian.bezdeka
  2021-03-08 18:22                               ` Jan Kiszka
  0 siblings, 1 reply; 57+ messages in thread
From: florian.bezdeka @ 2021-03-08 18:11 UTC (permalink / raw)
  To: rpm, xenomai, jan.kiszka, chensong

On Mon, 2021-03-08 at 18:12 +0100, Jan Kiszka wrote:
> On 08.03.21 18:02, Florian Bezdeka wrote:
> > On systems using 32 bit for time_t the sem_timedwait syscall was broken
> > because the function used for copying the timeout value from userspace
> > to kernel (=sem_fetch_timeout()) was always copying
> > sizeof(struct timespec64).
> > 
> > A 32 bit application (or more specific an application with 4 byte
> > time_t) would only provide sizeof(struct old_timespec32).
> > 
> > Notable changes:
> >   - The copy operation from userspace to kernel is now already done in
> >     the syscall handler. So it is always done. Previously it was copied
> >     over and validated before the first use (when used at all).
> >     So we have some additional instructions now that may be
> >     unnecessary, but that simplifies the code.
> > 
> >   - Validation: Switched to timespec64_valid() instead of our own
> >     check.
> > 
> > Fixes: 8043eccd232d ("cobalt/kernel: y2038: convert struct timespec to timespec64")
> 
> This patch was dropped from next again (and that sha was never applied).
> We should go a for fixed version of that series (patches 2..5, only
> patch 1 is now applied).

That's one of the things that may happen when working with branches
that are getting rebased... The correct refspec is maybe 4d31feb5 now,
which is part of wip/dovetail.

Please note the RFC tag. Would be nice to get some feedback before
going ahead, otherwise the loops with all the necessary synchronization
and rebases is getting endless...

Thanks!
> 
> Jan
> 


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

* Re: [RFC PATCH v2 1/4] y2038: Fixing the sem_timedwait syscall for 32 bit systems
  2021-03-08 18:11                             ` florian.bezdeka
@ 2021-03-08 18:22                               ` Jan Kiszka
  0 siblings, 0 replies; 57+ messages in thread
From: Jan Kiszka @ 2021-03-08 18:22 UTC (permalink / raw)
  To: Bezdeka, Florian (T RDA IOT SES-DE), rpm, xenomai, chensong

On 08.03.21 19:11, Bezdeka, Florian (T RDA IOT SES-DE) wrote:
> On Mon, 2021-03-08 at 18:12 +0100, Jan Kiszka wrote:
>> On 08.03.21 18:02, Florian Bezdeka wrote:
>>> On systems using 32 bit for time_t the sem_timedwait syscall was broken
>>> because the function used for copying the timeout value from userspace
>>> to kernel (=sem_fetch_timeout()) was always copying
>>> sizeof(struct timespec64).
>>>
>>> A 32 bit application (or more specific an application with 4 byte
>>> time_t) would only provide sizeof(struct old_timespec32).
>>>
>>> Notable changes:
>>>   - The copy operation from userspace to kernel is now already done in
>>>     the syscall handler. So it is always done. Previously it was copied
>>>     over and validated before the first use (when used at all).
>>>     So we have some additional instructions now that may be
>>>     unnecessary, but that simplifies the code.
>>>
>>>   - Validation: Switched to timespec64_valid() instead of our own
>>>     check.
>>>
>>> Fixes: 8043eccd232d ("cobalt/kernel: y2038: convert struct timespec to timespec64")
>>
>> This patch was dropped from next again (and that sha was never applied).
>> We should go a for fixed version of that series (patches 2..5, only
>> patch 1 is now applied).
> 
> That's one of the things that may happen when working with branches
> that are getting rebased... The correct refspec is maybe 4d31feb5 now,
> which is part of wip/dovetail.

All these are development branches, nothing considered stable. And, no,
even wip/dovetail is the wrong target. The right one is the patch that
needs to be fixed in v2 of Philippe's series.

> 
> Please note the RFC tag. Would be nice to get some feedback before
> going ahead, otherwise the loops with all the necessary synchronization
> and rebases is getting endless...

For this particular patch, Philippe should comment first.
I will have a look at the rest now.

Jan

-- 
Siemens AG, T RDA IOT
Corporate Competence Center Embedded Linux


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

* Re: [RFC PATCH v2 2/4] y2038: Adding sem_timedwait_time64
  2021-03-08 17:02                         ` [RFC PATCH v2 2/4] y2038: Adding sem_timedwait_time64 Florian Bezdeka
@ 2021-03-08 18:28                           ` Jan Kiszka
  2021-03-09  7:53                             ` florian.bezdeka
  0 siblings, 1 reply; 57+ messages in thread
From: Jan Kiszka @ 2021-03-08 18:28 UTC (permalink / raw)
  To: Florian Bezdeka, xenomai, rpm, chensong

On 08.03.21 18:02, Florian Bezdeka wrote:
> Implementation is heavily inspired by the sem_timedwait syscall,
> but expecting time64 based timespec / timeout.
> 
> We need two new syscall handlers:
>   - The native one (COBALT_SYSCALL()) to get 32 bit kernels time64
>     aware. This handler is added for 64 bit kernels as well, but not
>     used. As we don't have separate syscall tables for this both
>     worlds we have to add it.
> 
>  - The compat handler (COBALT_SYSCALL32emu()) for x32 or x86
>    applications running on an x86_64 kernel. Otherwise the redirection
>    to the compat / emulation syscalls is broken.
> 
> Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
> ---
>  include/cobalt/uapi/syscall.h                 |  1 +
>  .../include/asm-generic/xenomai/syscall.h     | 23 +++++++++++++++++++
>  kernel/cobalt/posix/sem.c                     | 13 +++++++++++
>  kernel/cobalt/posix/sem.h                     |  4 ++++
>  kernel/cobalt/posix/syscall32.c               | 13 +++++++++++
>  kernel/cobalt/posix/syscall32.h               |  4 ++++
>  6 files changed, 58 insertions(+)
> 
> diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
> index aa3c308d0..9b005da47 100644
> --- a/include/cobalt/uapi/syscall.h
> +++ b/include/cobalt/uapi/syscall.h
> @@ -122,6 +122,7 @@
>  #define sc_cobalt_sendmmsg			99
>  #define sc_cobalt_clock_adjtime			100
>  #define sc_cobalt_thread_setschedprio		101
> +#define sc_cobalt_sem_timedwait_time64		102

Maybe just sc_cobalt_sem_timedwait64?

How many additional calls are probably required?

>  
>  #define __NR_COBALT_SYSCALLS			128 /* Power of 2 */
>  
> diff --git a/kernel/cobalt/include/asm-generic/xenomai/syscall.h b/kernel/cobalt/include/asm-generic/xenomai/syscall.h
> index 91bbf3bfd..40d64b7a1 100644
> --- a/kernel/cobalt/include/asm-generic/xenomai/syscall.h
> +++ b/kernel/cobalt/include/asm-generic/xenomai/syscall.h
> @@ -19,6 +19,7 @@
>  #ifndef _COBALT_ASM_GENERIC_SYSCALL_H
>  #define _COBALT_ASM_GENERIC_SYSCALL_H
>  
> +#include <linux/compat.h>
>  #include <linux/types.h>
>  #include <linux/version.h>
>  #include <linux/uaccess.h>
> @@ -82,6 +83,28 @@ static inline int cobalt_strncpy_from_user(char *dst, const char __user *src,
>  	return __xn_strncpy_from_user(dst, src, count);
>  }
>  
> +static inline int cobalt_get_timespec64(struct timespec64 *ts,
> +				const struct __kernel_timespec __user *uts)
> +{
> +	struct __kernel_timespec kts;
> +	int ret;
> +
> +	ret = cobalt_copy_from_user(&kts, uts, sizeof(kts));
> +	if (ret)
> +		return -EFAULT;
> +
> +	ts->tv_sec = kts.tv_sec;
> +
> +	/* Zero out the padding in compat mode */
> +	if (in_compat_syscall())
> +		kts.tv_nsec &= 0xFFFFFFFFUL;
> +
> +	/* In 32-bit mode, this drops the padding */
> +	ts->tv_nsec = kts.tv_nsec;
> +
> +	return 0;
> +}
> +

Why inline? But that question is likely obsolete when we can avoid the
code duplication below.

>  #if __BITS_PER_LONG == 64
>  
>  /*
> diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
> index 827a4751a..3055a456d 100644
> --- a/kernel/cobalt/posix/sem.c
> +++ b/kernel/cobalt/posix/sem.c
> @@ -435,6 +435,19 @@ COBALT_SYSCALL(sem_timedwait, primary,
>  	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
>  }
>  
> +COBALT_SYSCALL(sem_timedwait_time64, primary,
> +	       (struct cobalt_sem_shadow __user *u_sem,
> +		const struct __kernel_timespec __user *u_ts))
> +{
> +	int ret = 1;
> +	struct timespec64 ts64;
> +
> +	if (u_ts)
> +		ret = cobalt_get_timespec64(&ts64, u_ts);
> +
> +	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
> +}
> +
>  COBALT_SYSCALL(sem_trywait, primary,
>  	       (struct cobalt_sem_shadow __user *u_sem))
>  {
> diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h
> index 658e11f7a..8491b69ba 100644
> --- a/kernel/cobalt/posix/sem.h
> +++ b/kernel/cobalt/posix/sem.h
> @@ -66,6 +66,10 @@ __cobalt_sem_open(struct cobalt_sem_shadow __user *usm,
>  int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
>  			   const struct timespec64 *ts);
>  
> +COBALT_SYSCALL_DECL(sem_timedwait_time64,
> +		    (struct cobalt_sem_shadow __user *u_sem,
> +		     const struct __kernel_timespec __user *u_ts));
> +
>  int __cobalt_sem_destroy(xnhandle_t handle);
>  
>  void cobalt_nsem_reclaim(struct cobalt_process *process);
> diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
> index edac7ea4a..f73bfcda3 100644
> --- a/kernel/cobalt/posix/syscall32.c
> +++ b/kernel/cobalt/posix/syscall32.c
> @@ -135,6 +135,19 @@ COBALT_SYSCALL32emu(sem_timedwait, primary,
>  	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
>  }
>  
> +COBALT_SYSCALL32emu(sem_timedwait_time64, primary,
> +		    (struct cobalt_sem_shadow __user *u_sem,
> +		     const struct __kernel_timespec __user *u_ts))
> +{
> +	int ret = 1;
> +	struct timespec64 ts64;
> +
> +	if (u_ts)
> +		ret = cobalt_get_timespec64(&ts64, u_ts);
> +
> +	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
> +}

Why do we need to code this out twice? I don't spot the difference to
the native implementation yet. Can't we point to it directly?

> +
>  COBALT_SYSCALL32emu(clock_getres, current,
>  		    (clockid_t clock_id,
>  		     struct old_timespec32 __user *u_ts))
> diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h
> index d72fd2022..3612bf751 100644
> --- a/kernel/cobalt/posix/syscall32.h
> +++ b/kernel/cobalt/posix/syscall32.h
> @@ -231,4 +231,8 @@ COBALT_SYSCALL32emu_DECL(sem_timedwait,
>  			 (struct cobalt_sem_shadow __user *u_sem,
>  			  const struct old_timespec32 __user *u_ts));
>  
> +COBALT_SYSCALL32emu_DECL(sem_timedwait_time64,
> +			 (struct cobalt_sem_shadow __user * u_sem,
> +			  const struct __kernel_timespec __user *u_ts));
> +
>  #endif /* !_COBALT_POSIX_SYSCALL32_H */
> 

Jan

-- 
Siemens AG, T RDA IOT
Corporate Competence Center Embedded Linux


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

* Re: [RFC PATCH v2 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait_time64 syscall
  2021-03-08 17:02                         ` [RFC PATCH v2 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait_time64 syscall Florian Bezdeka
@ 2021-03-08 18:35                           ` Jan Kiszka
  2021-03-09  8:00                             ` florian.bezdeka
  0 siblings, 1 reply; 57+ messages in thread
From: Jan Kiszka @ 2021-03-08 18:35 UTC (permalink / raw)
  To: Florian Bezdeka, xenomai, rpm, chensong

On 08.03.21 18:02, Florian Bezdeka wrote:
> Introducing a new smokey plugin that can be extended for all kind of
> y2038 tests.

And what does this version test? Some more words on how the new syscall
is stressed would be valuable here.

> 
> Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
> ---
>  configure.ac                           |   1 +
>  testsuite/smokey/Makefile.am           |   6 +-
>  testsuite/smokey/y2038/Makefile.am     |  10 ++
>  testsuite/smokey/y2038/syscall-tests.c | 170 +++++++++++++++++++++++++
>  4 files changed, 185 insertions(+), 2 deletions(-)
>  create mode 100644 testsuite/smokey/y2038/Makefile.am
>  create mode 100644 testsuite/smokey/y2038/syscall-tests.c
> 
> diff --git a/configure.ac b/configure.ac
> index abe538dbd..bd5fd5ba9 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -990,6 +990,7 @@ AC_CONFIG_FILES([ \
>  	testsuite/smokey/net_common/Makefile \
>  	testsuite/smokey/cpu-affinity/Makefile \
>  	testsuite/smokey/gdb/Makefile \
> +	testsuite/smokey/y2038/Makefile \
>  	testsuite/clocktest/Makefile \
>  	testsuite/xeno-test/Makefile \
>  	utils/Makefile \
> diff --git a/testsuite/smokey/Makefile.am b/testsuite/smokey/Makefile.am
> index 02613c7dc..56c873026 100644
> --- a/testsuite/smokey/Makefile.am
> +++ b/testsuite/smokey/Makefile.am
> @@ -38,7 +38,8 @@ COBALT_SUBDIRS = 	\
>  	timerfd		\
>  	tsc		\
>  	vdso-access 	\
> -	xddp
> +	xddp		\
> +	y2038
>  
>  MERCURY_SUBDIRS =	\
>  	memory-heapmem	\
> @@ -76,7 +77,8 @@ DIST_SUBDIRS = 		\
>  	timerfd		\
>  	tsc		\
>  	vdso-access 	\
> -	xddp
> +	xddp		\
> +	y2038
>  
>  if XENO_COBALT
>  if CONFIG_XENO_LIBS_DLOPEN
> diff --git a/testsuite/smokey/y2038/Makefile.am b/testsuite/smokey/y2038/Makefile.am
> new file mode 100644
> index 000000000..a97591aa2
> --- /dev/null
> +++ b/testsuite/smokey/y2038/Makefile.am
> @@ -0,0 +1,10 @@
> +
> +noinst_LIBRARIES = liby2038.a
> +
> +liby2038_a_SOURCES = syscall-tests.c
> +
> +liby2038_a_CPPFLAGS = 	\
> +	@XENO_USER_CFLAGS@	\
> +	-I$(top_srcdir)		\
> +	-I$(top_srcdir)/include
> +
> diff --git a/testsuite/smokey/y2038/syscall-tests.c b/testsuite/smokey/y2038/syscall-tests.c
> new file mode 100644
> index 000000000..0fc96374f
> --- /dev/null
> +++ b/testsuite/smokey/y2038/syscall-tests.c
> @@ -0,0 +1,170 @@
> +/*
> + * y2038 tests
> + *
> + * Copyright (c) Siemens AG 2021
> + *
> + * Authors:
> + *  Florian Bezdeka <florian.bezdeka@siemens.com>
> + *
> + * Released under the terms of GPLv2.
> + */
> +#include <cobalt/uapi/syscall.h>
> +#include <smokey/smokey.h>
> +#include <semaphore.h>
> +#include <unistd.h>
> +#include <stdint.h>
> +#include <errno.h>
> +
> +smokey_test_plugin(y2038, SMOKEY_NOARGS, "Validate correct y2038 support");
> +
> +/*
> + * libc independent data type representing a time64_t based struct timespec
> + */
> +struct xn_timespec64 {
> +	int64_t tv_sec;
> +	int64_t tv_nsec;
> +};
> +
> +#define NSEC_PER_SEC 1000000000
> +
> +static void ts_normalise(struct xn_timespec64 *ts)
> +{
> +	while (ts->tv_nsec >= NSEC_PER_SEC) {
> +		ts->tv_nsec += 1;
> +		ts->tv_nsec -= NSEC_PER_SEC;
> +	}
> +
> +	while (ts->tv_nsec <= -NSEC_PER_SEC) {
> +		ts->tv_sec -= 1;
> +		ts->tv_nsec += NSEC_PER_SEC;
> +	}
> +
> +	if (ts->tv_nsec < 0) {
> +		/*
> +		 * Negative nanoseconds isn't valid according to POSIX.
> +		 * Decrement tv_sec and roll tv_nsec over.
> +		 */
> +		ts->tv_sec -= 1;
> +		ts->tv_nsec = (NSEC_PER_SEC + ts->tv_nsec);
> +	}
> +}
> +
> +static inline void ts_add_ns(struct xn_timespec64 *ts, int ns)
> +{
> +	ts->tv_nsec += ns;
> +	ts_normalise(ts);
> +}
> +
> +/**
> + * Compare two struct timespec instances
> + *
> + * @param a
> + * @param b
> + * @return True if a < b, false otherwise
> + */
> +static inline bool ts_less(const struct xn_timespec64 *a,
> +			   const struct xn_timespec64 *b)
> +{
> +	if (a->tv_sec < b->tv_sec)
> +		return true;
> +
> +	if (a->tv_sec > b->tv_sec)
> +		return false;
> +
> +	/* a->tv_sec == b->tv_sec */
> +
> +	if (a->tv_nsec < b->tv_nsec)
> +		return true;
> +
> +	return false;
> +}
> +
> +static int test_sc_cobalt_sem_timedwait_time64(void)
> +{
> +	long ret;
> +	sem_t sem;
> +	int code = __xn_syscode(sc_cobalt_sem_timedwait_time64);
> +	struct xn_timespec64 ts64, ts_wu;
> +	struct timespec ts_nat;
> +
> +	sem_init(&sem, 0, 0);
> +
> +	/*
> +	 * TODO: Calling the syscall directly for now, as y2038 support is not
> +	 * yet available in glibc. Once this is available we should use our
> +	 * glibc wrappers provided by libcobalt.
> +	 */

Maybe wrap that, to make the invocations more readable? Maybe a macro
can do that in a way that will not affect the code once glibc is ready.

> +
> +	/* Make sure we don't crash because of NULL pointers */
> +	ret = syscall(code, NULL, NULL);
> +	if (ret == -1 && errno == ENOSYS)
> +		return 0; // Not implemented, nothing to test, success
> +	if (!smokey_assert(ret == -1) || !smokey_assert(errno == EINVAL))
> +		return errno;
> +
> +	/* Timeout is never read by the kernel, so NULL should be OK */
> +	sem_post(&sem);
> +	ret = syscall(code, &sem, NULL);
> +	if (!smokey_assert(!ret))
> +		return errno;
> +
> +	/*
> +	 * The semaphore is already exhausted, so calling again will validate
> +	 * the provided timeout now. Providing NULL has to deliver EFAULT
> +	 */
> +	ret = syscall(code, &sem, NULL);
> +	if (!smokey_assert(ret == -1) || !smokey_assert(errno == EFAULT))
> +		return errno;
> +
> +	/*
> +	 * The semaphore is still exhausted, calling again will validate the
> +	 * timeout, providing an invalid timeout has to deliver EINVAL
> +	 */
> +	ts64.tv_sec = -1;
> +	ret = syscall(code, &sem, &ts64);
> +	if (!smokey_assert(ret == -1) || !smokey_assert(errno == EINVAL))
> +		return errno;
> +
> +	/*
> +	 * Providing a valid timeout, waiting for it to time out and check
> +	 * that we didn't come back to early.
> +	 */
> +	ret = clock_gettime(CLOCK_MONOTONIC, &ts_nat);
> +	if (ret)
> +		return errno;
> +
> +	ts64.tv_sec = ts_nat.tv_sec;
> +	ts64.tv_nsec = ts_nat.tv_nsec;
> +	ts_add_ns(&ts64, 500000);
> +
> +	ret = syscall(code, &sem, &ts64);
> +	if (!smokey_assert(ret == -1) || !smokey_assert(errno == ETIMEDOUT))
> +		return errno;
> +
> +	ret = clock_gettime(CLOCK_MONOTONIC, &ts_nat);
> +	if (ret)
> +		return errno;
> +
> +	ts_wu.tv_sec = ts_nat.tv_sec;
> +	ts_wu.tv_nsec = ts_nat.tv_nsec;
> +
> +	if (ts_less(&ts_wu, &ts64))
> +		smokey_warning("sem_timedwait_time64 returned to early!\n"
> +			       "Expected wakeup at: %lld sec %lld nsec\n"
> +			       "Back at           : %lld sec %lld nsec\n",
> +			       ts64.tv_sec, ts64.tv_nsec, ts_wu.tv_sec,
> +			       ts_wu.tv_nsec);
> +

Does this already stress the 64-bit range of time_t? I don't spot that yet.

> +	return 0;
> +}
> +
> +static int run_y2038(struct smokey_test *t, int argc, char *const argv[])
> +{
> +	int ret;
> +
> +	ret = test_sc_cobalt_sem_timedwait_time64();
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> 

Such a test is obviously key to approach the issue correctly. It's a
complex beast.

Jan

-- 
Siemens AG, T RDA IOT
Corporate Competence Center Embedded Linux


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

* Re: [RFC PATCH v2 2/4] y2038: Adding sem_timedwait_time64
  2021-03-08 18:28                           ` Jan Kiszka
@ 2021-03-09  7:53                             ` florian.bezdeka
  2021-03-10  7:51                               ` florian.bezdeka
  0 siblings, 1 reply; 57+ messages in thread
From: florian.bezdeka @ 2021-03-09  7:53 UTC (permalink / raw)
  To: rpm, xenomai, jan.kiszka, chensong

On Mon, 2021-03-08 at 19:28 +0100, Jan Kiszka wrote:
> On 08.03.21 18:02, Florian Bezdeka wrote:
> > Implementation is heavily inspired by the sem_timedwait syscall,
> > but expecting time64 based timespec / timeout.
> > 
> > We need two new syscall handlers:
> >   - The native one (COBALT_SYSCALL()) to get 32 bit kernels time64
> >     aware. This handler is added for 64 bit kernels as well, but not
> >     used. As we don't have separate syscall tables for this both
> >     worlds we have to add it.
> > 
> >  - The compat handler (COBALT_SYSCALL32emu()) for x32 or x86
> >    applications running on an x86_64 kernel. Otherwise the redirection
> >    to the compat / emulation syscalls is broken.
> > 
> > Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
> > ---
> >  include/cobalt/uapi/syscall.h                 |  1 +
> >  .../include/asm-generic/xenomai/syscall.h     | 23 +++++++++++++++++++
> >  kernel/cobalt/posix/sem.c                     | 13 +++++++++++
> >  kernel/cobalt/posix/sem.h                     |  4 ++++
> >  kernel/cobalt/posix/syscall32.c               | 13 +++++++++++
> >  kernel/cobalt/posix/syscall32.h               |  4 ++++
> >  6 files changed, 58 insertions(+)
> > 
> > diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
> > index aa3c308d0..9b005da47 100644
> > --- a/include/cobalt/uapi/syscall.h
> > +++ b/include/cobalt/uapi/syscall.h
> > @@ -122,6 +122,7 @@
> >  #define sc_cobalt_sendmmsg			99
> >  #define sc_cobalt_clock_adjtime			100
> >  #define sc_cobalt_thread_setschedprio		101
> > +#define sc_cobalt_sem_timedwait_time64		102
> 
> Maybe just sc_cobalt_sem_timedwait64?
> 
> How many additional calls are probably required?

Yes, we can shrink to the "64" suffix instead of "time64" if you
prefer.

We have identified 15 syscalls so far.

> > 
> >  #define __NR_COBALT_SYSCALLS			128 /* Power of 2 */
> >  
> > diff --git a/kernel/cobalt/include/asm-generic/xenomai/syscall.h b/kernel/cobalt/include/asm-generic/xenomai/syscall.h
> > index 91bbf3bfd..40d64b7a1 100644
> > --- a/kernel/cobalt/include/asm-generic/xenomai/syscall.h
> > +++ b/kernel/cobalt/include/asm-generic/xenomai/syscall.h
> > @@ -19,6 +19,7 @@
> >  #ifndef _COBALT_ASM_GENERIC_SYSCALL_H
> >  #define _COBALT_ASM_GENERIC_SYSCALL_H
> > 
> > +#include <linux/compat.h>
> >  #include <linux/types.h>
> >  #include <linux/version.h>
> >  #include <linux/uaccess.h>
> > @@ -82,6 +83,28 @@ static inline int cobalt_strncpy_from_user(char *dst, const char __user *src,
> >  	return __xn_strncpy_from_user(dst, src, count);
> >  }
> >  
> > +static inline int cobalt_get_timespec64(struct timespec64 *ts,
> > +				const struct __kernel_timespec __user *uts)
> > +{
> > +	struct __kernel_timespec kts;
> > +	int ret;
> > +
> > +	ret = cobalt_copy_from_user(&kts, uts, sizeof(kts));
> > +	if (ret)
> > +		return -EFAULT;
> > +
> > +	ts->tv_sec = kts.tv_sec;
> > +
> > +	/* Zero out the padding in compat mode */
> > +	if (in_compat_syscall())
> > +		kts.tv_nsec &= 0xFFFFFFFFUL;
> > +
> > +	/* In 32-bit mode, this drops the padding */
> > +	ts->tv_nsec = kts.tv_nsec;
> > +
> > +	return 0;
> > +}
> > +
> 
> Why inline? But that question is likely obsolete when we can avoid the
> code duplication below.

Inline can be removed. Something for v3. There will follow more calls
to that helper. All syscalls reading a struct timespec from userspace
will have to use it.

> 
> >  #if __BITS_PER_LONG == 64
> >  
> >  /*
> > diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
> > index 827a4751a..3055a456d 100644
> > --- a/kernel/cobalt/posix/sem.c
> > +++ b/kernel/cobalt/posix/sem.c
> > @@ -435,6 +435,19 @@ COBALT_SYSCALL(sem_timedwait, primary,
> >  	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
> >  }
> >  
> > 
> > +COBALT_SYSCALL(sem_timedwait_time64, primary,
> > +	       (struct cobalt_sem_shadow __user *u_sem,
> > +		const struct __kernel_timespec __user *u_ts))
> > +{
> > +	int ret = 1;
> > +	struct timespec64 ts64;
> > +
> > +	if (u_ts)
> > +		ret = cobalt_get_timespec64(&ts64, u_ts);
> > +
> > +	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
> > +}
> > +
> >  COBALT_SYSCALL(sem_trywait, primary,
> >  	       (struct cobalt_sem_shadow __user *u_sem))
> >  {
> > diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h
> > index 658e11f7a..8491b69ba 100644
> > --- a/kernel/cobalt/posix/sem.h
> > +++ b/kernel/cobalt/posix/sem.h
> > @@ -66,6 +66,10 @@ __cobalt_sem_open(struct cobalt_sem_shadow __user *usm,
> >  int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
> >  			   const struct timespec64 *ts);
> >  
> > 
> > +COBALT_SYSCALL_DECL(sem_timedwait_time64,
> > +		    (struct cobalt_sem_shadow __user *u_sem,
> > +		     const struct __kernel_timespec __user *u_ts));
> > +
> >  int __cobalt_sem_destroy(xnhandle_t handle);
> >  
> >  void cobalt_nsem_reclaim(struct cobalt_process *process);
> > diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
> > index edac7ea4a..f73bfcda3 100644
> > --- a/kernel/cobalt/posix/syscall32.c
> > +++ b/kernel/cobalt/posix/syscall32.c
> > @@ -135,6 +135,19 @@ COBALT_SYSCALL32emu(sem_timedwait, primary,
> >  	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
> >  }
> >  
> > 
> > +COBALT_SYSCALL32emu(sem_timedwait_time64, primary,
> > +		    (struct cobalt_sem_shadow __user *u_sem,
> > +		     const struct __kernel_timespec __user *u_ts))
> > +{
> > +	int ret = 1;
> > +	struct timespec64 ts64;
> > +
> > +	if (u_ts)
> > +		ret = cobalt_get_timespec64(&ts64, u_ts);
> > +
> > +	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
> > +}
> 
> Why do we need to code this out twice? I don't spot the difference to
> the native implementation yet. Can't we point to it directly?

AFAIK we can't point to the same handler. That's how the internal
creation of the syscall table works. The "compat interfaces" of Linux
and Xenomai are different. Linux has a syscall table for each entry
point while Xenomai has only a single table, where compat syscalls are
located at a specific offset.

We need one handler defined by COBALT_SYSCALL() and one defined by
COBALT_SYSCALL32emu().

As all the "64 bit always" related will have the same content we could
move the content into a function that is being called from both
handlers. Will do...

Thanks for the feedback / review! 

> 
> > +
> >  COBALT_SYSCALL32emu(clock_getres, current,
> >  		    (clockid_t clock_id,
> >  		     struct old_timespec32 __user *u_ts))
> > diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h
> > index d72fd2022..3612bf751 100644
> > --- a/kernel/cobalt/posix/syscall32.h
> > +++ b/kernel/cobalt/posix/syscall32.h
> > @@ -231,4 +231,8 @@ COBALT_SYSCALL32emu_DECL(sem_timedwait,
> >  			 (struct cobalt_sem_shadow __user *u_sem,
> >  			  const struct old_timespec32 __user *u_ts));
> >  
> > 
> > +COBALT_SYSCALL32emu_DECL(sem_timedwait_time64,
> > +			 (struct cobalt_sem_shadow __user * u_sem,
> > +			  const struct __kernel_timespec __user *u_ts));
> > +
> >  #endif /* !_COBALT_POSIX_SYSCALL32_H */
> > 
> 
> Jan
> 


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

* Re: [RFC PATCH v2 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait_time64 syscall
  2021-03-08 18:35                           ` Jan Kiszka
@ 2021-03-09  8:00                             ` florian.bezdeka
  0 siblings, 0 replies; 57+ messages in thread
From: florian.bezdeka @ 2021-03-09  8:00 UTC (permalink / raw)
  To: rpm, xenomai, jan.kiszka, chensong

On Mon, 2021-03-08 at 19:35 +0100, Jan Kiszka wrote:
> On 08.03.21 18:02, Florian Bezdeka wrote:
> > Introducing a new smokey plugin that can be extended for all kind of
> > y2038 tests.
> 
> And what does this version test? Some more words on how the new syscall
> is stressed would be valuable here.

Yes. Will do.

> 
> > 
> > Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
> > ---
> >  configure.ac                           |   1 +
> >  testsuite/smokey/Makefile.am           |   6 +-
> >  testsuite/smokey/y2038/Makefile.am     |  10 ++
> >  testsuite/smokey/y2038/syscall-tests.c | 170 +++++++++++++++++++++++++
> >  4 files changed, 185 insertions(+), 2 deletions(-)
> >  create mode 100644 testsuite/smokey/y2038/Makefile.am
> >  create mode 100644 testsuite/smokey/y2038/syscall-tests.c
> > 
> > diff --git a/configure.ac b/configure.ac
> > index abe538dbd..bd5fd5ba9 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -990,6 +990,7 @@ AC_CONFIG_FILES([ \
> >  	testsuite/smokey/net_common/Makefile \
> >  	testsuite/smokey/cpu-affinity/Makefile \
> >  	testsuite/smokey/gdb/Makefile \
> > +	testsuite/smokey/y2038/Makefile \
> >  	testsuite/clocktest/Makefile \
> >  	testsuite/xeno-test/Makefile \
> >  	utils/Makefile \
> > diff --git a/testsuite/smokey/Makefile.am b/testsuite/smokey/Makefile.am
> > index 02613c7dc..56c873026 100644
> > --- a/testsuite/smokey/Makefile.am
> > +++ b/testsuite/smokey/Makefile.am
> > @@ -38,7 +38,8 @@ COBALT_SUBDIRS = 	\
> >  	timerfd		\
> >  	tsc		\
> >  	vdso-access 	\
> > -	xddp
> > +	xddp		\
> > +	y2038
> >  
> > 
> > 
> > 
> > 
> > 
> > 
> > 
> >  MERCURY_SUBDIRS =	\
> >  	memory-heapmem	\
> > @@ -76,7 +77,8 @@ DIST_SUBDIRS = 		\
> >  	timerfd		\
> >  	tsc		\
> >  	vdso-access 	\
> > -	xddp
> > +	xddp		\
> > +	y2038
> >  
> > 
> > 
> > 
> > 
> > 
> > 
> > 
> >  if XENO_COBALT
> >  if CONFIG_XENO_LIBS_DLOPEN
> > diff --git a/testsuite/smokey/y2038/Makefile.am b/testsuite/smokey/y2038/Makefile.am
> > new file mode 100644
> > index 000000000..a97591aa2
> > --- /dev/null
> > +++ b/testsuite/smokey/y2038/Makefile.am
> > @@ -0,0 +1,10 @@
> > +
> > +noinst_LIBRARIES = liby2038.a
> > +
> > +liby2038_a_SOURCES = syscall-tests.c
> > +
> > +liby2038_a_CPPFLAGS = 	\
> > +	@XENO_USER_CFLAGS@	\
> > +	-I$(top_srcdir)		\
> > +	-I$(top_srcdir)/include
> > +
> > diff --git a/testsuite/smokey/y2038/syscall-tests.c b/testsuite/smokey/y2038/syscall-tests.c
> > new file mode 100644
> > index 000000000..0fc96374f
> > --- /dev/null
> > +++ b/testsuite/smokey/y2038/syscall-tests.c
> > @@ -0,0 +1,170 @@
> > +/*
> > + * y2038 tests
> > + *
> > + * Copyright (c) Siemens AG 2021
> > + *
> > + * Authors:
> > + *  Florian Bezdeka <florian.bezdeka@siemens.com>
> > + *
> > + * Released under the terms of GPLv2.
> > + */
> > +#include <cobalt/uapi/syscall.h>
> > +#include <smokey/smokey.h>
> > +#include <semaphore.h>
> > +#include <unistd.h>
> > +#include <stdint.h>
> > +#include <errno.h>
> > +
> > +smokey_test_plugin(y2038, SMOKEY_NOARGS, "Validate correct y2038 support");
> > +
> > +/*
> > + * libc independent data type representing a time64_t based struct timespec
> > + */
> > +struct xn_timespec64 {
> > +	int64_t tv_sec;
> > +	int64_t tv_nsec;
> > +};
> > +
> > +#define NSEC_PER_SEC 1000000000
> > +
> > +static void ts_normalise(struct xn_timespec64 *ts)
> > +{
> > +	while (ts->tv_nsec >= NSEC_PER_SEC) {
> > +		ts->tv_nsec += 1;
> > +		ts->tv_nsec -= NSEC_PER_SEC;
> > +	}
> > +
> > +	while (ts->tv_nsec <= -NSEC_PER_SEC) {
> > +		ts->tv_sec -= 1;
> > +		ts->tv_nsec += NSEC_PER_SEC;
> > +	}
> > +
> > +	if (ts->tv_nsec < 0) {
> > +		/*
> > +		 * Negative nanoseconds isn't valid according to POSIX.
> > +		 * Decrement tv_sec and roll tv_nsec over.
> > +		 */
> > +		ts->tv_sec -= 1;
> > +		ts->tv_nsec = (NSEC_PER_SEC + ts->tv_nsec);
> > +	}
> > +}
> > +
> > +static inline void ts_add_ns(struct xn_timespec64 *ts, int ns)
> > +{
> > +	ts->tv_nsec += ns;
> > +	ts_normalise(ts);
> > +}
> > +
> > +/**
> > + * Compare two struct timespec instances
> > + *
> > + * @param a
> > + * @param b
> > + * @return True if a < b, false otherwise
> > + */
> > +static inline bool ts_less(const struct xn_timespec64 *a,
> > +			   const struct xn_timespec64 *b)
> > +{
> > +	if (a->tv_sec < b->tv_sec)
> > +		return true;
> > +
> > +	if (a->tv_sec > b->tv_sec)
> > +		return false;
> > +
> > +	/* a->tv_sec == b->tv_sec */
> > +
> > +	if (a->tv_nsec < b->tv_nsec)
> > +		return true;
> > +
> > +	return false;
> > +}
> > +
> > +static int test_sc_cobalt_sem_timedwait_time64(void)
> > +{
> > +	long ret;
> > +	sem_t sem;
> > +	int code = __xn_syscode(sc_cobalt_sem_timedwait_time64);
> > +	struct xn_timespec64 ts64, ts_wu;
> > +	struct timespec ts_nat;
> > +
> > +	sem_init(&sem, 0, 0);
> > +
> > +	/*
> > +	 * TODO: Calling the syscall directly for now, as y2038 support is not
> > +	 * yet available in glibc. Once this is available we should use our
> > +	 * glibc wrappers provided by libcobalt.
> > +	 */
> 
> Maybe wrap that, to make the invocations more readable? Maybe a macro
> can do that in a way that will not affect the code once glibc is ready.

Not sure if that is possible, but will think about that. We shouldn't
limit our implementation to glibc only, there are other implementations
like musl out there as well.

The idea was to test the libcobalt libc wrappers here as well, but
maybe that is not an good idea. Even glibc has the y2038 in the future
it may not be activated by user code... So calling the syscall directly
might be right thing to do here, and just remove the TODO comment.

> 
> > +
> > +	/* Make sure we don't crash because of NULL pointers */
> > +	ret = syscall(code, NULL, NULL);
> > +	if (ret == -1 && errno == ENOSYS)
> > +		return 0; // Not implemented, nothing to test, success
> > +	if (!smokey_assert(ret == -1) || !smokey_assert(errno == EINVAL))
> > +		return errno;
> > +
> > +	/* Timeout is never read by the kernel, so NULL should be OK */
> > +	sem_post(&sem);
> > +	ret = syscall(code, &sem, NULL);
> > +	if (!smokey_assert(!ret))
> > +		return errno;
> > +
> > +	/*
> > +	 * The semaphore is already exhausted, so calling again will validate
> > +	 * the provided timeout now. Providing NULL has to deliver EFAULT
> > +	 */
> > +	ret = syscall(code, &sem, NULL);
> > +	if (!smokey_assert(ret == -1) || !smokey_assert(errno == EFAULT))
> > +		return errno;
> > +
> > +	/*
> > +	 * The semaphore is still exhausted, calling again will validate the
> > +	 * timeout, providing an invalid timeout has to deliver EINVAL
> > +	 */
> > +	ts64.tv_sec = -1;
> > +	ret = syscall(code, &sem, &ts64);
> > +	if (!smokey_assert(ret == -1) || !smokey_assert(errno == EINVAL))
> > +		return errno;
> > +
> > +	/*
> > +	 * Providing a valid timeout, waiting for it to time out and check
> > +	 * that we didn't come back to early.
> > +	 */
> > +	ret = clock_gettime(CLOCK_MONOTONIC, &ts_nat);
> > +	if (ret)
> > +		return errno;
> > +
> > +	ts64.tv_sec = ts_nat.tv_sec;
> > +	ts64.tv_nsec = ts_nat.tv_nsec;
> > +	ts_add_ns(&ts64, 500000);
> > +
> > +	ret = syscall(code, &sem, &ts64);
> > +	if (!smokey_assert(ret == -1) || !smokey_assert(errno == ETIMEDOUT))
> > +		return errno;
> > +
> > +	ret = clock_gettime(CLOCK_MONOTONIC, &ts_nat);
> > +	if (ret)
> > +		return errno;
> > +
> > +	ts_wu.tv_sec = ts_nat.tv_sec;
> > +	ts_wu.tv_nsec = ts_nat.tv_nsec;
> > +
> > +	if (ts_less(&ts_wu, &ts64))
> > +		smokey_warning("sem_timedwait_time64 returned to early!\n"
> > +			       "Expected wakeup at: %lld sec %lld nsec\n"
> > +			       "Back at           : %lld sec %lld nsec\n",
> > +			       ts64.tv_sec, ts64.tv_nsec, ts_wu.tv_sec,
> > +			       ts_wu.tv_nsec);
> > +
> 
> Does this already stress the 64-bit range of time_t? I don't spot that yet.
> 
> > +	return 0;
> > +}
> > +
> > +static int run_y2038(struct smokey_test *t, int argc, char *const argv[])
> > +{
> > +	int ret;
> > +
> > +	ret = test_sc_cobalt_sem_timedwait_time64();
> > +	if (ret)
> > +		return ret;
> > +
> > +	return 0;
> > +}
> > 
> 
> Such a test is obviously key to approach the issue correctly. It's a
> complex beast.
> 
> Jan
> 


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

* Re: [RFC PATCH v2 1/4] y2038: Fixing the sem_timedwait syscall for 32 bit systems
  2021-03-08 17:02                         ` [RFC PATCH v2 1/4] y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
  2021-03-08 17:12                           ` Jan Kiszka
@ 2021-03-09  9:46                           ` Philippe Gerum
  2021-03-09 11:08                             ` florian.bezdeka
  1 sibling, 1 reply; 57+ messages in thread
From: Philippe Gerum @ 2021-03-09  9:46 UTC (permalink / raw)
  To: Florian Bezdeka; +Cc: xenomai, jan.kiszka, chensong


Florian Bezdeka <florian.bezdeka@siemens.com> writes:

> On systems using 32 bit for time_t the sem_timedwait syscall was broken
> because the function used for copying the timeout value from userspace
> to kernel (=sem_fetch_timeout()) was always copying
> sizeof(struct timespec64).
>
> A 32 bit application (or more specific an application with 4 byte
> time_t) would only provide sizeof(struct old_timespec32).
>
> Notable changes:
>   - The copy operation from userspace to kernel is now already done in
>     the syscall handler. So it is always done. Previously it was copied
>     over and validated before the first use (when used at all).
>     So we have some additional instructions now that may be
>     unnecessary, but that simplifies the code.
>
>   - Validation: Switched to timespec64_valid() instead of our own
>     check.
>
> Fixes: 8043eccd232d ("cobalt/kernel: y2038: convert struct timespec to timespec64")
> Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
> ---
>  kernel/cobalt/posix/sem.c       | 40 +++++++++++++++------------------
>  kernel/cobalt/posix/sem.h       |  6 ++---
>  kernel/cobalt/posix/syscall32.c | 10 +++++++--
>  kernel/cobalt/posix/syscall32.h |  2 +-
>  4 files changed, 29 insertions(+), 29 deletions(-)
>
> diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
> index 467a9b7dd..827a4751a 100644
> --- a/kernel/cobalt/posix/sem.c
> +++ b/kernel/cobalt/posix/sem.c
> @@ -267,20 +267,11 @@ out:
>  	return ret;
>  }
>  
> -static inline int sem_fetch_timeout(struct timespec64 *ts,
> -				    const void __user *u_ts)
> -{
> -	return u_ts == NULL ? -EFAULT :
> -		cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
> -}
> -
>  int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
> -			   const void __user *u_ts,
> -			   int (*fetch_timeout)(struct timespec64 *ts,
> -						const void __user *u_ts))
> +			   const struct timespec64 *ts)
>  {
> -	struct timespec64 ts = { .tv_sec = 0, .tv_nsec = 0 };
> -	int pull_ts = 1, ret, info;
> +	int ret, info;
> +	bool validate_ts = true;
>  	struct cobalt_sem *sem;
>  	xnhandle_t handle;
>  	xntmode_t tmode;
> @@ -304,24 +295,23 @@ int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
>  		 * it's actually more complex, to keep some
>  		 * applications ported to Linux happy.
>  		 */
> -		if (pull_ts) {
> +		if (validate_ts) {
>  			atomic_inc(&sem->state->value);
> -			xnlock_put_irqrestore(&nklock, s);
> -			ret = fetch_timeout(&ts, u_ts);
> -			xnlock_get_irqsave(&nklock, s);
> -			if (ret)

As mentioned in a previous comment on this series, this type of patch is
subtly changing where the core currently stands with respect to a
peculiar POSIX compliance issue. Checking the content of a valid
timespec struct is currently postponed until the timeout is needed, but
the validity of the timespec pointer referring to that information is
checked as late as possible too.

If the code now pre-loads the timespec struct early on in the syscall
path, before the timed services are called, the pointer is explicitly
checked for validity before we can decide if that timeout information is
going to be used.

e.g.

struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000000 };
sem_init(&sem, 0, 0);
sem_post(&sem);
sem_timedwait(&sem, &ts); /* should not fail, and won't as expected. */

but,

sem_init(&sem, 0, 0);
sem_post(&sem);
sem_timedwait(&sem, (void *)0xdeadbeefUL); /* should not fail, but will. */

Since the standard does not mandates such behavior but seems to tag it
as an implementation-dependent option ("The validity of the abstime need
not be checked if..."), the change would still be acceptable POSIX-wise
I believe. However, I'm pretty sure that there are POSIX compliance test
suites around which would start reporting failures due to this
change.

-- 
Philippe.


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

* Re: [RFC PATCH v2 1/4] y2038: Fixing the sem_timedwait syscall for 32 bit systems
  2021-03-09  9:46                           ` Philippe Gerum
@ 2021-03-09 11:08                             ` florian.bezdeka
  0 siblings, 0 replies; 57+ messages in thread
From: florian.bezdeka @ 2021-03-09 11:08 UTC (permalink / raw)
  To: rpm; +Cc: xenomai, jan.kiszka, chensong

On Tue, 2021-03-09 at 10:46 +0100, Philippe Gerum wrote:
> Florian Bezdeka <florian.bezdeka@siemens.com> writes:
> 
> > On systems using 32 bit for time_t the sem_timedwait syscall was broken
> > because the function used for copying the timeout value from userspace
> > to kernel (=sem_fetch_timeout()) was always copying
> > sizeof(struct timespec64).
> > 
> > A 32 bit application (or more specific an application with 4 byte
> > time_t) would only provide sizeof(struct old_timespec32).
> > 
> > Notable changes:
> >   - The copy operation from userspace to kernel is now already done in
> >     the syscall handler. So it is always done. Previously it was copied
> >     over and validated before the first use (when used at all).
> >     So we have some additional instructions now that may be
> >     unnecessary, but that simplifies the code.
> > 
> >   - Validation: Switched to timespec64_valid() instead of our own
> >     check.
> > 
> > Fixes: 8043eccd232d ("cobalt/kernel: y2038: convert struct timespec to timespec64")
> > Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
> > ---
> >  kernel/cobalt/posix/sem.c       | 40 +++++++++++++++------------------
> >  kernel/cobalt/posix/sem.h       |  6 ++---
> >  kernel/cobalt/posix/syscall32.c | 10 +++++++--
> >  kernel/cobalt/posix/syscall32.h |  2 +-
> >  4 files changed, 29 insertions(+), 29 deletions(-)
> > 
> > diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
> > index 467a9b7dd..827a4751a 100644
> > --- a/kernel/cobalt/posix/sem.c
> > +++ b/kernel/cobalt/posix/sem.c
> > @@ -267,20 +267,11 @@ out:
> >  	return ret;
> >  }
> >  
> > 
> > 
> > 
> > -static inline int sem_fetch_timeout(struct timespec64 *ts,
> > -				    const void __user *u_ts)
> > -{
> > -	return u_ts == NULL ? -EFAULT :
> > -		cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
> > -}
> > -
> >  int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
> > -			   const void __user *u_ts,
> > -			   int (*fetch_timeout)(struct timespec64 *ts,
> > -						const void __user *u_ts))
> > +			   const struct timespec64 *ts)
> >  {
> > -	struct timespec64 ts = { .tv_sec = 0, .tv_nsec = 0 };
> > -	int pull_ts = 1, ret, info;
> > +	int ret, info;
> > +	bool validate_ts = true;
> >  	struct cobalt_sem *sem;
> >  	xnhandle_t handle;
> >  	xntmode_t tmode;
> > @@ -304,24 +295,23 @@ int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
> >  		 * it's actually more complex, to keep some
> >  		 * applications ported to Linux happy.
> >  		 */
> > -		if (pull_ts) {
> > +		if (validate_ts) {
> >  			atomic_inc(&sem->state->value);
> > -			xnlock_put_irqrestore(&nklock, s);
> > -			ret = fetch_timeout(&ts, u_ts);
> > -			xnlock_get_irqsave(&nklock, s);
> > -			if (ret)
> 
> As mentioned in a previous comment on this series, this type of patch is
> subtly changing where the core currently stands with respect to a
> peculiar POSIX compliance issue. Checking the content of a valid
> timespec struct is currently postponed until the timeout is needed, but
> the validity of the timespec pointer referring to that information is
> checked as late as possible too.

I took care of that comment. Please note that "ts" supplied to
__cobalt_sem_timedwait() is non NULL only if it could be properly read.
If the read failed (inside the handler) we will not return an error.
The error will occur when trying to validate later.

> 
> If the code now pre-loads the timespec struct early on in the syscall
> path, before the timed services are called, the pointer is explicitly
> checked for validity before we can decide if that timeout information is
> going to be used.
> 
> e.g.
> 
> struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000000 };
> sem_init(&sem, 0, 0);
> sem_post(&sem);
> sem_timedwait(&sem, &ts); /* should not fail, and won't as expected. */

This is already part of the smokey y2038 plugin, and does not fail.

> 
> but,
> 
> sem_init(&sem, 0, 0);
> sem_post(&sem);
> sem_timedwait(&sem, (void *)0xdeadbeefUL); /* should not fail, but will. */
> 

This is not yet part of the y2038 smokey tests, but works (= does not
fail). I will add it to the tests as well.

> Since the standard does not mandates such behavior but seems to tag it
> as an implementation-dependent option ("The validity of the abstime need
> not be checked if..."), the change would still be acceptable POSIX-wise
> I believe. However, I'm pretty sure that there are POSIX compliance test
> suites around which would start reporting failures due to this
> change.
> 


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

* Re: [RFC PATCH v2 2/4] y2038: Adding sem_timedwait_time64
  2021-03-09  7:53                             ` florian.bezdeka
@ 2021-03-10  7:51                               ` florian.bezdeka
  2021-03-10  9:46                                 ` chensong
  0 siblings, 1 reply; 57+ messages in thread
From: florian.bezdeka @ 2021-03-10  7:51 UTC (permalink / raw)
  To: rpm, xenomai, jan.kiszka, chensong

On Tue, 2021-03-09 at 07:53 +0000, florian.bezdeka--- via Xenomai
wrote:
> On Mon, 2021-03-08 at 19:28 +0100, Jan Kiszka wrote:
> > On 08.03.21 18:02, Florian Bezdeka wrote:
> > > Implementation is heavily inspired by the sem_timedwait syscall,
> > > but expecting time64 based timespec / timeout.
> > > 
> > > [snip]
> > > @@ -82,6 +83,28 @@ static inline int cobalt_strncpy_from_user(char *dst, const char __user *src,
> > >  	return __xn_strncpy_from_user(dst, src, count);
> > >  }
> > >  
> > > +static inline int cobalt_get_timespec64(struct timespec64 *ts,
> > > +				const struct __kernel_timespec __user *uts)
> > > +{
> > > +	struct __kernel_timespec kts;
> > > +	int ret;
> > > +
> > > +	ret = cobalt_copy_from_user(&kts, uts, sizeof(kts));
> > > +	if (ret)
> > > +		return -EFAULT;
> > > +
> > > +	ts->tv_sec = kts.tv_sec;
> > > +
> > > +	/* Zero out the padding in compat mode */
> > > +	if (in_compat_syscall())
> > > +		kts.tv_nsec &= 0xFFFFFFFFUL;
> > > +
> > > +	/* In 32-bit mode, this drops the padding */
> > > +	ts->tv_nsec = kts.tv_nsec;
> > > +
> > > +	return 0;
> > > +}
> > > +
> > 
> > Why inline? But that question is likely obsolete when we can avoid the
> > code duplication below.
> 
> Inline can be removed. Something for v3. There will follow more calls
> to that helper. All syscalls reading a struct timespec from userspace
> will have to use it.
> > > 

I was following the pattern of all the other struct timespec64 heplers
introduced by Philippe here. So "static inline". Removing "inline" now
throws some warnings (at least on gcc 10), because the function is
unused in this file.

So my question is now: Where should this function reside?

Linux pattern: kernel/time/time.c (where get_timespec64 resides)
Xenomai path would be kernel/cobalt/time.c

This is the last thing I have to address. A non RFC series will follow
afterwards, based on Philippe's tree.

@Song: My hope was this series can be used as pattern, to start
integration of all the other remaining parts. What do you think? Is
that sufficient?
- 

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

* Re: [RFC PATCH v2 2/4] y2038: Adding sem_timedwait_time64
  2021-03-10  7:51                               ` florian.bezdeka
@ 2021-03-10  9:46                                 ` chensong
  0 siblings, 0 replies; 57+ messages in thread
From: chensong @ 2021-03-10  9:46 UTC (permalink / raw)
  To: florian.bezdeka, rpm, xenomai, jan.kiszka, chensong



On 2021年03月10日 15:51, florian.bezdeka--- via Xenomai wrote:
> On Tue, 2021-03-09 at 07:53 +0000, florian.bezdeka--- via Xenomai
> wrote:
>> On Mon, 2021-03-08 at 19:28 +0100, Jan Kiszka wrote:
>>> On 08.03.21 18:02, Florian Bezdeka wrote:
>>>> Implementation is heavily inspired by the sem_timedwait syscall,
>>>> but expecting time64 based timespec / timeout.
>>>>
>>>> [snip]
>>>> @@ -82,6 +83,28 @@ static inline int cobalt_strncpy_from_user(char *dst, const char __user *src,
>>>>   	return __xn_strncpy_from_user(dst, src, count);
>>>>   }
>>>>
>>>> +static inline int cobalt_get_timespec64(struct timespec64 *ts,
>>>> +				const struct __kernel_timespec __user *uts)
>>>> +{
>>>> +	struct __kernel_timespec kts;
>>>> +	int ret;
>>>> +
>>>> +	ret = cobalt_copy_from_user(&kts, uts, sizeof(kts));
>>>> +	if (ret)
>>>> +		return -EFAULT;
>>>> +
>>>> +	ts->tv_sec = kts.tv_sec;
>>>> +
>>>> +	/* Zero out the padding in compat mode */
>>>> +	if (in_compat_syscall())
>>>> +		kts.tv_nsec &= 0xFFFFFFFFUL;
>>>> +
>>>> +	/* In 32-bit mode, this drops the padding */
>>>> +	ts->tv_nsec = kts.tv_nsec;
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>
>>> Why inline? But that question is likely obsolete when we can avoid the
>>> code duplication below.
>>
>> Inline can be removed. Something for v3. There will follow more calls
>> to that helper. All syscalls reading a struct timespec from userspace
>> will have to use it.
>>>>
>
> I was following the pattern of all the other struct timespec64 heplers
> introduced by Philippe here. So "static inline". Removing "inline" now
> throws some warnings (at least on gcc 10), because the function is
> unused in this file.
>
> So my question is now: Where should this function reside?
>
> Linux pattern: kernel/time/time.c (where get_timespec64 resides)
> Xenomai path would be kernel/cobalt/time.c
>
> This is the last thing I have to address. A non RFC series will follow
> afterwards, based on Philippe's tree.
>
> @Song: My hope was this series can be used as pattern, to start
> integration of all the other remaining parts. What do you think? Is
> that sufficient?

This series look good to me and i'm following it to work on my patches.

Song
> -
>




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

* [y2038][PATCH v3 0/4] Pattern for implementing y2038 syscalls
  2021-03-08 17:02                         ` [RFC PATCH v2 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait_time64 Florian Bezdeka
@ 2021-03-10 13:09                           ` Florian Bezdeka
  2021-03-10 13:09                             ` [y2038][PATCH v3 1/4] y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
                                               ` (3 more replies)
  0 siblings, 4 replies; 57+ messages in thread
From: Florian Bezdeka @ 2021-03-10 13:09 UTC (permalink / raw)
  To: xenomai, jan.kiszka, rpm, chensong

This series was tested against the following branches:
  - upstream: wip/dovetail
  - philippe-private: for-upstream/dovetail

Song can take this series as template and continue to bring in more
y2038 syscalls, while I will go and fixup some of the things that are
alredy broken (on 32 bit systems).

Changes in v3:
  - Removed RFC tag
  - Extended tests to cover one of the POSIX edge cases found during
    review 
                                                                                    
Changes in v2:                                                                      
  - Added a smokey plugin named y2038 for running Y2038 related tests               
    (Should be extended with all related tests)                                     
  - Review implementations (covered by tests now as well)                           
  - Drop support for kernel 4.4                                                     
  - Added the libcobalt part 

Florian Bezdeka (4):
  y2038: Fixing the sem_timedwait syscall for 32 bit systems
  y2038: Adding sem_timedwait64
  y2038: Add tests for the sc_cobalt_sem_timedwait64 syscall
  y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64

 configure.ac                           |   1 +
 include/cobalt/kernel/time.h           |  22 ++++
 include/cobalt/uapi/syscall.h          |   1 +
 kernel/cobalt/Makefile                 |   1 +
 kernel/cobalt/posix/sem.c              |  60 +++++----
 kernel/cobalt/posix/sem.h              |  13 +-
 kernel/cobalt/posix/syscall32.c        |  17 ++-
 kernel/cobalt/posix/syscall32.h        |   6 +-
 kernel/cobalt/time.c                   |  29 ++++
 lib/cobalt/semaphore.c                 |   5 +
 testsuite/smokey/Makefile.am           |   6 +-
 testsuite/smokey/y2038/Makefile.am     |  10 ++
 testsuite/smokey/y2038/syscall-tests.c | 175 +++++++++++++++++++++++++
 13 files changed, 315 insertions(+), 31 deletions(-)
 create mode 100644 include/cobalt/kernel/time.h
 create mode 100644 kernel/cobalt/time.c
 create mode 100644 testsuite/smokey/y2038/Makefile.am
 create mode 100644 testsuite/smokey/y2038/syscall-tests.c

-- 
2.29.2



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

* [y2038][PATCH v3 1/4] y2038: Fixing the sem_timedwait syscall for 32 bit systems
  2021-03-10 13:09                           ` [y2038][PATCH v3 0/4] Pattern for implementing y2038 syscalls Florian Bezdeka
@ 2021-03-10 13:09                             ` Florian Bezdeka
  2021-03-10 13:09                             ` [y2038][PATCH v3 2/4] y2038: Adding sem_timedwait64 Florian Bezdeka
                                               ` (2 subsequent siblings)
  3 siblings, 0 replies; 57+ messages in thread
From: Florian Bezdeka @ 2021-03-10 13:09 UTC (permalink / raw)
  To: xenomai, jan.kiszka, rpm, chensong

On systems using 32 bit for time_t the sem_timedwait syscall was broken
because the function used for copying the timeout value from userspace
to kernel (=sem_fetch_timeout()) was always copying
sizeof(struct timespec64).

A 32 bit application (or more specific an application with 4 byte
time_t) would only provide sizeof(struct old_timespec32).

Notable changes:
  - The copy operation from userspace to kernel is now already done in
    the syscall handler. So it is always done and might fail. Reporting
    a failure is delayed until the timeout is being validated.

  - Validation: Switched to timespec64_valid() instead of our own
    check.

Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
 kernel/cobalt/posix/sem.c       | 40 +++++++++++++++------------------
 kernel/cobalt/posix/sem.h       |  6 ++---
 kernel/cobalt/posix/syscall32.c | 10 +++++++--
 kernel/cobalt/posix/syscall32.h |  2 +-
 4 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
index 467a9b7dd..827a4751a 100644
--- a/kernel/cobalt/posix/sem.c
+++ b/kernel/cobalt/posix/sem.c
@@ -267,20 +267,11 @@ out:
 	return ret;
 }
 
-static inline int sem_fetch_timeout(struct timespec64 *ts,
-				    const void __user *u_ts)
-{
-	return u_ts == NULL ? -EFAULT :
-		cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
-}
-
 int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
-			   const void __user *u_ts,
-			   int (*fetch_timeout)(struct timespec64 *ts,
-						const void __user *u_ts))
+			   const struct timespec64 *ts)
 {
-	struct timespec64 ts = { .tv_sec = 0, .tv_nsec = 0 };
-	int pull_ts = 1, ret, info;
+	int ret, info;
+	bool validate_ts = true;
 	struct cobalt_sem *sem;
 	xnhandle_t handle;
 	xntmode_t tmode;
@@ -304,24 +295,23 @@ int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
 		 * it's actually more complex, to keep some
 		 * applications ported to Linux happy.
 		 */
-		if (pull_ts) {
+		if (validate_ts) {
 			atomic_inc(&sem->state->value);
-			xnlock_put_irqrestore(&nklock, s);
-			ret = fetch_timeout(&ts, u_ts);
-			xnlock_get_irqsave(&nklock, s);
-			if (ret)
+			if (!ts) {
+				ret = -EFAULT;
 				break;
-			if (ts.tv_nsec >= ONE_BILLION) {
+			}
+			if (!timespec64_valid(ts)) {
 				ret = -EINVAL;
 				break;
 			}
-			pull_ts = 0;
+			validate_ts = false;
 			continue;
 		}
 
 		ret = 0;
 		tmode = sem->flags & SEM_RAWCLOCK ? XN_ABSOLUTE : XN_REALTIME;
-		info = xnsynch_sleep_on(&sem->synchbase, ts2ns(&ts) + 1, tmode);
+		info = xnsynch_sleep_on(&sem->synchbase, ts2ns(ts) + 1, tmode);
 		if (info & XNRMID)
 			ret = -EINVAL;
 		else if (info & (XNBREAK|XNTIMEO)) {
@@ -434,9 +424,15 @@ COBALT_SYSCALL(sem_wait, primary,
 
 COBALT_SYSCALL(sem_timedwait, primary,
 	       (struct cobalt_sem_shadow __user *u_sem,
-		struct __user_old_timespec __user *u_ts))
+		const struct __user_old_timespec __user *u_ts))
 {
-	return __cobalt_sem_timedwait(u_sem, u_ts, sem_fetch_timeout);
+	int ret = 1;
+	struct timespec64 ts64;
+
+	if (u_ts)
+		ret = cobalt_get_u_timespec(&ts64, u_ts);
+
+	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
 }
 
 COBALT_SYSCALL(sem_trywait, primary,
diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h
index d17299495..658e11f7a 100644
--- a/kernel/cobalt/posix/sem.h
+++ b/kernel/cobalt/posix/sem.h
@@ -64,9 +64,7 @@ __cobalt_sem_open(struct cobalt_sem_shadow __user *usm,
 		  int oflags, mode_t mode, unsigned int value);
 
 int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
-			   const void __user *u_ts,
-			   int (*fetch_timeout)(struct timespec64 *ts,
-						const void __user *u_ts));
+			   const struct timespec64 *ts);
 
 int __cobalt_sem_destroy(xnhandle_t handle);
 
@@ -91,7 +89,7 @@ COBALT_SYSCALL_DECL(sem_wait,
 
 COBALT_SYSCALL_DECL(sem_timedwait,
 		    (struct cobalt_sem_shadow __user *u_sem,
-		     struct __user_old_timespec __user *u_ts));
+		     const struct __user_old_timespec __user *u_ts));
 
 COBALT_SYSCALL_DECL(sem_trywait,
 		    (struct cobalt_sem_shadow __user *u_sem));
diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
index b83944089..bc60a81a7 100644
--- a/kernel/cobalt/posix/syscall32.c
+++ b/kernel/cobalt/posix/syscall32.c
@@ -124,9 +124,15 @@ COBALT_SYSCALL32emu(sem_open, lostage,
 
 COBALT_SYSCALL32emu(sem_timedwait, primary,
 		    (struct cobalt_sem_shadow __user *u_sem,
-		     struct old_timespec32 __user *u_ts))
+		     const struct old_timespec32 __user *u_ts))
 {
-	return __cobalt_sem_timedwait(u_sem, u_ts, sys32_fetch_timeout);
+	int ret = 1;
+	struct timespec64 ts64;
+
+	if (u_ts)
+		ret = sys32_fetch_timeout(&ts64, u_ts);
+
+	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
 }
 
 COBALT_SYSCALL32emu(clock_getres, current,
diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h
index 936343fa4..d5b07da86 100644
--- a/kernel/cobalt/posix/syscall32.h
+++ b/kernel/cobalt/posix/syscall32.h
@@ -223,6 +223,6 @@ COBALT_SYSCALL32emu_DECL(sem_open,
 
 COBALT_SYSCALL32emu_DECL(sem_timedwait,
 			 (struct cobalt_sem_shadow __user *u_sem,
-			  struct old_timespec32 __user *u_ts));
+			  const struct old_timespec32 __user *u_ts));
 
 #endif /* !_COBALT_POSIX_SYSCALL32_H */
-- 
2.29.2



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

* [y2038][PATCH v3 2/4] y2038: Adding sem_timedwait64
  2021-03-10 13:09                           ` [y2038][PATCH v3 0/4] Pattern for implementing y2038 syscalls Florian Bezdeka
  2021-03-10 13:09                             ` [y2038][PATCH v3 1/4] y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
@ 2021-03-10 13:09                             ` Florian Bezdeka
  2021-03-10 13:09                             ` [y2038][PATCH v3 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait64 syscall Florian Bezdeka
  2021-03-10 13:09                             ` [y2038][PATCH v3 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64 Florian Bezdeka
  3 siblings, 0 replies; 57+ messages in thread
From: Florian Bezdeka @ 2021-03-10 13:09 UTC (permalink / raw)
  To: xenomai, jan.kiszka, rpm, chensong

Implementation is heavily inspired by the sem_timedwait syscall,
but expecting time64 based timespec / timeout.

We need two new syscall handlers:
  - The native one (COBALT_SYSCALL()) to get 32 bit kernels time64
    aware. This handler is added for 64 bit kernels as well, but not
    used. As we don't have separate syscall tables for this both
    worlds we have to add it.

 - The compat handler (COBALT_SYSCALL32emu()) for x32 or x86
   applications running on an x86_64 kernel. Otherwise the redirection
   to the compat / emulation syscalls is broken.

Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
 include/cobalt/kernel/time.h    | 22 ++++++++++++++++++++++
 include/cobalt/uapi/syscall.h   |  1 +
 kernel/cobalt/Makefile          |  1 +
 kernel/cobalt/posix/sem.c       | 20 ++++++++++++++++++++
 kernel/cobalt/posix/sem.h       |  7 +++++++
 kernel/cobalt/posix/syscall32.c |  7 +++++++
 kernel/cobalt/posix/syscall32.h |  4 ++++
 kernel/cobalt/time.c            | 29 +++++++++++++++++++++++++++++
 8 files changed, 91 insertions(+)
 create mode 100644 include/cobalt/kernel/time.h
 create mode 100644 kernel/cobalt/time.c

diff --git a/include/cobalt/kernel/time.h b/include/cobalt/kernel/time.h
new file mode 100644
index 000000000..19e8f2c56
--- /dev/null
+++ b/include/cobalt/kernel/time.h
@@ -0,0 +1,22 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _COBALT_KERNEL_TIME_H
+#define _COBALT_KERNEL_TIME_H
+
+#include <linux/time.h>
+#include <linux/time64.h>
+
+/**
+ * Read struct __kernel_timespec from userspace and convert to
+ * struct timespec64
+ *
+ * @param ts The destination, will be filled
+ * @param uts The source, provided by an application
+ * @return 0 on success, -EFAULT otherwise
+ */
+int cobalt_get_timespec64(struct timespec64 *ts,
+			  const struct __kernel_timespec __user *uts);
+
+#endif //_COBALT_KERNEL_TIME_H
diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
index aa3c308d0..8895d2bff 100644
--- a/include/cobalt/uapi/syscall.h
+++ b/include/cobalt/uapi/syscall.h
@@ -122,6 +122,7 @@
 #define sc_cobalt_sendmmsg			99
 #define sc_cobalt_clock_adjtime			100
 #define sc_cobalt_thread_setschedprio		101
+#define sc_cobalt_sem_timedwait64		102
 
 #define __NR_COBALT_SYSCALLS			128 /* Power of 2 */
 
diff --git a/kernel/cobalt/Makefile b/kernel/cobalt/Makefile
index 129005d8f..6cd2d5994 100644
--- a/kernel/cobalt/Makefile
+++ b/kernel/cobalt/Makefile
@@ -13,6 +13,7 @@ xenomai-y :=	arith.o 	\
 		select.o	\
 		synch.o		\
 		thread.o	\
+		time.o		\
 		timer.o		\
 		tree.o
 
diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
index 827a4751a..72b20c78d 100644
--- a/kernel/cobalt/posix/sem.c
+++ b/kernel/cobalt/posix/sem.c
@@ -19,6 +19,7 @@
 
 #include <stddef.h>
 #include <linux/err.h>
+#include <cobalt/kernel/time.h>
 #include "internal.h"
 #include "thread.h"
 #include "clock.h"
@@ -326,6 +327,18 @@ int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
 	return ret;
 }
 
+int __cobalt_sem_timedwait64(struct cobalt_sem_shadow __user *u_sem,
+			     const struct __kernel_timespec __user *u_ts)
+{
+	int ret = 1;
+	struct timespec64 ts64;
+
+	if (u_ts)
+		ret = cobalt_get_timespec64(&ts64, u_ts);
+
+	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
+}
+
 static int sem_post(xnhandle_t handle)
 {
 	struct cobalt_sem *sem;
@@ -435,6 +448,13 @@ COBALT_SYSCALL(sem_timedwait, primary,
 	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
 }
 
+COBALT_SYSCALL(sem_timedwait64, primary,
+	       (struct cobalt_sem_shadow __user *u_sem,
+		const struct __kernel_timespec __user *u_ts))
+{
+	return __cobalt_sem_timedwait64(u_sem, u_ts);
+}
+
 COBALT_SYSCALL(sem_trywait, primary,
 	       (struct cobalt_sem_shadow __user *u_sem))
 {
diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h
index 658e11f7a..d7dbb9098 100644
--- a/kernel/cobalt/posix/sem.h
+++ b/kernel/cobalt/posix/sem.h
@@ -66,6 +66,9 @@ __cobalt_sem_open(struct cobalt_sem_shadow __user *usm,
 int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
 			   const struct timespec64 *ts);
 
+int __cobalt_sem_timedwait64(struct cobalt_sem_shadow __user *u_sem,
+			     const struct __kernel_timespec __user *u_ts);
+
 int __cobalt_sem_destroy(xnhandle_t handle);
 
 void cobalt_nsem_reclaim(struct cobalt_process *process);
@@ -91,6 +94,10 @@ COBALT_SYSCALL_DECL(sem_timedwait,
 		    (struct cobalt_sem_shadow __user *u_sem,
 		     const struct __user_old_timespec __user *u_ts));
 
+COBALT_SYSCALL_DECL(sem_timedwait64,
+		    (struct cobalt_sem_shadow __user *u_sem,
+		     const struct __kernel_timespec __user *u_ts));
+
 COBALT_SYSCALL_DECL(sem_trywait,
 		    (struct cobalt_sem_shadow __user *u_sem));
 
diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
index bc60a81a7..8bc74e997 100644
--- a/kernel/cobalt/posix/syscall32.c
+++ b/kernel/cobalt/posix/syscall32.c
@@ -135,6 +135,13 @@ COBALT_SYSCALL32emu(sem_timedwait, primary,
 	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
 }
 
+COBALT_SYSCALL32emu(sem_timedwait64, primary,
+		    (struct cobalt_sem_shadow __user *u_sem,
+		     const struct __kernel_timespec __user *u_ts))
+{
+	return __cobalt_sem_timedwait64(u_sem, u_ts);
+}
+
 COBALT_SYSCALL32emu(clock_getres, current,
 		    (clockid_t clock_id,
 		     struct old_timespec32 __user *u_ts))
diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h
index d5b07da86..c2e4bf355 100644
--- a/kernel/cobalt/posix/syscall32.h
+++ b/kernel/cobalt/posix/syscall32.h
@@ -225,4 +225,8 @@ COBALT_SYSCALL32emu_DECL(sem_timedwait,
 			 (struct cobalt_sem_shadow __user *u_sem,
 			  const struct old_timespec32 __user *u_ts));
 
+COBALT_SYSCALL32emu_DECL(sem_timedwait64,
+			 (struct cobalt_sem_shadow __user * u_sem,
+			  const struct __kernel_timespec __user *u_ts));
+
 #endif /* !_COBALT_POSIX_SYSCALL32_H */
diff --git a/kernel/cobalt/time.c b/kernel/cobalt/time.c
new file mode 100644
index 000000000..a3fd8a740
--- /dev/null
+++ b/kernel/cobalt/time.c
@@ -0,0 +1,29 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <asm-generic/xenomai/syscall.h>
+#include <cobalt/kernel/time.h>
+#include <linux/compat.h>
+
+int cobalt_get_timespec64(struct timespec64 *ts,
+			  const struct __kernel_timespec __user *uts)
+{
+	struct __kernel_timespec kts;
+	int ret;
+
+	ret = cobalt_copy_from_user(&kts, uts, sizeof(kts));
+	if (ret)
+		return -EFAULT;
+
+	ts->tv_sec = kts.tv_sec;
+
+	/* Zero out the padding in compat mode */
+	if (in_compat_syscall())
+		kts.tv_nsec &= 0xFFFFFFFFUL;
+
+	/* In 32-bit mode, this drops the padding */
+	ts->tv_nsec = kts.tv_nsec;
+
+	return 0;
+}
-- 
2.29.2



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

* [y2038][PATCH v3 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait64 syscall
  2021-03-10 13:09                           ` [y2038][PATCH v3 0/4] Pattern for implementing y2038 syscalls Florian Bezdeka
  2021-03-10 13:09                             ` [y2038][PATCH v3 1/4] y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
  2021-03-10 13:09                             ` [y2038][PATCH v3 2/4] y2038: Adding sem_timedwait64 Florian Bezdeka
@ 2021-03-10 13:09                             ` Florian Bezdeka
  2021-03-10 13:09                             ` [y2038][PATCH v3 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64 Florian Bezdeka
  3 siblings, 0 replies; 57+ messages in thread
From: Florian Bezdeka @ 2021-03-10 13:09 UTC (permalink / raw)
  To: xenomai, jan.kiszka, rpm, chensong

Introducing a new smokey plugin that can be extended for all kind of
y2038 tests. For now we are testing the new sc_cobalt_sem_timedwait64
syscall without using any libc wrappers provided by libcobalt.

Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
 configure.ac                           |   1 +
 testsuite/smokey/Makefile.am           |   6 +-
 testsuite/smokey/y2038/Makefile.am     |  10 ++
 testsuite/smokey/y2038/syscall-tests.c | 175 +++++++++++++++++++++++++
 4 files changed, 190 insertions(+), 2 deletions(-)
 create mode 100644 testsuite/smokey/y2038/Makefile.am
 create mode 100644 testsuite/smokey/y2038/syscall-tests.c

diff --git a/configure.ac b/configure.ac
index abe538dbd..bd5fd5ba9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -990,6 +990,7 @@ AC_CONFIG_FILES([ \
 	testsuite/smokey/net_common/Makefile \
 	testsuite/smokey/cpu-affinity/Makefile \
 	testsuite/smokey/gdb/Makefile \
+	testsuite/smokey/y2038/Makefile \
 	testsuite/clocktest/Makefile \
 	testsuite/xeno-test/Makefile \
 	utils/Makefile \
diff --git a/testsuite/smokey/Makefile.am b/testsuite/smokey/Makefile.am
index 02613c7dc..56c873026 100644
--- a/testsuite/smokey/Makefile.am
+++ b/testsuite/smokey/Makefile.am
@@ -38,7 +38,8 @@ COBALT_SUBDIRS = 	\
 	timerfd		\
 	tsc		\
 	vdso-access 	\
-	xddp
+	xddp		\
+	y2038
 
 MERCURY_SUBDIRS =	\
 	memory-heapmem	\
@@ -76,7 +77,8 @@ DIST_SUBDIRS = 		\
 	timerfd		\
 	tsc		\
 	vdso-access 	\
-	xddp
+	xddp		\
+	y2038
 
 if XENO_COBALT
 if CONFIG_XENO_LIBS_DLOPEN
diff --git a/testsuite/smokey/y2038/Makefile.am b/testsuite/smokey/y2038/Makefile.am
new file mode 100644
index 000000000..a97591aa2
--- /dev/null
+++ b/testsuite/smokey/y2038/Makefile.am
@@ -0,0 +1,10 @@
+
+noinst_LIBRARIES = liby2038.a
+
+liby2038_a_SOURCES = syscall-tests.c
+
+liby2038_a_CPPFLAGS = 	\
+	@XENO_USER_CFLAGS@	\
+	-I$(top_srcdir)		\
+	-I$(top_srcdir)/include
+
diff --git a/testsuite/smokey/y2038/syscall-tests.c b/testsuite/smokey/y2038/syscall-tests.c
new file mode 100644
index 000000000..1d61bbd94
--- /dev/null
+++ b/testsuite/smokey/y2038/syscall-tests.c
@@ -0,0 +1,175 @@
+/*
+ * y2038 tests
+ *
+ * Copyright (c) Siemens AG 2021
+ *
+ * Authors:
+ *  Florian Bezdeka <florian.bezdeka@siemens.com>
+ *
+ * Released under the terms of GPLv2.
+ */
+#include <cobalt/uapi/syscall.h>
+#include <smokey/smokey.h>
+#include <semaphore.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <errno.h>
+
+smokey_test_plugin(y2038, SMOKEY_NOARGS, "Validate correct y2038 support");
+
+/*
+ * libc independent data type representing a time64_t based struct timespec
+ */
+struct xn_timespec64 {
+	int64_t tv_sec;
+	int64_t tv_nsec;
+};
+
+#define NSEC_PER_SEC 1000000000
+
+static void ts_normalise(struct xn_timespec64 *ts)
+{
+	while (ts->tv_nsec >= NSEC_PER_SEC) {
+		ts->tv_nsec += 1;
+		ts->tv_nsec -= NSEC_PER_SEC;
+	}
+
+	while (ts->tv_nsec <= -NSEC_PER_SEC) {
+		ts->tv_sec -= 1;
+		ts->tv_nsec += NSEC_PER_SEC;
+	}
+
+	if (ts->tv_nsec < 0) {
+		/*
+		 * Negative nanoseconds isn't valid according to POSIX.
+		 * Decrement tv_sec and roll tv_nsec over.
+		 */
+		ts->tv_sec -= 1;
+		ts->tv_nsec = (NSEC_PER_SEC + ts->tv_nsec);
+	}
+}
+
+static inline void ts_add_ns(struct xn_timespec64 *ts, int ns)
+{
+	ts->tv_nsec += ns;
+	ts_normalise(ts);
+}
+
+/**
+ * Compare two struct timespec instances
+ *
+ * @param a
+ * @param b
+ * @return True if a < b, false otherwise
+ */
+static inline bool ts_less(const struct xn_timespec64 *a,
+			   const struct xn_timespec64 *b)
+{
+	if (a->tv_sec < b->tv_sec)
+		return true;
+
+	if (a->tv_sec > b->tv_sec)
+		return false;
+
+	/* a->tv_sec == b->tv_sec */
+
+	if (a->tv_nsec < b->tv_nsec)
+		return true;
+
+	return false;
+}
+
+static int test_sc_cobalt_sem_timedwait64(void)
+{
+	long ret;
+	sem_t sem;
+	int code = __xn_syscode(sc_cobalt_sem_timedwait64);
+	struct xn_timespec64 ts64, ts_wu;
+	struct timespec ts_nat;
+
+	sem_init(&sem, 0, 0);
+
+	/* Make sure we don't crash because of NULL pointers */
+	ret = syscall(code, NULL, NULL);
+	if (ret == -1 && errno == ENOSYS) {
+		smokey_note("sem_timedwait64: skipped. (no kernel support)");
+		return 0; // Not implemented, nothing to test, success
+	}
+	if (!smokey_assert(ret == -1) || !smokey_assert(errno == EINVAL))
+		return errno;
+
+	/* Timeout is never read by the kernel, so NULL should be OK */
+	sem_post(&sem);
+	ret = syscall(code, &sem, NULL);
+	if (!smokey_assert(!ret))
+		return errno;
+
+	/*
+	 * The semaphore is already exhausted, so calling again will validate
+	 * the provided timeout now. Providing NULL has to deliver EFAULT
+	 */
+	ret = syscall(code, &sem, NULL);
+	if (!smokey_assert(ret == -1) || !smokey_assert(errno == EFAULT))
+		return errno;
+
+	/*
+	 * The semaphore is already exhausted, so calling again will validate
+	 * the provided timeout now. Providing an invalid adress has to deliver
+	 * EFAULT
+	 */
+	ret = syscall(code, &sem, (void*) 0xdeadbeefUL);
+	if (!smokey_assert(ret == -1) || !smokey_assert(errno == EFAULT))
+		return errno;
+
+	/*
+	 * The semaphore is still exhausted, calling again will validate the
+	 * timeout, providing an invalid timeout has to deliver EINVAL
+	 */
+	ts64.tv_sec = -1;
+	ret = syscall(code, &sem, &ts64);
+	if (!smokey_assert(ret == -1) || !smokey_assert(errno == EINVAL))
+		return errno;
+
+	/*
+	 * Providing a valid timeout, waiting for it to time out and check
+	 * that we didn't come back to early.
+	 */
+	ret = clock_gettime(CLOCK_MONOTONIC, &ts_nat);
+	if (ret)
+		return errno;
+
+	ts64.tv_sec = ts_nat.tv_sec;
+	ts64.tv_nsec = ts_nat.tv_nsec;
+	ts_add_ns(&ts64, 500000);
+
+	ret = syscall(code, &sem, &ts64);
+	if (!smokey_assert(ret == -1) || !smokey_assert(errno == ETIMEDOUT))
+		return errno;
+
+	ret = clock_gettime(CLOCK_MONOTONIC, &ts_nat);
+	if (ret)
+		return errno;
+
+	ts_wu.tv_sec = ts_nat.tv_sec;
+	ts_wu.tv_nsec = ts_nat.tv_nsec;
+
+	if (ts_less(&ts_wu, &ts64))
+		smokey_warning("sem_timedwait64 returned to early!\n"
+			       "Expected wakeup at: %lld sec %lld nsec\n"
+			       "Back at           : %lld sec %lld nsec\n",
+			       ts64.tv_sec, ts64.tv_nsec, ts_wu.tv_sec,
+			       ts_wu.tv_nsec);
+
+	return 0;
+}
+
+static int run_y2038(struct smokey_test *t, int argc, char *const argv[])
+{
+	int ret;
+
+	ret = test_sc_cobalt_sem_timedwait64();
+	if (ret)
+		return ret;
+
+	return 0;
+}
-- 
2.29.2



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

* [y2038][PATCH v3 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64
  2021-03-10 13:09                           ` [y2038][PATCH v3 0/4] Pattern for implementing y2038 syscalls Florian Bezdeka
                                               ` (2 preceding siblings ...)
  2021-03-10 13:09                             ` [y2038][PATCH v3 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait64 syscall Florian Bezdeka
@ 2021-03-10 13:09                             ` Florian Bezdeka
  2021-03-11  2:38                               ` chensong
  3 siblings, 1 reply; 57+ messages in thread
From: Florian Bezdeka @ 2021-03-10 13:09 UTC (permalink / raw)
  To: xenomai, jan.kiszka, rpm, chensong

In case libcobalt is build with -D_TIME_BITS=64
sc_cobalt_sem_timedwait64 will be used instead of
sc_cobalt_sem_timedwait.

Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
 lib/cobalt/semaphore.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lib/cobalt/semaphore.c b/lib/cobalt/semaphore.c
index 45705d48f..bff005440 100644
--- a/lib/cobalt/semaphore.c
+++ b/lib/cobalt/semaphore.c
@@ -373,7 +373,12 @@ COBALT_IMPL(int, sem_timedwait, (sem_t *sem, const struct timespec *abs_timeout)
 
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
 
+#ifdef __USE_TIME_BITS64
+	ret = XENOMAI_SYSCALL2(sc_cobalt_sem_timedwait64, _sem,
+			       abs_timeout);
+#else
 	ret = XENOMAI_SYSCALL2(sc_cobalt_sem_timedwait, _sem, abs_timeout);
+#endif
 
 	pthread_setcanceltype(oldtype, NULL);
 
-- 
2.29.2



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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-03-04 10:08           ` Philippe Gerum
  2021-03-04 11:36             ` [y2038][RFC PATCH 0/2] Pattern for implementing y2038 syscalls Florian Bezdeka
  2021-03-08 12:59             ` [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64 Jan Kiszka
@ 2021-03-10 17:52             ` florian.bezdeka
  2021-03-10 18:14               ` Philippe Gerum
  2 siblings, 1 reply; 57+ messages in thread
From: florian.bezdeka @ 2021-03-10 17:52 UTC (permalink / raw)
  To: rpm; +Cc: xenomai, jan.kiszka, chensong

On Thu, 2021-03-04 at 11:08 +0100, Philippe Gerum wrote:
> Philippe Gerum <rpm@xenomai.org> writes:
> 
> > florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:
> > 
> > > On Thu, 2021-03-04 at 10:35 +0100, Philippe Gerum wrote:
> > > > florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:
> > > > 
> > > > > On Sat, 2021-02-20 at 16:18 +0100, Philippe Gerum via Xenomai wrote:
> > > > > [snip]
> > > Adding the full code:
> > > 
> > > static inline int sem_fetch_timeout(struct timespec64 *ts,
> > > 				    const void __user *u_ts)
> > > {
> > > 	return u_ts == NULL ? -EFAULT :
> > > 		cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
> > > }
> > > 
> > > Copying sizeof(*ts) is to much if the application provided
> > > "__old_time_t" (sizeof(time_t) =4) only. Isn't it? I would expect the
> > > result (in ts) to be garbage. Due to different padding the "sec" field
> > > (in ts) would now contain the nsec value from u_ts as well.
> > > 
> > 
> > Ah, I was looking at the wrong path (32emu). Yes, this is broken for
> > mere 32bit now (i.e. natively 32bit platform).
> 
> We could simply use cobalt_get_u_timespec() instead of open coding the
> call to cobalt_copy_from_user(). Condvars have this right already,
> mutex, mq and sema4s have their fetch_timeout() helper broken
> indeed. Good spot.
> 

I had a look at the affected mutex syscalls today.
pthread_mutex_timedlock() has the well known "The validity of the
abs_timeout parameter need not be checked if the mutex can be locked
immediately." as well.

Could someone please confirm that Xenomai is already validating the
supplied timeout even if the mutex could be taken immediately? Maybe
I'm missing something.

Should we fix that as well? Any advice how to do so?

Starting point: 
__cobalt_mutex_timedlock_break()
	__cobalt_mutex_timedlock_break(): Validation before calling
		__cobalt_mutex_acquire_unchecked()

If I'm right, the problem was once fixed with:
860ea449a298 ("cobalt/posix/mutex: fix timeout handling in pthread_mutex_timedlock()")

but broken again in:
c53a9dd3ebc7 ("cobalt/posix/mutex: prepare for 32bit syscall emulation")


		

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

* Re: [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64
  2021-03-10 17:52             ` florian.bezdeka
@ 2021-03-10 18:14               ` Philippe Gerum
  0 siblings, 0 replies; 57+ messages in thread
From: Philippe Gerum @ 2021-03-10 18:14 UTC (permalink / raw)
  To: florian.bezdeka; +Cc: xenomai, jan.kiszka, chensong


florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:

> On Thu, 2021-03-04 at 11:08 +0100, Philippe Gerum wrote:
>> Philippe Gerum <rpm@xenomai.org> writes:
>> 
>> > florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:
>> > 
>> > > On Thu, 2021-03-04 at 10:35 +0100, Philippe Gerum wrote:
>> > > > florian.bezdeka@siemens.com <florian.bezdeka@siemens.com> writes:
>> > > > 
>> > > > > On Sat, 2021-02-20 at 16:18 +0100, Philippe Gerum via Xenomai wrote:
>> > > > > [snip]
>> > > Adding the full code:
>> > > 
>> > > static inline int sem_fetch_timeout(struct timespec64 *ts,
>> > > 				    const void __user *u_ts)
>> > > {
>> > > 	return u_ts == NULL ? -EFAULT :
>> > > 		cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
>> > > }
>> > > 
>> > > Copying sizeof(*ts) is to much if the application provided
>> > > "__old_time_t" (sizeof(time_t) =4) only. Isn't it? I would expect the
>> > > result (in ts) to be garbage. Due to different padding the "sec" field
>> > > (in ts) would now contain the nsec value from u_ts as well.
>> > > 
>> > 
>> > Ah, I was looking at the wrong path (32emu). Yes, this is broken for
>> > mere 32bit now (i.e. natively 32bit platform).
>> 
>> We could simply use cobalt_get_u_timespec() instead of open coding the
>> call to cobalt_copy_from_user(). Condvars have this right already,
>> mutex, mq and sema4s have their fetch_timeout() helper broken
>> indeed. Good spot.
>> 
>
> I had a look at the affected mutex syscalls today.
> pthread_mutex_timedlock() has the well known "The validity of the
> abs_timeout parameter need not be checked if the mutex can be locked
> immediately." as well.
>
> Could someone please confirm that Xenomai is already validating the
> supplied timeout even if the mutex could be taken immediately? Maybe
> I'm missing something.
>

Yes it does, and probably should not for consistency with other calls.

> Should we fix that as well? Any advice how to do so?
>
> Starting point: 
> __cobalt_mutex_timedlock_break()
> 	__cobalt_mutex_timedlock_break(): Validation before calling
> 		__cobalt_mutex_acquire_unchecked()
>
> If I'm right, the problem was once fixed with:
> 860ea449a298 ("cobalt/posix/mutex: fix timeout handling in pthread_mutex_timedlock()")
>
> but broken again in:
> c53a9dd3ebc7 ("cobalt/posix/mutex: prepare for 32bit syscall emulation")
>
>
> 		

The less intrusive way would be to try lock first calling
xnsynch_try_acquire(), then fallback to xnsynch_acquire() if
failed. This is likely to become the hot path for this code, assuming a
mutex is most often unlocked on entry.

We are all locked under the big ugly nklock at this point, so there
should be nothing to care about preemption-wise.

-- 
Philippe.


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

* Re: [y2038][PATCH v3 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64
  2021-03-10 13:09                             ` [y2038][PATCH v3 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64 Florian Bezdeka
@ 2021-03-11  2:38                               ` chensong
  0 siblings, 0 replies; 57+ messages in thread
From: chensong @ 2021-03-11  2:38 UTC (permalink / raw)
  To: Florian Bezdeka, xenomai, jan.kiszka, rpm, chensong



On 2021年03月10日 21:09, Florian Bezdeka via Xenomai wrote:
> In case libcobalt is build with -D_TIME_BITS=64
> sc_cobalt_sem_timedwait64 will be used instead of
> sc_cobalt_sem_timedwait.
>
> Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
> ---
>   lib/cobalt/semaphore.c | 5 +++++
>   1 file changed, 5 insertions(+)
>
> diff --git a/lib/cobalt/semaphore.c b/lib/cobalt/semaphore.c
> index 45705d48f..bff005440 100644
> --- a/lib/cobalt/semaphore.c
> +++ b/lib/cobalt/semaphore.c
> @@ -373,7 +373,12 @@ COBALT_IMPL(int, sem_timedwait, (sem_t *sem, const struct timespec *abs_timeout)
>
>   	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
>
> +#ifdef __USE_TIME_BITS64
> +	ret = XENOMAI_SYSCALL2(sc_cobalt_sem_timedwait64, _sem,
> +			       abs_timeout);
> +#else
>   	ret = XENOMAI_SYSCALL2(sc_cobalt_sem_timedwait, _sem, abs_timeout);
> +#endif
>
>   	pthread_setcanceltype(oldtype, NULL);
>
>

shall we take cobalt_features_available into account?

Song




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

end of thread, other threads:[~2021-03-11  2:38 UTC | newest]

Thread overview: 57+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-20 15:18 [PATCH 1/5] cobalt/kernel: y2038: convert struct timeval to __kernel_old_timeval Philippe Gerum
2021-02-20 15:18 ` [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64 Philippe Gerum
2021-02-21  2:17   ` chensong
2021-02-21 15:27     ` Philippe Gerum
2021-02-22  1:04       ` chensong
2021-02-22  8:21       ` florian.bezdeka
2021-02-22  9:08         ` Philippe Gerum
2021-03-08 12:19           ` Jan Kiszka
2021-03-08 14:01             ` Philippe Gerum
2021-03-08 14:03               ` Jan Kiszka
2021-03-03 10:05   ` florian.bezdeka
2021-03-04  9:35     ` Philippe Gerum
2021-03-04  9:49       ` florian.bezdeka
2021-03-04  9:55         ` Philippe Gerum
2021-03-04  9:59           ` florian.bezdeka
2021-03-04 10:08           ` Philippe Gerum
2021-03-04 11:36             ` [y2038][RFC PATCH 0/2] Pattern for implementing y2038 syscalls Florian Bezdeka
2021-03-04 11:36               ` [y2038][RFC PATCH 1/2] y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
2021-03-04 15:11                 ` Philippe Gerum
2021-03-04 15:22                   ` florian.bezdeka
2021-03-04 15:42                     ` Philippe Gerum
2021-03-08 17:02                       ` [RFC PATCH v2 0/4] Pattern for implementing y2038 syscalls Florian Bezdeka
2021-03-08 17:02                         ` [RFC PATCH v2 1/4] y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
2021-03-08 17:12                           ` Jan Kiszka
2021-03-08 18:11                             ` florian.bezdeka
2021-03-08 18:22                               ` Jan Kiszka
2021-03-09  9:46                           ` Philippe Gerum
2021-03-09 11:08                             ` florian.bezdeka
2021-03-08 17:02                         ` [RFC PATCH v2 2/4] y2038: Adding sem_timedwait_time64 Florian Bezdeka
2021-03-08 18:28                           ` Jan Kiszka
2021-03-09  7:53                             ` florian.bezdeka
2021-03-10  7:51                               ` florian.bezdeka
2021-03-10  9:46                                 ` chensong
2021-03-08 17:02                         ` [RFC PATCH v2 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait_time64 syscall Florian Bezdeka
2021-03-08 18:35                           ` Jan Kiszka
2021-03-09  8:00                             ` florian.bezdeka
2021-03-08 17:02                         ` [RFC PATCH v2 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait_time64 Florian Bezdeka
2021-03-10 13:09                           ` [y2038][PATCH v3 0/4] Pattern for implementing y2038 syscalls Florian Bezdeka
2021-03-10 13:09                             ` [y2038][PATCH v3 1/4] y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
2021-03-10 13:09                             ` [y2038][PATCH v3 2/4] y2038: Adding sem_timedwait64 Florian Bezdeka
2021-03-10 13:09                             ` [y2038][PATCH v3 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait64 syscall Florian Bezdeka
2021-03-10 13:09                             ` [y2038][PATCH v3 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64 Florian Bezdeka
2021-03-11  2:38                               ` chensong
2021-03-04 11:36               ` [y2038][RFC PATCH 2/2] y2038: Adding sem_timedwait_time64 Florian Bezdeka
2021-03-05  5:49                 ` chensong
2021-03-05  6:36                   ` florian.bezdeka
2021-03-05  7:42                     ` chensong
2021-03-05  7:53                       ` florian.bezdeka
2021-03-08 12:59             ` [PATCH 2/5] cobalt/kernel: y2038: convert struct timespec to timespec64 Jan Kiszka
2021-03-10 17:52             ` florian.bezdeka
2021-03-10 18:14               ` Philippe Gerum
2021-03-03 14:36   ` florian.bezdeka
2021-03-04  9:44     ` Philippe Gerum
2021-03-04  9:57       ` florian.bezdeka
2021-02-20 15:18 ` [PATCH 3/5] lib: y2038: convert to internal timespec type Philippe Gerum
2021-02-20 15:18 ` [PATCH 4/5] cobalt/kernel: y2038: convert struct itimerspec to itimerspec64 Philippe Gerum
2021-02-20 15:18 ` [PATCH 5/5] cobalt/kernel: y2038: convert struct timex to __kernel_timex Philippe Gerum

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.