linux-user: respect timezone for settimeofday
The settimeofday syscall accepts a tz argument indicating the desired timezone to the kernel. QEMU previously ignored any argument provided by the target program & always passed NULL to the kernel. Instead, translate the argument & pass along the data userland provided. Although this argument is described by the settimeofday man page as obsolete, it is used by systemd as of version 213. Signed-off-by: Paul Burton <paul@archlinuxmips.org> Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
This commit is contained in:
		
							parent
							
								
									fd76783243
								
							
						
					
					
						commit
						ef4467e911
					
				| @ -935,6 +935,23 @@ static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr, | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static inline abi_long copy_from_user_timezone(struct timezone *tz, | ||||
|                                                abi_ulong target_tz_addr) | ||||
| { | ||||
|     struct target_timezone *target_tz; | ||||
| 
 | ||||
|     if (!lock_user_struct(VERIFY_READ, target_tz, target_tz_addr, 1)) { | ||||
|         return -TARGET_EFAULT; | ||||
|     } | ||||
| 
 | ||||
|     __get_user(tz->tz_minuteswest, &target_tz->tz_minuteswest); | ||||
|     __get_user(tz->tz_dsttime, &target_tz->tz_dsttime); | ||||
| 
 | ||||
|     unlock_user_struct(target_tz, target_tz_addr, 0); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| #if defined(TARGET_NR_mq_open) && defined(__NR_mq_open) | ||||
| #include <mqueue.h> | ||||
| 
 | ||||
| @ -6385,9 +6402,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, | ||||
|     case TARGET_NR_settimeofday: | ||||
|         { | ||||
|             struct timeval tv; | ||||
|             struct timezone tz, *ptz = NULL; | ||||
| 
 | ||||
|             if (copy_from_user_timeval(&tv, arg1)) | ||||
|                 goto efault; | ||||
|             ret = get_errno(settimeofday(&tv, NULL)); | ||||
| 
 | ||||
|             if (arg2) { | ||||
|                 if (copy_from_user_timezone(&tz, arg2)) { | ||||
|                     goto efault; | ||||
|                 } | ||||
|                 ptz = &tz; | ||||
|             } | ||||
| 
 | ||||
|             ret = get_errno(settimeofday(&tv, ptz)); | ||||
|         } | ||||
|         break; | ||||
| #if defined(TARGET_NR_select) | ||||
|  | ||||
| @ -165,6 +165,11 @@ struct target_timespec { | ||||
|     abi_long tv_nsec; | ||||
| }; | ||||
| 
 | ||||
| struct target_timezone { | ||||
|     abi_int tz_minuteswest; | ||||
|     abi_int tz_dsttime; | ||||
| }; | ||||
| 
 | ||||
| struct target_itimerval { | ||||
|     struct target_timeval it_interval; | ||||
|     struct target_timeval it_value; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Paul Burton
						Paul Burton