aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Vivier <laurent@vivier.eu>2018-05-10 01:11:21 +0200
committerLaurent Vivier <laurent@vivier.eu>2018-05-11 19:05:19 +0200
commitae68ad9fee4e51eae26e34b43a9e6999bd1c6819 (patch)
tree6126eed6547bb2bd31314a89e52f11251f929b03
parent534cdbf56c2a72952ffde9a258160f5586cea886 (diff)
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>
-rw-r--r--linux-user/syscall.c66
1 files changed, 48 insertions, 18 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index e4825747f9..af8603f1b7 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -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);