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:
Laurent Vivier 2018-05-10 01:11:21 +02:00
parent 534cdbf56c
commit ae68ad9fee

View File

@ -6546,28 +6546,50 @@ static int target_to_host_fcntl_cmd(int cmd)
return -TARGET_EINVAL; return -TARGET_EINVAL;
} }
#define TRANSTBL_CONVERT(a) { -1, TARGET_##a, -1, a } #define FLOCK_TRANSTBL \
static const bitmask_transtbl flock_tbl[] = { switch (type) { \
TRANSTBL_CONVERT(F_RDLCK), TRANSTBL_CONVERT(F_RDLCK); \
TRANSTBL_CONVERT(F_WRLCK), TRANSTBL_CONVERT(F_WRLCK); \
TRANSTBL_CONVERT(F_UNLCK), TRANSTBL_CONVERT(F_UNLCK); \
TRANSTBL_CONVERT(F_EXLCK), TRANSTBL_CONVERT(F_EXLCK); \
TRANSTBL_CONVERT(F_SHLCK), TRANSTBL_CONVERT(F_SHLCK); \
{ 0, 0, 0, 0 } }
};
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, static inline abi_long copy_from_user_flock(struct flock64 *fl,
abi_ulong target_flock_addr) abi_ulong target_flock_addr)
{ {
struct target_flock *target_fl; struct target_flock *target_fl;
short l_type; int l_type;
if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) { if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
return -TARGET_EFAULT; return -TARGET_EFAULT;
} }
__get_user(l_type, &target_fl->l_type); __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_whence, &target_fl->l_whence);
__get_user(fl->l_start, &target_fl->l_start); __get_user(fl->l_start, &target_fl->l_start);
__get_user(fl->l_len, &target_fl->l_len); __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; 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(l_type, &target_fl->l_type);
__put_user(fl->l_whence, &target_fl->l_whence); __put_user(fl->l_whence, &target_fl->l_whence);
__put_user(fl->l_start, &target_fl->l_start); __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) abi_ulong target_flock_addr)
{ {
struct target_oabi_flock64 *target_fl; struct target_oabi_flock64 *target_fl;
short l_type; int l_type;
if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) { if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
return -TARGET_EFAULT; return -TARGET_EFAULT;
} }
__get_user(l_type, &target_fl->l_type); __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_whence, &target_fl->l_whence);
__get_user(fl->l_start, &target_fl->l_start); __get_user(fl->l_start, &target_fl->l_start);
__get_user(fl->l_len, &target_fl->l_len); __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; 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(l_type, &target_fl->l_type);
__put_user(fl->l_whence, &target_fl->l_whence); __put_user(fl->l_whence, &target_fl->l_whence);
__put_user(fl->l_start, &target_fl->l_start); __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) abi_ulong target_flock_addr)
{ {
struct target_flock64 *target_fl; struct target_flock64 *target_fl;
short l_type; int l_type;
if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) { if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
return -TARGET_EFAULT; return -TARGET_EFAULT;
} }
__get_user(l_type, &target_fl->l_type); __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_whence, &target_fl->l_whence);
__get_user(fl->l_start, &target_fl->l_start); __get_user(fl->l_start, &target_fl->l_start);
__get_user(fl->l_len, &target_fl->l_len); __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; 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(l_type, &target_fl->l_type);
__put_user(fl->l_whence, &target_fl->l_whence); __put_user(fl->l_whence, &target_fl->l_whence);
__put_user(fl->l_start, &target_fl->l_start); __put_user(fl->l_start, &target_fl->l_start);