diff mbox series

[1/2] linux-user: Add support for 'ppoll_time64()' and 'pselect6_time64()'

Message ID 20200812135703.39404-2-Filip.Bozuta@syrmia.com (mailing list archive)
State New, archived
Headers show
Series linux-user: Adding support for a group of 4 time64 syscalls | expand

Commit Message

Filip Bozuta Aug. 12, 2020, 1:57 p.m. UTC
This patch introduces functionality for following time64 syscalls:

*ppoll_time64

    This is a year 2038 safe variant of:

    int poll(struct pollfd *fds, nfds_t nfds, int timeout)
    -- wait for some event on a file descriptor --
    man page: https://man7.org/linux/man-pages/man2/ppoll.2.html

*pselect6_time64

    This is a year 2038 safe variant of:

    int pselect6(int nfds, fd_set *readfds, fd_set *writefds,
                 fd_set *exceptfds, const struct timespec *timeout,
                 const sigset_t *sigmask);
    -- synchronous I/O multiplexing --
    man page: https://man7.org/linux/man-pages/man2/pselect6.2.html

Implementation notes:

    Year 2038 safe syscalls in this patch were implemented
    with the same code as their regular variants (ppoll() and pselect()).
    A switch/case statement was used to call an apropriate converting
    function for 'struct timespec' between target and host.
    (target_to_host/host_to_target_timespec() for regular and
     target_to_host/host_to_target_timespec64() for time64 variants)

Signed-off-by: Filip Bozuta <Filip.Bozuta@syrmia.com>
---
 linux-user/syscall.c | 101 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 86 insertions(+), 15 deletions(-)

Comments

Laurent Vivier Aug. 24, 2020, 5:12 p.m. UTC | #1
Le 12/08/2020 à 15:57, Filip Bozuta a écrit :
> This patch introduces functionality for following time64 syscalls:
> 
> *ppoll_time64
> 
>     This is a year 2038 safe variant of:
> 
>     int poll(struct pollfd *fds, nfds_t nfds, int timeout)
>     -- wait for some event on a file descriptor --
>     man page: https://man7.org/linux/man-pages/man2/ppoll.2.html
> 
> *pselect6_time64
> 
>     This is a year 2038 safe variant of:
> 
>     int pselect6(int nfds, fd_set *readfds, fd_set *writefds,
>                  fd_set *exceptfds, const struct timespec *timeout,
>                  const sigset_t *sigmask);
>     -- synchronous I/O multiplexing --
>     man page: https://man7.org/linux/man-pages/man2/pselect6.2.html
> 
> Implementation notes:
> 
>     Year 2038 safe syscalls in this patch were implemented
>     with the same code as their regular variants (ppoll() and pselect()).
>     A switch/case statement was used to call an apropriate converting
>     function for 'struct timespec' between target and host.
>     (target_to_host/host_to_target_timespec() for regular and
>      target_to_host/host_to_target_timespec64() for time64 variants)
> 
> Signed-off-by: Filip Bozuta <Filip.Bozuta@syrmia.com>
> ---
>  linux-user/syscall.c | 101 ++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 86 insertions(+), 15 deletions(-)
> 

I think it would be cleaner if you move the code to new functions,
do_ppoll() and do_pselect6() first, and then you introduce a new
parameter "bool time64" to implement the time64 variant (rather than a
switch()) as you do in PATCH 2.

Thanks,
Laurent
diff mbox series

Patch

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 1211e759c2..8f63a46f58 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -397,7 +397,7 @@  static int sys_getcwd1(char *buf, size_t size)
   return strlen(buf)+1;
 }
 
-#ifdef TARGET_NR_utimensat
+#if defined(TARGET_NR_utimensat)
 #if defined(__NR_utimensat)
 #define __NR_sys_utimensat __NR_utimensat
 _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
@@ -763,11 +763,11 @@  safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
               int, options, struct rusage *, rusage)
 safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp)
 #if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
-    defined(TARGET_NR_pselect6)
+    defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
 safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \
               fd_set *, exceptfds, struct timespec *, timeout, void *, sig)
 #endif
-#if defined(TARGET_NR_ppoll) || defined(TARGET_NR_poll)
+#if defined(TARGET_NR_ppoll) || defined(TARGET_NR_ppoll_time64)
 safe_syscall5(int, ppoll, struct pollfd *, ufds, unsigned int, nfds,
               struct timespec *, tsp, const sigset_t *, sigmask,
               size_t, sigsetsize)
@@ -984,7 +984,7 @@  abi_long do_brk(abi_ulong new_brk)
 }
 
 #if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
-    defined(TARGET_NR_pselect6)
+    defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
 static inline abi_long copy_from_user_fdset(fd_set *fds,
                                             abi_ulong target_fds_addr,
                                             int n)
@@ -1252,7 +1252,8 @@  static inline abi_long target_to_host_timespec(struct timespec *host_ts,
 }
 #endif
 
-#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64)
+#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \
+    defined(TARGET_NR_pselect6_time64) || defined(TARGET_NR_ppoll_time64)
 static inline abi_long target_to_host_timespec64(struct timespec *host_ts,
                                                  abi_ulong target_addr)
 {
@@ -9043,8 +9044,13 @@  static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
 #endif
         return ret;
 #endif
+#if defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
 #ifdef TARGET_NR_pselect6
     case TARGET_NR_pselect6:
+#endif
+#ifdef TARGET_NR_pselect6_time64
+    case TARGET_NR_pselect6_time64:
+#endif
         {
             abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
             fd_set rfds, wfds, efds;
@@ -9088,8 +9094,21 @@  static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
              * use the do_select() helper ...
              */
             if (ts_addr) {
-                if (target_to_host_timespec(&ts, ts_addr)) {
-                    return -TARGET_EFAULT;
+                switch (num) {
+#ifdef TARGET_NR_pselect6
+                case TARGET_NR_pselect6:
+                    if (target_to_host_timespec(&ts, ts_addr)) {
+                        return -TARGET_EFAULT;
+                    }
+                    break;
+#endif
+#ifdef TARGET_NR_pselect6_time64
+                case TARGET_NR_pselect6_time64:
+                    if (target_to_host_timespec64(&ts, ts_addr)) {
+                        return -TARGET_EFAULT;
+                    }
+                    break;
+#endif
                 }
                 ts_ptr = &ts;
             } else {
@@ -9140,8 +9159,22 @@  static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
                 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
                     return -TARGET_EFAULT;
 
-                if (ts_addr && host_to_target_timespec(ts_addr, &ts))
-                    return -TARGET_EFAULT;
+                switch (num) {
+#ifdef TARGET_NR_pselect6
+                case TARGET_NR_pselect6:
+                    if (ts_addr && host_to_target_timespec(ts_addr, &ts)) {
+                        return -TARGET_EFAULT;
+                    }
+                break;
+#endif
+#ifdef TARGET_NR_pselect6_time64
+                case TARGET_NR_pselect6_time64:
+                    if (ts_addr && host_to_target_timespec64(ts_addr, &ts)) {
+                        return -TARGET_EFAULT;
+                    }
+                break;
+#endif
+                }
             }
         }
         return ret;
@@ -10076,12 +10109,16 @@  static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     case TARGET_NR__newselect:
         return do_select(arg1, arg2, arg3, arg4, arg5);
 #endif
-#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll)
+#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll) || \
+    defined(TARGET_NR_ppoll_time64)
 # ifdef TARGET_NR_poll
     case TARGET_NR_poll:
 # endif
 # ifdef TARGET_NR_ppoll
     case TARGET_NR_ppoll:
+# endif
+# ifdef TARGET_NR_ppoll_time64
+    case TARGET_NR_ppoll_time64:
 # endif
         {
             struct target_pollfd *target_pfd;
@@ -10110,17 +10147,38 @@  static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
             }
 
             switch (num) {
-# ifdef TARGET_NR_ppoll
+#if defined(TARGET_NR_ppoll) || defined(TARGET_NR_ppoll_time64)
+#ifdef TARGET_NR_ppoll
             case TARGET_NR_ppoll:
+#endif
+#ifdef TARGET_NR_ppoll_time64
+            case TARGET_NR_ppoll_time64:
+#endif
             {
                 struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
                 target_sigset_t *target_set;
                 sigset_t _set, *set = &_set;
 
                 if (arg3) {
-                    if (target_to_host_timespec(timeout_ts, arg3)) {
-                        unlock_user(target_pfd, arg1, 0);
-                        return -TARGET_EFAULT;
+                    switch (num) {
+#ifdef TARGET_NR_ppoll
+                    case TARGET_NR_ppoll:
+                        if (target_to_host_timespec(timeout_ts, arg3)) {
+                            unlock_user(target_pfd, arg1, 0);
+                            return -TARGET_EFAULT;
+                        }
+                    break;
+#endif
+#ifdef TARGET_NR_ppoll_time64
+                    case TARGET_NR_ppoll_time64:
+                        if (target_to_host_timespec64(timeout_ts, arg3)) {
+                            unlock_user(target_pfd, arg1, 0);
+                            return -TARGET_EFAULT;
+                        }
+                    break;
+#endif
+                    default:
+                        g_assert_not_reached();
                     }
                 } else {
                     timeout_ts = NULL;
@@ -10146,7 +10204,20 @@  static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
                                            set, SIGSET_T_SIZE));
 
                 if (!is_error(ret) && arg3) {
-                    host_to_target_timespec(arg3, timeout_ts);
+                    switch (num) {
+#ifdef TARGET_NR_ppoll
+                    case TARGET_NR_ppoll:
+                        host_to_target_timespec(arg3, timeout_ts);
+                        break;
+#endif
+#ifdef TARGET_NR_ppoll_time64
+                    case TARGET_NR_ppoll_time64:
+                        host_to_target_timespec64(arg3, timeout_ts);
+                        break;
+#endif
+                    default:
+                        g_assert_not_reached();
+                    }
                 }
                 if (arg4) {
                     unlock_user(target_set, arg4, 0);