aboutsummaryrefslogtreecommitdiff
path: root/linux-user/syscall.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r--linux-user/syscall.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 35f4146662..49395dcea9 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1273,6 +1273,25 @@ static inline abi_long host_to_target_timespec64(abi_ulong target_addr,
return 0;
}
+#if defined(TARGET_NR_gettimeofday)
+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;
+}
+#endif
+
#if defined(TARGET_NR_settimeofday)
static inline abi_long copy_from_user_timezone(struct timezone *tz,
abi_ulong target_tz_addr)
@@ -7144,6 +7163,16 @@ static int open_self_maps(void *cpu_env, int fd)
}
}
+#ifdef TARGET_VSYSCALL_PAGE
+ /*
+ * We only support execution from the vsyscall page.
+ * This is as if CONFIG_LEGACY_VSYSCALL_XONLY=y from v5.3.
+ */
+ dprintf(fd, TARGET_FMT_lx "-" TARGET_FMT_lx
+ " --xp 00000000 00:00 0 [vsyscall]\n",
+ TARGET_VSYSCALL_PAGE, TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE);
+#endif
+
free(line);
fclose(fp);
@@ -8700,10 +8729,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;