[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v2 2/2] linux-user: Add support for 'recvmmsg_time64()'
From: |
Filip Bozuta |
Subject: |
[PATCH v2 2/2] linux-user: Add support for 'recvmmsg_time64()' |
Date: |
Tue, 25 Aug 2020 23:20:05 +0200 |
This patch introduces functionality for syscall:
*recvmmsg_time64
This syscall is a 2038 safe variant for syscall:
int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
int flags, struct timespec *timeout)
--receive multiple messages on a socket--
man page: https://man7.org/linux/man-pages/man2/recvmmsg.2.html
Implementation notes:
Function 'do_sendrecvmmsg()' in 'syscall.c' was changed with the
addition of a new argument 'time64' which represents a flag by
which the function knows what kind of 'struct timespec' converting
function to call ('target_to_host_timespec() or
'target_to_host_timespec64()'). It is false in case of
'TARGET_NR_recvmmsg' and true in case of 'TARGET_NR_recvmmsg_time64'.
In 'do_socketcall()', the 'TARGET_ABI_BITS' was checked to know
what value for 'time64' argument to pass.
Signed-off-by: Filip Bozuta <Filip.Bozuta@syrmia.com>
---
linux-user/syscall.c | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index dc89bfacca..762eea0e5b 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -3197,7 +3197,7 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong
target_msg,
static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
unsigned int vlen, unsigned int flags,
- abi_ulong timeout, int send)
+ abi_ulong timeout, bool time64, int send)
{
struct target_mmsghdr *mmsgp;
struct timespec ts, end_time, curr_time;
@@ -3212,8 +3212,14 @@ static abi_long do_sendrecvmmsg(int fd, abi_ulong
target_msgvec,
return -TARGET_EFAULT;
}
if (timeout) {
- if (target_to_host_timespec(&ts, timeout)) {
- return -TARGET_EFAULT;
+ if (time64) {
+ if (target_to_host_timespec64(&ts, timeout)) {
+ return -TARGET_EFAULT;
+ }
+ } else {
+ if (target_to_host_timespec(&ts, timeout)) {
+ return -TARGET_EFAULT;
+ }
}
if (ts.tv_sec < 0 || ts.tv_nsec < 0 || ts.tv_nsec > 1000000000) {
return -TARGET_EINVAL;
@@ -3506,7 +3512,7 @@ static abi_long do_socketcall(int num, abi_ulong vptr)
[TARGET_SYS_SENDMSG] = 3, /* fd, msg, flags */
[TARGET_SYS_RECVMSG] = 3, /* fd, msg, flags */
[TARGET_SYS_ACCEPT4] = 4, /* fd, addr, addrlen, flags */
- [TARGET_SYS_RECVMMSG] = 5, /* fd, msgvec, vlen, flags, timeout */
+ [TARGET_SYS_RECVMMSG] = 6, /* fd, msgvec, vlen, flags, timeout */
[TARGET_SYS_SENDMMSG] = 4, /* fd, msgvec, vlen, flags */
};
abi_long a[6]; /* max 6 args */
@@ -3566,9 +3572,10 @@ static abi_long do_socketcall(int num, abi_ulong vptr)
case TARGET_SYS_ACCEPT4: /* sockfd, addr, addrlen, flags */
return do_accept4(a[0], a[1], a[2], a[3]);
case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags, timeout */
- return do_sendrecvmmsg(a[0], a[1], a[2], a[3], a[4], 0);
+ return do_sendrecvmmsg(a[0], a[1], a[2], a[3], a[4],
+ TARGET_ABI_BITS == 64, 0);
case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */
- return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0, 1);
+ return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0, false, 1);
default:
qemu_log_mask(LOG_UNIMP, "Unsupported socketcall: %d\n", num);
return -TARGET_EINVAL;
@@ -9372,11 +9379,15 @@ static abi_long do_syscall1(void *cpu_env, int num,
abi_long arg1,
#endif
#ifdef TARGET_NR_sendmmsg
case TARGET_NR_sendmmsg:
- return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0, 1);
+ return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0, false, 1);
#endif
#ifdef TARGET_NR_recvmmsg
case TARGET_NR_recvmmsg:
- return do_sendrecvmmsg(arg1, arg2, arg3, arg4, arg5, 0);
+ return do_sendrecvmmsg(arg1, arg2, arg3, arg4, arg5, false, 0);
+#endif
+#ifdef TARGET_NR_recvmmsg_time64
+ case TARGET_NR_recvmmsg_time64:
+ return do_sendrecvmmsg(arg1, arg2, arg3, arg4, arg5, true, 0);
#endif
#ifdef TARGET_NR_sendto
case TARGET_NR_sendto:
--
2.25.1