diff mbox series

[v2,2/2] linux-user: Add support for 'recvmmsg_time64()'

Message ID 20200825212005.35982-3-Filip.Bozuta@syrmia.com
State New
Headers show
Series linux-user: Introducing support for 'recvmmsg_time64()' | expand

Commit Message

Filip Bozuta Aug. 25, 2020, 9:20 p.m. UTC
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 mbox series

Patch

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: