linux-user: Use 'last' instead of 'end' in target_mmap
Complete the transition within the mmap functions to a formulation that does not overflow at the end of the address space. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20230707204054.8792-20-richard.henderson@linaro.org>
This commit is contained in:
parent
4c13048e02
commit
f9cd8f5eca
@ -456,8 +456,8 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong align)
|
||||
abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
|
||||
int flags, int fd, off_t offset)
|
||||
{
|
||||
abi_ulong ret, end, real_start, real_end, retaddr, host_len,
|
||||
passthrough_start = -1, passthrough_end = -1;
|
||||
abi_ulong ret, last, real_start, real_last, retaddr, host_len;
|
||||
abi_ulong passthrough_start = -1, passthrough_last = 0;
|
||||
int page_flags;
|
||||
off_t host_offset;
|
||||
|
||||
@ -581,29 +581,30 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
|
||||
host_start += offset - host_offset;
|
||||
}
|
||||
start = h2g(host_start);
|
||||
last = start + len - 1;
|
||||
passthrough_start = start;
|
||||
passthrough_end = start + len;
|
||||
passthrough_last = last;
|
||||
} else {
|
||||
if (start & ~TARGET_PAGE_MASK) {
|
||||
errno = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
end = start + len;
|
||||
real_end = HOST_PAGE_ALIGN(end);
|
||||
last = start + len - 1;
|
||||
real_last = HOST_PAGE_ALIGN(last) - 1;
|
||||
|
||||
/*
|
||||
* Test if requested memory area fits target address space
|
||||
* It can fail only on 64-bit host with 32-bit target.
|
||||
* On any other target/host host mmap() handles this error correctly.
|
||||
*/
|
||||
if (end < start || !guest_range_valid_untagged(start, len)) {
|
||||
if (last < start || !guest_range_valid_untagged(start, len)) {
|
||||
errno = ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Validate that the chosen range is empty. */
|
||||
if ((flags & MAP_FIXED_NOREPLACE)
|
||||
&& !page_check_range_empty(start, end - 1)) {
|
||||
&& !page_check_range_empty(start, last)) {
|
||||
errno = EEXIST;
|
||||
goto fail;
|
||||
}
|
||||
@ -642,9 +643,9 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
|
||||
|
||||
/* handle the start of the mapping */
|
||||
if (start > real_start) {
|
||||
if (real_end == real_start + qemu_host_page_size) {
|
||||
if (real_last == real_start + qemu_host_page_size - 1) {
|
||||
/* one single host page */
|
||||
if (!mmap_frag(real_start, start, end - 1,
|
||||
if (!mmap_frag(real_start, start, last,
|
||||
target_prot, flags, fd, offset)) {
|
||||
goto fail;
|
||||
}
|
||||
@ -658,18 +659,18 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
|
||||
real_start += qemu_host_page_size;
|
||||
}
|
||||
/* handle the end of the mapping */
|
||||
if (end < real_end) {
|
||||
if (!mmap_frag(real_end - qemu_host_page_size,
|
||||
real_end - qemu_host_page_size, end - 1,
|
||||
if (last < real_last) {
|
||||
abi_ulong real_page = real_last - qemu_host_page_size + 1;
|
||||
if (!mmap_frag(real_page, real_page, last,
|
||||
target_prot, flags, fd,
|
||||
offset + real_end - qemu_host_page_size - start)) {
|
||||
offset + real_page - start)) {
|
||||
goto fail;
|
||||
}
|
||||
real_end -= qemu_host_page_size;
|
||||
real_last -= qemu_host_page_size;
|
||||
}
|
||||
|
||||
/* map the middle (easier) */
|
||||
if (real_start < real_end) {
|
||||
if (real_start < real_last) {
|
||||
void *p;
|
||||
off_t offset1;
|
||||
|
||||
@ -678,13 +679,13 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
|
||||
} else {
|
||||
offset1 = offset + real_start - start;
|
||||
}
|
||||
p = mmap(g2h_untagged(real_start), real_end - real_start,
|
||||
p = mmap(g2h_untagged(real_start), real_last - real_start + 1,
|
||||
target_to_host_prot(target_prot), flags, fd, offset1);
|
||||
if (p == MAP_FAILED) {
|
||||
goto fail;
|
||||
}
|
||||
passthrough_start = real_start;
|
||||
passthrough_end = real_end;
|
||||
passthrough_last = real_last;
|
||||
}
|
||||
}
|
||||
the_end1:
|
||||
@ -692,16 +693,16 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
|
||||
page_flags |= PAGE_ANON;
|
||||
}
|
||||
page_flags |= PAGE_RESET;
|
||||
if (passthrough_start == passthrough_end) {
|
||||
page_set_flags(start, start + len - 1, page_flags);
|
||||
if (passthrough_start > passthrough_last) {
|
||||
page_set_flags(start, last, page_flags);
|
||||
} else {
|
||||
if (start < passthrough_start) {
|
||||
page_set_flags(start, passthrough_start - 1, page_flags);
|
||||
}
|
||||
page_set_flags(passthrough_start, passthrough_end - 1,
|
||||
page_set_flags(passthrough_start, passthrough_last,
|
||||
page_flags | PAGE_PASSTHROUGH);
|
||||
if (passthrough_end < start + len) {
|
||||
page_set_flags(passthrough_end, start + len - 1, page_flags);
|
||||
if (passthrough_last < last) {
|
||||
page_set_flags(passthrough_last + 1, last, page_flags);
|
||||
}
|
||||
}
|
||||
the_end:
|
||||
|
Loading…
Reference in New Issue
Block a user