diff mbox series

[v2,5/5] linux-user: Flush out implementation of gettimeofday

Message ID 20200116194341.402-6-richard.henderson@linaro.org
State New
Headers show
Series linux-user: Implement x86_64 vsyscalls | expand

Commit Message

Richard Henderson Jan. 16, 2020, 7:43 p.m. UTC
The first argument, timeval, is allowed to be NULL.

The second argument, timezone, was missing.  While its use is
deprecated, it is still present in the syscall.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/syscall.c | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

Comments

Philippe Mathieu-Daudé Jan. 17, 2020, 6:37 a.m. UTC | #1
On 1/16/20 8:43 PM, Richard Henderson wrote:
> The first argument, timeval, is allowed to be NULL.
> 
> The second argument, timezone, was missing.  While its use is
> deprecated, it is still present in the syscall.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/syscall.c | 27 +++++++++++++++++++++++++--
>   1 file changed, 25 insertions(+), 2 deletions(-)
> 
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index eb867a5296..628b4de9a1 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -1219,6 +1219,23 @@ static inline abi_long host_to_target_timespec64(abi_ulong target_addr,
>       return 0;
>   }
>   
> +static inline abi_long copy_to_user_timezone(abi_ulong target_tz_addr,
> +                                             struct timezone *tz)
> +{
> +    struct target_timezone *target_tz;
> +
> +    if (!lock_user_struct(VERIFY_WRITE, target_tz, target_tz_addr, 1)) {
> +        return -TARGET_EFAULT;
> +    }
> +
> +    __put_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
> +    __put_user(tz->tz_dsttime, &target_tz->tz_dsttime);
> +
> +    unlock_user_struct(target_tz, target_tz_addr, 1);
> +
> +    return 0;
> +}
> +
>   static inline abi_long copy_from_user_timezone(struct timezone *tz,
>                                                  abi_ulong target_tz_addr)
>   {
> @@ -8567,10 +8584,16 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
>       case TARGET_NR_gettimeofday:
>           {
>               struct timeval tv;
> -            ret = get_errno(gettimeofday(&tv, NULL));
> +            struct timezone tz;
> +
> +            ret = get_errno(gettimeofday(&tv, &tz));
>               if (!is_error(ret)) {
> -                if (copy_to_user_timeval(arg1, &tv))
> +                if (arg1 && copy_to_user_timeval(arg1, &tv)) {
>                       return -TARGET_EFAULT;
> +                }
> +                if (arg2 && copy_to_user_timezone(arg2, &tz)) {
> +                    return -TARGET_EFAULT;
> +                }
>               }
>           }
>           return ret;
> 

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Alex Bennée Jan. 20, 2020, 1:27 p.m. UTC | #2
Richard Henderson <richard.henderson@linaro.org> writes:

> The first argument, timeval, is allowed to be NULL.
>
> The second argument, timezone, was missing.  While its use is
> deprecated, it is still present in the syscall.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  linux-user/syscall.c | 27 +++++++++++++++++++++++++--
>  1 file changed, 25 insertions(+), 2 deletions(-)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index eb867a5296..628b4de9a1 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -1219,6 +1219,23 @@ static inline abi_long host_to_target_timespec64(abi_ulong target_addr,
>      return 0;
>  }
>  
> +static inline abi_long copy_to_user_timezone(abi_ulong target_tz_addr,
> +                                             struct timezone *tz)
> +{
> +    struct target_timezone *target_tz;
> +
> +    if (!lock_user_struct(VERIFY_WRITE, target_tz, target_tz_addr, 1)) {
> +        return -TARGET_EFAULT;
> +    }
> +
> +    __put_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
> +    __put_user(tz->tz_dsttime, &target_tz->tz_dsttime);
> +
> +    unlock_user_struct(target_tz, target_tz_addr, 1);
> +
> +    return 0;
> +}
> +
>  static inline abi_long copy_from_user_timezone(struct timezone *tz,
>                                                 abi_ulong target_tz_addr)
>  {
> @@ -8567,10 +8584,16 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
>      case TARGET_NR_gettimeofday:
>          {
>              struct timeval tv;
> -            ret = get_errno(gettimeofday(&tv, NULL));
> +            struct timezone tz;
> +
> +            ret = get_errno(gettimeofday(&tv, &tz));
>              if (!is_error(ret)) {
> -                if (copy_to_user_timeval(arg1, &tv))
> +                if (arg1 && copy_to_user_timeval(arg1, &tv)) {
>                      return -TARGET_EFAULT;
> +                }
> +                if (arg2 && copy_to_user_timezone(arg2, &tz)) {
> +                    return -TARGET_EFAULT;
> +                }
>              }
>          }
>          return ret;
diff mbox series

Patch

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index eb867a5296..628b4de9a1 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1219,6 +1219,23 @@  static inline abi_long host_to_target_timespec64(abi_ulong target_addr,
     return 0;
 }
 
+static inline abi_long copy_to_user_timezone(abi_ulong target_tz_addr,
+                                             struct timezone *tz)
+{
+    struct target_timezone *target_tz;
+
+    if (!lock_user_struct(VERIFY_WRITE, target_tz, target_tz_addr, 1)) {
+        return -TARGET_EFAULT;
+    }
+
+    __put_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
+    __put_user(tz->tz_dsttime, &target_tz->tz_dsttime);
+
+    unlock_user_struct(target_tz, target_tz_addr, 1);
+
+    return 0;
+}
+
 static inline abi_long copy_from_user_timezone(struct timezone *tz,
                                                abi_ulong target_tz_addr)
 {
@@ -8567,10 +8584,16 @@  static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     case TARGET_NR_gettimeofday:
         {
             struct timeval tv;
-            ret = get_errno(gettimeofday(&tv, NULL));
+            struct timezone tz;
+
+            ret = get_errno(gettimeofday(&tv, &tz));
             if (!is_error(ret)) {
-                if (copy_to_user_timeval(arg1, &tv))
+                if (arg1 && copy_to_user_timeval(arg1, &tv)) {
                     return -TARGET_EFAULT;
+                }
+                if (arg2 && copy_to_user_timezone(arg2, &tz)) {
+                    return -TARGET_EFAULT;
+                }
             }
         }
         return ret;