accel/tcg: Pass last not end to page_set_flags

Pass the address of the last byte to be changed, rather than
the first address past the last byte.  This avoids overflow
when the last page of the address space is involved.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1528
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2023-03-06 01:51:09 +03:00
parent 2f7828b572
commit 49840a4a09
6 changed files with 27 additions and 28 deletions

View File

@ -480,24 +480,22 @@ static bool pageflags_set_clear(target_ulong start, target_ulong last,
* The flag PAGE_WRITE_ORG is positioned automatically depending
* on PAGE_WRITE. The mmap_lock should already be held.
*/
void page_set_flags(target_ulong start, target_ulong end, int flags)
void page_set_flags(target_ulong start, target_ulong last, int flags)
{
target_ulong last;
bool reset = false;
bool inval_tb = false;
/* This function should never be called with addresses outside the
guest address space. If this assert fires, it probably indicates
a missing call to h2g_valid. */
assert(start < end);
assert(end - 1 <= GUEST_ADDR_MAX);
assert(start <= last);
assert(last <= GUEST_ADDR_MAX);
/* Only set PAGE_ANON with new mappings. */
assert(!(flags & PAGE_ANON) || (flags & PAGE_RESET));
assert_memory_lock();
start = start & TARGET_PAGE_MASK;
end = TARGET_PAGE_ALIGN(end);
last = end - 1;
start &= TARGET_PAGE_MASK;
last |= ~TARGET_PAGE_MASK;
if (!(flags & PAGE_VALID)) {
flags = 0;
@ -510,7 +508,7 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
}
if (!flags || reset) {
page_reset_target_data(start, end);
page_reset_target_data(start, last + 1);
inval_tb |= pageflags_unset(start, last);
}
if (flags) {
@ -518,7 +516,7 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
~(reset ? 0 : PAGE_STICKY));
}
if (inval_tb) {
tb_invalidate_phys_range(start, end);
tb_invalidate_phys_range(start, last + 1);
}
}

View File

@ -118,7 +118,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
if (ret != 0)
goto error;
}
page_set_flags(start, start + len, prot | PAGE_VALID);
page_set_flags(start, start + len - 1, prot | PAGE_VALID);
mmap_unlock();
return 0;
error:
@ -656,7 +656,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
}
}
the_end1:
page_set_flags(start, start + len, prot | PAGE_VALID);
page_set_flags(start, start + len - 1, prot | PAGE_VALID);
the_end:
#ifdef DEBUG_MMAP
printf("ret=0x" TARGET_ABI_FMT_lx "\n", start);
@ -767,7 +767,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
}
if (ret == 0) {
page_set_flags(start, start + len, 0);
page_set_flags(start, start + len - 1, 0);
}
mmap_unlock();
return ret;

View File

@ -276,7 +276,7 @@ typedef int (*walk_memory_regions_fn)(void *, target_ulong,
int walk_memory_regions(void *, walk_memory_regions_fn);
int page_get_flags(target_ulong address);
void page_set_flags(target_ulong start, target_ulong end, int flags);
void page_set_flags(target_ulong start, target_ulong last, int flags);
void page_reset_target_data(target_ulong start, target_ulong end);
int page_check_range(target_ulong start, target_ulong len, int flags);

View File

@ -213,7 +213,7 @@ static bool init_guest_commpage(void)
exit(EXIT_FAILURE);
}
page_set_flags(TARGET_VSYSCALL_PAGE,
TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE,
TARGET_VSYSCALL_PAGE | ~TARGET_PAGE_MASK,
PAGE_EXEC | PAGE_VALID);
return true;
}
@ -444,7 +444,7 @@ static bool init_guest_commpage(void)
exit(EXIT_FAILURE);
}
page_set_flags(commpage, commpage + qemu_host_page_size,
page_set_flags(commpage, commpage | ~qemu_host_page_mask,
PAGE_READ | PAGE_EXEC | PAGE_VALID);
return true;
}
@ -1316,7 +1316,7 @@ static bool init_guest_commpage(void)
exit(EXIT_FAILURE);
}
page_set_flags(LO_COMMPAGE, LO_COMMPAGE + TARGET_PAGE_SIZE,
page_set_flags(LO_COMMPAGE, LO_COMMPAGE | ~TARGET_PAGE_MASK,
PAGE_READ | PAGE_EXEC | PAGE_VALID);
return true;
}
@ -1728,7 +1728,7 @@ static bool init_guest_commpage(void)
* and implement syscalls. Here, simply mark the page executable.
* Special case the entry points during translation (see do_page_zero).
*/
page_set_flags(LO_COMMPAGE, LO_COMMPAGE + TARGET_PAGE_SIZE,
page_set_flags(LO_COMMPAGE, LO_COMMPAGE | ~TARGET_PAGE_MASK,
PAGE_EXEC | PAGE_VALID);
return true;
}
@ -2209,7 +2209,8 @@ static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
/* Ensure that the bss page(s) are valid */
if ((page_get_flags(last_bss-1) & prot) != prot) {
page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss, prot | PAGE_VALID);
page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss - 1,
prot | PAGE_VALID);
}
if (host_start < host_map_start) {

View File

@ -181,7 +181,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int target_prot)
}
}
page_set_flags(start, start + len, page_flags);
page_set_flags(start, start + len - 1, page_flags);
ret = 0;
error:
@ -640,15 +640,15 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
}
page_flags |= PAGE_RESET;
if (passthrough_start == passthrough_end) {
page_set_flags(start, start + len, page_flags);
page_set_flags(start, start + len - 1, page_flags);
} else {
if (start < passthrough_start) {
page_set_flags(start, passthrough_start, page_flags);
page_set_flags(start, passthrough_start - 1, page_flags);
}
page_set_flags(passthrough_start, passthrough_end,
page_set_flags(passthrough_start, passthrough_end - 1,
page_flags | PAGE_PASSTHROUGH);
if (passthrough_end < start + len) {
page_set_flags(passthrough_end, start + len, page_flags);
page_set_flags(passthrough_end, start + len - 1, page_flags);
}
}
the_end:
@ -763,7 +763,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
}
if (ret == 0) {
page_set_flags(start, start + len, 0);
page_set_flags(start, start + len - 1, 0);
}
mmap_unlock();
return ret;
@ -849,8 +849,8 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
} else {
new_addr = h2g(host_addr);
prot = page_get_flags(old_addr);
page_set_flags(old_addr, old_addr + old_size, 0);
page_set_flags(new_addr, new_addr + new_size,
page_set_flags(old_addr, old_addr + old_size - 1, 0);
page_set_flags(new_addr, new_addr + new_size - 1,
prot | PAGE_VALID | PAGE_RESET);
}
mmap_unlock();

View File

@ -4595,7 +4595,7 @@ static inline abi_ulong do_shmat(CPUArchState *cpu_env,
}
raddr=h2g((unsigned long)host_raddr);
page_set_flags(raddr, raddr + shm_info.shm_segsz,
page_set_flags(raddr, raddr + shm_info.shm_segsz - 1,
PAGE_VALID | PAGE_RESET | PAGE_READ |
(shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
@ -4625,7 +4625,7 @@ static inline abi_long do_shmdt(abi_ulong shmaddr)
for (i = 0; i < N_SHM_REGIONS; ++i) {
if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
shm_regions[i].in_use = false;
page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
page_set_flags(shmaddr, shmaddr + shm_regions[i].size - 1, 0);
break;
}
}