From: Arnd Bergmann <arnd@arndb.de>
To: y2038@lists.linaro.org, linux-kernel@vger.kernel.org
Cc: Arnd Bergmann <arnd@arndb.de>,
linux-api@vger.kernel.org, linux-arch@vger.kernel.org,
libc-alpha@sourceware.org, tglx@linutronix.de,
netdev@vger.kernel.org, deepa.kernel@gmail.com,
viro@zeniv.linux.org.uk, albert.aribaud@3adev.fr,
Peter Zijlstra <peterz@infradead.org>,
Darren Hart <dvhart@infradead.org>,
"Eric W. Biederman" <ebiederm@xmission.com>,
Dominik Brodowski <linux@dominikbrodowski.net>
Subject: [PATCH 14/17] y2038: socket: Add compat_sys_recvmmsg_time64
Date: Wed, 25 Apr 2018 18:03:08 +0200 [thread overview]
Message-ID: <20180425160311.2718314-15-arnd@arndb.de> (raw)
In-Reply-To: <20180425160311.2718314-1-arnd@arndb.de>
recvmmsg() takes two arguments to pointers of structures that differ
between 32-bit and 64-bit architectures: mmsghdr and timespec.
For y2038 compatbility, we are changing the native system call from
timespec to __kernel_timespec with a 64-bit time_t (in another patch),
and use the existing compat system call on both 32-bit and 64-bit
architectures for compatibility with traditional 32-bit user space.
As we now have two variants of recvmmsg() for 32-bit tasks that are both
different from the variant that we use on 64-bit tasks, this means we
also require two compat system calls!
The solution I picked is to flip things around: The existing
compat_sys_recvmmsg() call gets moved from net/compat.c into net/socket.c
and now handles the case for old user space on all architectures that
have set CONFIG_COMPAT_32BIT_TIME. A new compat_sys_recvmmsg_time64()
call gets added in the old place for 64-bit architectures only, this
one handles the case of a compat mmsghdr structure combined with
__kernel_timespec.
In the indirect sys_socketcall(), we now need to call either
do_sys_recvmmsg() or __compat_sys_recvmmsg(), depending on what kind of
architecture we are on. For compat_sys_socketcall(), no such change is
needed, we always call __compat_sys_recvmmsg().
I decided to not add a new SYS_RECVMMSG_TIME64 socketcall: Any libc
implementation for 64-bit time_t will need significant changes including
an updated asm/unistd.h, and it seems better to consistently use the
separate syscalls that configuration, leaving the socketcall only for
backward compatibility with 32-bit time_t based libc.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
include/linux/compat.h | 5 ++++-
include/linux/socket.h | 15 ++++++++++++++-
kernel/sys_ni.c | 1 +
net/compat.c | 14 +++++++-------
net/socket.c | 39 +++++++++++++++++++++++++++++++++++++--
5 files changed, 63 insertions(+), 11 deletions(-)
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 7887b0a54c1e..f9423bbf7e7c 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -863,7 +863,10 @@ asmlinkage long compat_sys_move_pages(pid_t pid, compat_ulong_t nr_pages,
asmlinkage long compat_sys_rt_tgsigqueueinfo(compat_pid_t tgid,
compat_pid_t pid, int sig,
struct compat_siginfo __user *uinfo);
-asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg,
+asmlinkage long compat_sys_recvmmsg_time64(int fd, struct compat_mmsghdr __user *mmsg,
+ unsigned vlen, unsigned int flags,
+ struct __kernel_timespec __user *timeout);
+asmlinkage long compat_sys_recvmmsg(int fd, struct mmsghdr __user *mmsg,
unsigned vlen, unsigned int flags,
struct compat_timespec __user *timeout);
asmlinkage long compat_sys_wait4(compat_pid_t pid,
diff --git a/include/linux/socket.h b/include/linux/socket.h
index d36a6c1bdbaf..22358e0e1288 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -2,8 +2,8 @@
#ifndef _LINUX_SOCKET_H
#define _LINUX_SOCKET_H
-
#include <asm/socket.h> /* arch-dependent defines */
+#include <linux/errno.h>
#include <linux/sockios.h> /* the SIOCxxx I/O controls */
#include <linux/uio.h> /* iovec support */
#include <linux/types.h> /* pid_t */
@@ -346,6 +346,7 @@ extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_sto
extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
struct timespec64;
+struct compat_timespec;
/* The __sys_...msg variants allow MSG_CMSG_COMPAT iff
* forbid_cmsg_compat==false
@@ -356,6 +357,18 @@ extern long __sys_sendmsg(int fd, struct user_msghdr __user *msg,
unsigned int flags, bool forbid_cmsg_compat);
extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
unsigned int flags, struct timespec64 *timeout);
+#ifdef CONFIG_COMPAT_32BIT_TIME
+extern int __compat_sys_recvmmsg(int fd, struct mmsghdr __user *mmsg,
+ unsigned int vlen, unsigned int flags,
+ struct compat_timespec __user *timeout);
+#else
+static inline int __compat_sys_recvmmsg(int fd, struct mmsghdr __user *mmsg,
+ unsigned int vlen, unsigned int flags,
+ struct compat_timespec __user *timeout)
+{
+ return -EINVAL;
+}
+#endif
extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg,
unsigned int vlen, unsigned int flags,
bool forbid_cmsg_compat);
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 9791364925dc..61fc9babe6ce 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -283,6 +283,7 @@ COND_SYSCALL(perf_event_open);
COND_SYSCALL(accept4);
COND_SYSCALL(recvmmsg);
COND_SYSCALL_COMPAT(recvmmsg);
+COND_SYSCALL_COMPAT(recvmmsg_time64);
/*
* Architecture specific syscalls: see further below
diff --git a/net/compat.c b/net/compat.c
index 93b80a3d967c..7521a0afe18d 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -810,9 +810,9 @@ COMPAT_SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, buf, compat_size_t, len
return __compat_sys_recvfrom(fd, buf, len, flags, addr, addrlen);
}
-static int __compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg,
+static int __compat_sys_recvmmsg_time64(int fd, struct compat_mmsghdr __user *mmsg,
unsigned int vlen, unsigned int flags,
- struct compat_timespec __user *timeout)
+ struct __kernel_timespec __user *timeout)
{
int datagrams;
struct timespec64 ktspec;
@@ -821,22 +821,22 @@ static int __compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg,
return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
flags | MSG_CMSG_COMPAT, NULL);
- if (compat_get_timespec64(&ktspec, timeout))
+ if (get_timespec64(&ktspec, timeout))
return -EFAULT;
datagrams = __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
flags | MSG_CMSG_COMPAT, &ktspec);
- if (datagrams > 0 && compat_put_timespec64(&ktspec, timeout))
+ if (datagrams > 0 && put_timespec64(&ktspec, timeout))
datagrams = -EFAULT;
return datagrams;
}
-COMPAT_SYSCALL_DEFINE5(recvmmsg, int, fd, struct compat_mmsghdr __user *, mmsg,
+COMPAT_SYSCALL_DEFINE5(recvmmsg_time64, int, fd, struct compat_mmsghdr __user *, mmsg,
unsigned int, vlen, unsigned int, flags,
- struct compat_timespec __user *, timeout)
+ struct __kernel_timespec __user *, timeout)
{
- return __compat_sys_recvmmsg(fd, mmsg, vlen, flags, timeout);
+ return __compat_sys_recvmmsg_time64(fd, mmsg, vlen, flags, timeout);
}
COMPAT_SYSCALL_DEFINE2(socketcall, int, call, u32 __user *, args)
diff --git a/net/socket.c b/net/socket.c
index 4510e6269764..5e97b645bfee 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2483,6 +2483,37 @@ SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
return do_sys_recvmmsg(fd, mmsg, vlen, flags, timeout);
}
+#ifdef CONFIG_COMPAT_32BIT_TIME
+int __compat_sys_recvmmsg(int fd, struct mmsghdr __user *mmsg,
+ unsigned int vlen, unsigned int flags,
+ struct compat_timespec __user *timeout)
+{
+ int datagrams;
+ struct timespec64 ktspec;
+
+ if (timeout == NULL)
+ return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
+ flags | MSG_CMSG_COMPAT, NULL);
+
+ if (compat_get_timespec64(&ktspec, timeout))
+ return -EFAULT;
+
+ datagrams = __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
+ flags | MSG_CMSG_COMPAT, &ktspec);
+ if (datagrams > 0 && compat_put_timespec64(&ktspec, timeout))
+ datagrams = -EFAULT;
+
+ return datagrams;
+}
+
+COMPAT_SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
+ unsigned int, vlen, unsigned int, flags,
+ struct compat_timespec __user *, timeout)
+{
+ return __compat_sys_recvmmsg(fd, mmsg, vlen, flags, timeout);
+}
+#endif
+
#ifdef __ARCH_WANT_SYS_SOCKETCALL
/* Argument list sizes for sys_socketcall */
#define AL(x) ((x) * sizeof(unsigned long))
@@ -2600,8 +2631,12 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
a[2], true);
break;
case SYS_RECVMMSG:
- err = do_sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2],
- a[3], (struct __kernel_timespec __user *)a[4]);
+ if (IS_ENABLED(CONFIG_64BIT) || !IS_ENABLED(CONFIG_64BIT_TIME))
+ err = do_sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2],
+ a[3], (struct __kernel_timespec __user *)a[4]);
+ else
+ err = __compat_sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2],
+ a[3], (struct compat_timespec __user *)a[4]);
break;
case SYS_ACCEPT4:
err = __sys_accept4(a0, (struct sockaddr __user *)a1,
--
2.9.0
next prev parent reply other threads:[~2018-04-25 16:03 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-04-25 16:02 [PATCH 00/17] y2038: system calls, part 3 Arnd Bergmann
2018-04-25 16:02 ` [PATCH 01/17] y2038: compat: Move common compat types to asm-generic/compat.h Arnd Bergmann
2018-04-25 16:02 ` [PATCH 02/17] y2038: Remove newstat family from default syscall set Arnd Bergmann
2018-04-25 18:36 ` Geert Uytterhoeven
2018-04-25 16:02 ` [PATCH 03/17] y2038: Remove stat64 " Arnd Bergmann
2018-04-25 16:02 ` [PATCH 04/17] asm-generic: Remove unneeded __ARCH_WANT_SYS_LLSEEK macro Arnd Bergmann
2018-04-25 18:36 ` Geert Uytterhoeven
2018-04-25 16:02 ` [PATCH 05/17] asm-generic: Remove empty asm/unistd.h Arnd Bergmann
2018-04-25 16:03 ` [PATCH 06/17] y2038: Change sys_utimensat() to use __kernel_timespec Arnd Bergmann
2018-04-25 16:03 ` [PATCH 07/17] y2038: Compile utimes()/futimesat() conditionally Arnd Bergmann
2018-04-25 16:03 ` [PATCH 08/17] y2038: utimes: Rework #ifdef guards for compat syscalls Arnd Bergmann
2018-04-25 16:03 ` [PATCH 09/17] y2038: futex: Move compat implementation into futex.c Arnd Bergmann
2018-04-25 16:03 ` [PATCH 10/17] y2038: futex: Add support for __kernel_timespec Arnd Bergmann
2018-04-25 16:03 ` [PATCH 11/17] y2038: Prepare sched_rr_get_interval " Arnd Bergmann
2018-04-25 16:03 ` [PATCH 12/17] y2038: aio: Prepare sys_io_getevents " Arnd Bergmann
2018-04-25 16:03 ` [PATCH 13/17] y2038: socket: Convert recvmmsg to __kernel_timespec Arnd Bergmann
2018-04-25 16:03 ` Arnd Bergmann [this message]
2018-04-25 16:03 ` [PATCH 15/17] y2038: signal: Change rt_sigtimedwait to use __kernel_timespec Arnd Bergmann
2018-04-25 16:03 ` [PATCH 16/17] y2038: Make compat_sys_rt_sigtimedwait usable on 32-bit Arnd Bergmann
2018-04-25 16:03 ` [PATCH 17/17] y2038: signal: Add compat_sys_rt_sigtimedwait_time64 Arnd Bergmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180425160311.2718314-15-arnd@arndb.de \
--to=arnd@arndb.de \
--cc=albert.aribaud@3adev.fr \
--cc=deepa.kernel@gmail.com \
--cc=dvhart@infradead.org \
--cc=ebiederm@xmission.com \
--cc=libc-alpha@sourceware.org \
--cc=linux-api@vger.kernel.org \
--cc=linux-arch@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@dominikbrodowski.net \
--cc=netdev@vger.kernel.org \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
--cc=viro@zeniv.linux.org.uk \
--cc=y2038@lists.linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox