* [PATCH for-8.1 0/2] linux-user: Fix MAP_SHARED_VALIDATE, MAP_FIXED_NOREPLACE
@ 2023-08-08 2:55 Richard Henderson
2023-08-08 2:55 ` [PATCH 1/2] linux-user: Split out do_mmap Richard Henderson
2023-08-08 2:55 ` [PATCH 2/2] linux-user: Use ARRAY_SIZE with bitmask_transtbl Richard Henderson
0 siblings, 2 replies; 5+ messages in thread
From: Richard Henderson @ 2023-08-08 2:55 UTC (permalink / raw)
To: qemu-devel; +Cc: mjt, laurent
Fixes LTP mmap17 (MAP_FIXED_NOREPLACE) and mmap20 (MAP_SHARED_VALIDATE),
both of which were added to linux-user during the 8.1 cycle, and so
would be nice to fix right away.
Does not fix mmap18, which will fail depending on the guest memory map.
The real kernel avoids placing new maps immediately prior to GROWSDOWN
regions (leaving them no room into which to expand) and qemu does not.
This is a long-standing problem and will not be fixable for 8.1.
Reported-by: Michael Tokarev <mjt@tls.msk.ru>
r~
Richard Henderson (2):
linux-user: Split out do_mmap
linux-user: Use ARRAY_SIZE with bitmask_transtbl
bsd-user/syscall_defs.h | 2 +
include/exec/user/thunk.h | 15 ++++--
linux-user/syscall.c | 96 +++++++++++++++++++++++++++++----------
linux-user/thunk.c | 24 +++++-----
4 files changed, 98 insertions(+), 39 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] linux-user: Split out do_mmap
2023-08-08 2:55 [PATCH for-8.1 0/2] linux-user: Fix MAP_SHARED_VALIDATE, MAP_FIXED_NOREPLACE Richard Henderson
@ 2023-08-08 2:55 ` Richard Henderson
2023-08-09 9:15 ` Alex Bennée
2023-08-08 2:55 ` [PATCH 2/2] linux-user: Use ARRAY_SIZE with bitmask_transtbl Richard Henderson
1 sibling, 1 reply; 5+ messages in thread
From: Richard Henderson @ 2023-08-08 2:55 UTC (permalink / raw)
To: qemu-devel; +Cc: mjt, laurent
New function that rejects unsupported map types and flags.
In 4b840f96 we should not have accepted MAP_SHARED_VALIDATE
without actually validating the rest of the flags.
Fixes: 4b840f96 ("linux-user: Populate more bits in mmap_flags_tbl")
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/syscall.c | 90 +++++++++++++++++++++++++++++++++++---------
1 file changed, 73 insertions(+), 17 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index a15bce2be2..34deff0723 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5985,10 +5985,6 @@ static const StructEntry struct_termios_def = {
#endif
static const bitmask_transtbl mmap_flags_tbl[] = {
- { TARGET_MAP_TYPE, TARGET_MAP_SHARED, MAP_TYPE, MAP_SHARED },
- { TARGET_MAP_TYPE, TARGET_MAP_PRIVATE, MAP_TYPE, MAP_PRIVATE },
- { TARGET_MAP_TYPE, TARGET_MAP_SHARED_VALIDATE,
- MAP_TYPE, MAP_SHARED_VALIDATE },
{ TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
{ TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS,
MAP_ANONYMOUS, MAP_ANONYMOUS },
@@ -6006,7 +6002,6 @@ static const bitmask_transtbl mmap_flags_tbl[] = {
Recognize it for the target insofar as we do not want to pass
it through to the host. */
{ TARGET_MAP_STACK, TARGET_MAP_STACK, 0, 0 },
- { TARGET_MAP_SYNC, TARGET_MAP_SYNC, MAP_SYNC, MAP_SYNC },
{ TARGET_MAP_NONBLOCK, TARGET_MAP_NONBLOCK, MAP_NONBLOCK, MAP_NONBLOCK },
{ TARGET_MAP_POPULATE, TARGET_MAP_POPULATE, MAP_POPULATE, MAP_POPULATE },
{ TARGET_MAP_FIXED_NOREPLACE, TARGET_MAP_FIXED_NOREPLACE,
@@ -6016,6 +6011,75 @@ static const bitmask_transtbl mmap_flags_tbl[] = {
{ 0, 0, 0, 0 }
};
+/*
+ * Arrange for legacy / undefined architecture specific flags to be
+ * ignored by mmap handling code.
+ */
+#ifndef TARGET_MAP_32BIT
+#define TARGET_MAP_32BIT 0
+#endif
+#ifndef TARGET_MAP_HUGE_2MB
+#define TARGET_MAP_HUGE_2MB 0
+#endif
+#ifndef TARGET_MAP_HUGE_1GB
+#define TARGET_MAP_HUGE_1GB 0
+#endif
+
+static abi_long do_mmap(abi_ulong addr, abi_ulong len, int prot,
+ int target_flags, int fd, off_t offset)
+{
+ /*
+ * The historical set of flags that all mmap types implicitly support.
+ */
+ enum {
+ TARGET_LEGACY_MAP_MASK = TARGET_MAP_SHARED
+ | TARGET_MAP_PRIVATE
+ | TARGET_MAP_FIXED
+ | TARGET_MAP_ANONYMOUS
+ | TARGET_MAP_DENYWRITE
+ | TARGET_MAP_EXECUTABLE
+ | TARGET_MAP_UNINITIALIZED
+ | TARGET_MAP_GROWSDOWN
+ | TARGET_MAP_LOCKED
+ | TARGET_MAP_NORESERVE
+ | TARGET_MAP_POPULATE
+ | TARGET_MAP_NONBLOCK
+ | TARGET_MAP_STACK
+ | TARGET_MAP_HUGETLB
+ | TARGET_MAP_32BIT
+ | TARGET_MAP_HUGE_2MB
+ | TARGET_MAP_HUGE_1GB
+ };
+ int host_flags;
+
+ switch (target_flags & TARGET_MAP_TYPE) {
+ case TARGET_MAP_PRIVATE:
+ host_flags = MAP_PRIVATE;
+ break;
+ case TARGET_MAP_SHARED:
+ host_flags = MAP_SHARED;
+ break;
+ case TARGET_MAP_SHARED_VALIDATE:
+ /*
+ * MAP_SYNC is only supported for MAP_SHARED_VALIDATE, and is
+ * therefore omitted from mmap_flags_tbl and TARGET_LEGACY_MAP_MASK.
+ */
+ if (target_flags & ~(TARGET_LEGACY_MAP_MASK | TARGET_MAP_SYNC)) {
+ return -TARGET_EOPNOTSUPP;
+ }
+ host_flags = MAP_SHARED_VALIDATE;
+ if (target_flags & TARGET_MAP_SYNC) {
+ host_flags |= MAP_SYNC;
+ }
+ break;
+ default:
+ return -TARGET_EINVAL;
+ }
+ host_flags |= target_to_host_bitmask(target_flags, mmap_flags_tbl);
+
+ return get_errno(target_mmap(addr, len, prot, host_flags, fd, offset));
+}
+
/*
* NOTE: TARGET_ABI32 is defined for TARGET_I386 (but not for TARGET_X86_64)
* TARGET_I386 is defined if TARGET_X86_64 is defined
@@ -10536,28 +10600,20 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
v5 = tswapal(v[4]);
v6 = tswapal(v[5]);
unlock_user(v, arg1, 0);
- ret = get_errno(target_mmap(v1, v2, v3,
- target_to_host_bitmask(v4, mmap_flags_tbl),
- v5, v6));
+ return do_mmap(v1, v2, v3, v4, v5, v6);
}
#else
/* mmap pointers are always untagged */
- ret = get_errno(target_mmap(arg1, arg2, arg3,
- target_to_host_bitmask(arg4, mmap_flags_tbl),
- arg5,
- arg6));
+ return do_mmap(arg1, arg2, arg3, arg4, arg5, arg6);
#endif
- return ret;
#endif
#ifdef TARGET_NR_mmap2
case TARGET_NR_mmap2:
#ifndef MMAP_SHIFT
#define MMAP_SHIFT 12
#endif
- ret = target_mmap(arg1, arg2, arg3,
- target_to_host_bitmask(arg4, mmap_flags_tbl),
- arg5, (off_t)(abi_ulong)arg6 << MMAP_SHIFT);
- return get_errno(ret);
+ return do_mmap(arg1, arg2, arg3, arg4, arg5,
+ (off_t)(abi_ulong)arg6 << MMAP_SHIFT);
#endif
case TARGET_NR_munmap:
arg1 = cpu_untagged_addr(cpu, arg1);
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] linux-user: Use ARRAY_SIZE with bitmask_transtbl
2023-08-08 2:55 [PATCH for-8.1 0/2] linux-user: Fix MAP_SHARED_VALIDATE, MAP_FIXED_NOREPLACE Richard Henderson
2023-08-08 2:55 ` [PATCH 1/2] linux-user: Split out do_mmap Richard Henderson
@ 2023-08-08 2:55 ` Richard Henderson
2023-08-09 9:14 ` Alex Bennée
1 sibling, 1 reply; 5+ messages in thread
From: Richard Henderson @ 2023-08-08 2:55 UTC (permalink / raw)
To: qemu-devel; +Cc: mjt, laurent
Rather than using a zero tuple to end the table, use a macro
to apply ARRAY_SIZE and pass that on to the convert functions.
This fixes two bugs in which the conversion functions required
that both the target and host masks be non-zero in order to
continue, rather than require both target and host masks be
zero in order to terminate.
This affected mmap_flags_tbl when the host does not support
all of the flags we wish to convert (e.g. MAP_UNINITIALIZED).
Mapping these flags to zero is good enough, and matches how
the kernel ignores bits that are unknown.
Fixes: 4b840f96 ("linux-user: Populate more bits in mmap_flags_tbl")
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
bsd-user/syscall_defs.h | 2 ++
include/exec/user/thunk.h | 15 +++++++++++----
linux-user/syscall.c | 6 ------
linux-user/thunk.c | 24 ++++++++++++------------
4 files changed, 25 insertions(+), 22 deletions(-)
diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h
index b6d113d24a..aedfbf2d7d 100644
--- a/bsd-user/syscall_defs.h
+++ b/bsd-user/syscall_defs.h
@@ -227,7 +227,9 @@ type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
}
/* So far all target and host bitmasks are the same */
+#undef target_to_host_bitmask
#define target_to_host_bitmask(x, tbl) (x)
+#undef host_to_target_bitmask
#define host_to_target_bitmask(x, tbl) (x)
#endif /* SYSCALL_DEFS_H */
diff --git a/include/exec/user/thunk.h b/include/exec/user/thunk.h
index 300a840d58..6eedef48d8 100644
--- a/include/exec/user/thunk.h
+++ b/include/exec/user/thunk.h
@@ -193,10 +193,17 @@ static inline int thunk_type_align(const argtype *type_ptr, int is_host)
}
}
-unsigned int target_to_host_bitmask(unsigned int target_mask,
- const bitmask_transtbl * trans_tbl);
-unsigned int host_to_target_bitmask(unsigned int host_mask,
- const bitmask_transtbl * trans_tbl);
+unsigned int target_to_host_bitmask_len(unsigned int target_mask,
+ const bitmask_transtbl *trans_tbl,
+ size_t trans_len);
+unsigned int host_to_target_bitmask_len(unsigned int host_mask,
+ const bitmask_transtbl * trans_tbl,
+ size_t trans_len);
+
+#define target_to_host_bitmask(M, T) \
+ target_to_host_bitmask_len(M, T, ARRAY_SIZE(T))
+#define host_to_target_bitmask(M, T) \
+ host_to_target_bitmask_len(M, T, ARRAY_SIZE(T))
void thunk_init(unsigned int max_structs);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 34deff0723..12ebc70df5 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -455,7 +455,6 @@ static const bitmask_transtbl fcntl_flags_tbl[] = {
#if TARGET_O_LARGEFILE != 0 || O_LARGEFILE != 0
{ TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
#endif
- { 0, 0, 0, 0 }
};
_syscall2(int, sys_getcwd1, char *, buf, size_t, size)
@@ -5813,7 +5812,6 @@ static const bitmask_transtbl iflag_tbl[] = {
{ TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
{ TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
{ TARGET_IUTF8, TARGET_IUTF8, IUTF8, IUTF8},
- { 0, 0, 0, 0 }
};
static const bitmask_transtbl oflag_tbl[] = {
@@ -5841,7 +5839,6 @@ static const bitmask_transtbl oflag_tbl[] = {
{ TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
{ TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
{ TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
- { 0, 0, 0, 0 }
};
static const bitmask_transtbl cflag_tbl[] = {
@@ -5876,7 +5873,6 @@ static const bitmask_transtbl cflag_tbl[] = {
{ TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
{ TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
{ TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
- { 0, 0, 0, 0 }
};
static const bitmask_transtbl lflag_tbl[] = {
@@ -5896,7 +5892,6 @@ static const bitmask_transtbl lflag_tbl[] = {
{ TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
{ TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
{ TARGET_EXTPROC, TARGET_EXTPROC, EXTPROC, EXTPROC},
- { 0, 0, 0, 0 }
};
static void target_to_host_termios (void *dst, const void *src)
@@ -6008,7 +6003,6 @@ static const bitmask_transtbl mmap_flags_tbl[] = {
MAP_FIXED_NOREPLACE, MAP_FIXED_NOREPLACE },
{ TARGET_MAP_UNINITIALIZED, TARGET_MAP_UNINITIALIZED,
MAP_UNINITIALIZED, MAP_UNINITIALIZED },
- { 0, 0, 0, 0 }
};
/*
diff --git a/linux-user/thunk.c b/linux-user/thunk.c
index dac4bf11c6..071aad4b5f 100644
--- a/linux-user/thunk.c
+++ b/linux-user/thunk.c
@@ -436,29 +436,29 @@ const argtype *thunk_print(void *arg, const argtype *type_ptr)
/* Utility function: Table-driven functions to translate bitmasks
* between host and target formats
*/
-unsigned int target_to_host_bitmask(unsigned int target_mask,
- const bitmask_transtbl * trans_tbl)
+unsigned int target_to_host_bitmask_len(unsigned int target_mask,
+ const bitmask_transtbl *tbl,
+ size_t len)
{
- const bitmask_transtbl *btp;
unsigned int host_mask = 0;
- for (btp = trans_tbl; btp->target_mask && btp->host_mask; btp++) {
- if ((target_mask & btp->target_mask) == btp->target_bits) {
- host_mask |= btp->host_bits;
+ for (size_t i = 0; i < len; ++i) {
+ if ((target_mask & tbl[i].target_mask) == tbl[i].target_bits) {
+ host_mask |= tbl[i].host_bits;
}
}
return host_mask;
}
-unsigned int host_to_target_bitmask(unsigned int host_mask,
- const bitmask_transtbl * trans_tbl)
+unsigned int host_to_target_bitmask_len(unsigned int host_mask,
+ const bitmask_transtbl *tbl,
+ size_t len)
{
- const bitmask_transtbl *btp;
unsigned int target_mask = 0;
- for (btp = trans_tbl; btp->target_mask && btp->host_mask; btp++) {
- if ((host_mask & btp->host_mask) == btp->host_bits) {
- target_mask |= btp->target_bits;
+ for (size_t i = 0; i < len; ++i) {
+ if ((host_mask & tbl[i].host_mask) == tbl[i].host_bits) {
+ target_mask |= tbl[i].target_bits;
}
}
return target_mask;
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] linux-user: Use ARRAY_SIZE with bitmask_transtbl
2023-08-08 2:55 ` [PATCH 2/2] linux-user: Use ARRAY_SIZE with bitmask_transtbl Richard Henderson
@ 2023-08-09 9:14 ` Alex Bennée
0 siblings, 0 replies; 5+ messages in thread
From: Alex Bennée @ 2023-08-09 9:14 UTC (permalink / raw)
To: Richard Henderson; +Cc: mjt, laurent, qemu-devel
Richard Henderson <richard.henderson@linaro.org> writes:
> Rather than using a zero tuple to end the table, use a macro
> to apply ARRAY_SIZE and pass that on to the convert functions.
>
> This fixes two bugs in which the conversion functions required
> that both the target and host masks be non-zero in order to
> continue, rather than require both target and host masks be
> zero in order to terminate.
>
> This affected mmap_flags_tbl when the host does not support
> all of the flags we wish to convert (e.g. MAP_UNINITIALIZED).
> Mapping these flags to zero is good enough, and matches how
> the kernel ignores bits that are unknown.
>
> Fixes: 4b840f96 ("linux-user: Populate more bits in mmap_flags_tbl")
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
--
Alex Bennée
Virtualisation Tech Lead @ Linaro
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] linux-user: Split out do_mmap
2023-08-08 2:55 ` [PATCH 1/2] linux-user: Split out do_mmap Richard Henderson
@ 2023-08-09 9:15 ` Alex Bennée
0 siblings, 0 replies; 5+ messages in thread
From: Alex Bennée @ 2023-08-09 9:15 UTC (permalink / raw)
To: Richard Henderson; +Cc: mjt, laurent, qemu-devel
Richard Henderson <richard.henderson@linaro.org> writes:
> New function that rejects unsupported map types and flags.
> In 4b840f96 we should not have accepted MAP_SHARED_VALIDATE
> without actually validating the rest of the flags.
>
> Fixes: 4b840f96 ("linux-user: Populate more bits in mmap_flags_tbl")
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
--
Alex Bennée
Virtualisation Tech Lead @ Linaro
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2023-08-09 9:16 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-08 2:55 [PATCH for-8.1 0/2] linux-user: Fix MAP_SHARED_VALIDATE, MAP_FIXED_NOREPLACE Richard Henderson
2023-08-08 2:55 ` [PATCH 1/2] linux-user: Split out do_mmap Richard Henderson
2023-08-09 9:15 ` Alex Bennée
2023-08-08 2:55 ` [PATCH 2/2] linux-user: Use ARRAY_SIZE with bitmask_transtbl Richard Henderson
2023-08-09 9:14 ` Alex Bennée
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).