linux-user: Split out do_mmap

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")
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2023-08-07 18:22:35 -07:00
parent c42e77a90d
commit 9ab8d07149
1 changed files with 73 additions and 17 deletions

View File

@ -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);