linux-user: fix conversion of flock/flock64 l_type field
As l_type values (F_RDLCK, F_WRLCK, F_UNLCK, F_EXLCK, F_SHLCK) are not bitmasks, we can't use target_to_host_bitmask() and host_to_target_bitmask() to convert them. Introduce target_to_host_flock() and host_to_target_flock() to convert values between host and target. Signed-off-by: Laurent Vivier <laurent@vivier.eu> Reviewed-by: Max Filippov <jcmvbkbc@gmail.com> Message-Id: <20180509231123.20864-5-laurent@vivier.eu>
This commit is contained in:
		
							parent
							
								
									534cdbf56c
								
							
						
					
					
						commit
						ae68ad9fee
					
				| @ -6546,28 +6546,50 @@ static int target_to_host_fcntl_cmd(int cmd) | ||||
|     return -TARGET_EINVAL; | ||||
| } | ||||
| 
 | ||||
| #define TRANSTBL_CONVERT(a) { -1, TARGET_##a, -1, a } | ||||
| static const bitmask_transtbl flock_tbl[] = { | ||||
|     TRANSTBL_CONVERT(F_RDLCK), | ||||
|     TRANSTBL_CONVERT(F_WRLCK), | ||||
|     TRANSTBL_CONVERT(F_UNLCK), | ||||
|     TRANSTBL_CONVERT(F_EXLCK), | ||||
|     TRANSTBL_CONVERT(F_SHLCK), | ||||
|     { 0, 0, 0, 0 } | ||||
| }; | ||||
| #define FLOCK_TRANSTBL \ | ||||
|     switch (type) { \ | ||||
|     TRANSTBL_CONVERT(F_RDLCK); \ | ||||
|     TRANSTBL_CONVERT(F_WRLCK); \ | ||||
|     TRANSTBL_CONVERT(F_UNLCK); \ | ||||
|     TRANSTBL_CONVERT(F_EXLCK); \ | ||||
|     TRANSTBL_CONVERT(F_SHLCK); \ | ||||
|     } | ||||
| 
 | ||||
| static int target_to_host_flock(int type) | ||||
| { | ||||
| #define TRANSTBL_CONVERT(a) case TARGET_##a: return a | ||||
|     FLOCK_TRANSTBL | ||||
| #undef  TRANSTBL_CONVERT | ||||
|     return -TARGET_EINVAL; | ||||
| } | ||||
| 
 | ||||
| static int host_to_target_flock(int type) | ||||
| { | ||||
| #define TRANSTBL_CONVERT(a) case a: return TARGET_##a | ||||
|     FLOCK_TRANSTBL | ||||
| #undef  TRANSTBL_CONVERT | ||||
|     /* if we don't know how to convert the value coming
 | ||||
|      * from the host we copy to the target field as-is | ||||
|      */ | ||||
|     return type; | ||||
| } | ||||
| 
 | ||||
| static inline abi_long copy_from_user_flock(struct flock64 *fl, | ||||
|                                             abi_ulong target_flock_addr) | ||||
| { | ||||
|     struct target_flock *target_fl; | ||||
|     short l_type; | ||||
|     int l_type; | ||||
| 
 | ||||
|     if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) { | ||||
|         return -TARGET_EFAULT; | ||||
|     } | ||||
| 
 | ||||
|     __get_user(l_type, &target_fl->l_type); | ||||
|     fl->l_type = target_to_host_bitmask(l_type, flock_tbl); | ||||
|     l_type = target_to_host_flock(l_type); | ||||
|     if (l_type < 0) { | ||||
|         return l_type; | ||||
|     } | ||||
|     fl->l_type = l_type; | ||||
|     __get_user(fl->l_whence, &target_fl->l_whence); | ||||
|     __get_user(fl->l_start, &target_fl->l_start); | ||||
|     __get_user(fl->l_len, &target_fl->l_len); | ||||
| @ -6586,7 +6608,7 @@ static inline abi_long copy_to_user_flock(abi_ulong target_flock_addr, | ||||
|         return -TARGET_EFAULT; | ||||
|     } | ||||
| 
 | ||||
|     l_type = host_to_target_bitmask(fl->l_type, flock_tbl); | ||||
|     l_type = host_to_target_flock(fl->l_type); | ||||
|     __put_user(l_type, &target_fl->l_type); | ||||
|     __put_user(fl->l_whence, &target_fl->l_whence); | ||||
|     __put_user(fl->l_start, &target_fl->l_start); | ||||
| @ -6604,14 +6626,18 @@ static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl, | ||||
|                                                    abi_ulong target_flock_addr) | ||||
| { | ||||
|     struct target_oabi_flock64 *target_fl; | ||||
|     short l_type; | ||||
|     int l_type; | ||||
| 
 | ||||
|     if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) { | ||||
|         return -TARGET_EFAULT; | ||||
|     } | ||||
| 
 | ||||
|     __get_user(l_type, &target_fl->l_type); | ||||
|     fl->l_type = target_to_host_bitmask(l_type, flock_tbl); | ||||
|     l_type = target_to_host_flock(l_type); | ||||
|     if (l_type < 0) { | ||||
|         return l_type; | ||||
|     } | ||||
|     fl->l_type = l_type; | ||||
|     __get_user(fl->l_whence, &target_fl->l_whence); | ||||
|     __get_user(fl->l_start, &target_fl->l_start); | ||||
|     __get_user(fl->l_len, &target_fl->l_len); | ||||
| @ -6630,7 +6656,7 @@ static inline abi_long copy_to_user_oabi_flock64(abi_ulong target_flock_addr, | ||||
|         return -TARGET_EFAULT; | ||||
|     } | ||||
| 
 | ||||
|     l_type = host_to_target_bitmask(fl->l_type, flock_tbl); | ||||
|     l_type = host_to_target_flock(fl->l_type); | ||||
|     __put_user(l_type, &target_fl->l_type); | ||||
|     __put_user(fl->l_whence, &target_fl->l_whence); | ||||
|     __put_user(fl->l_start, &target_fl->l_start); | ||||
| @ -6645,14 +6671,18 @@ static inline abi_long copy_from_user_flock64(struct flock64 *fl, | ||||
|                                               abi_ulong target_flock_addr) | ||||
| { | ||||
|     struct target_flock64 *target_fl; | ||||
|     short l_type; | ||||
|     int l_type; | ||||
| 
 | ||||
|     if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) { | ||||
|         return -TARGET_EFAULT; | ||||
|     } | ||||
| 
 | ||||
|     __get_user(l_type, &target_fl->l_type); | ||||
|     fl->l_type = target_to_host_bitmask(l_type, flock_tbl); | ||||
|     l_type = target_to_host_flock(l_type); | ||||
|     if (l_type < 0) { | ||||
|         return l_type; | ||||
|     } | ||||
|     fl->l_type = l_type; | ||||
|     __get_user(fl->l_whence, &target_fl->l_whence); | ||||
|     __get_user(fl->l_start, &target_fl->l_start); | ||||
|     __get_user(fl->l_len, &target_fl->l_len); | ||||
| @ -6671,7 +6701,7 @@ static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr, | ||||
|         return -TARGET_EFAULT; | ||||
|     } | ||||
| 
 | ||||
|     l_type = host_to_target_bitmask(fl->l_type, flock_tbl); | ||||
|     l_type = host_to_target_flock(fl->l_type); | ||||
|     __put_user(l_type, &target_fl->l_type); | ||||
|     __put_user(fl->l_whence, &target_fl->l_whence); | ||||
|     __put_user(fl->l_start, &target_fl->l_start); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Laurent Vivier
						Laurent Vivier