[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 07/18] linux-user: Fix the computation of the reques
From: |
riku . voipio |
Subject: |
[Qemu-devel] [PATCH 07/18] linux-user: Fix the computation of the requested heap size |
Date: |
Mon, 20 Jun 2011 19:20:12 +0300 |
From: Cédric VINCENT <address@hidden>
There were two remaining bugs in the previous implementation of
do_brk():
1. the value of "new_alloc_size" was one page too large when the
requested brk was aligned on a host page boundary.
2. no new pages should be (re-)allocated when the requested brk is
in the range of the pages that were already allocated
previsouly (for the same purpose). Technically these pages are
never unmapped in the current implementation.
The problem/fix can be reproduced/validated with the following test
case:
#include <unistd.h> /* syscall(2), */
#include <sys/syscall.h> /* SYS_brk, */
#include <stdio.h> /* puts(3), */
#include <stdlib.h> /* exit(3), EXIT_*, */
int main()
{
int current_brk = 0;
int new_brk;
int failure = 0;
void test(int increment) {
static int test_number = 0;
test_number++;
new_brk = syscall(SYS_brk, current_brk + increment);
if (new_brk == current_brk) {
printf("test %d fails\n", test_number);
failure++;
}
current_brk = new_brk;
}
/* Initialization. */
test(0);
/* Does QEMU overlap host pages? */
test(HOST_PAGE_SIZE);
test(HOST_PAGE_SIZE);
/* Does QEMU allocate the same host page twice? */
test(-HOST_PAGE_SIZE);
test(HOST_PAGE_SIZE);
if (!failure) {
printf("success\n");
exit(EXIT_SUCCESS);
}
else {
exit(EXIT_FAILURE);
}
}
Signed-off-by: Cédric VINCENT <address@hidden>
Reviewed-by: Christophe Guillon <address@hidden>
Signed-off-by: Riku Voipio <address@hidden>
---
linux-user/syscall.c | 11 ++++++-----
1 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index b975730..be27f53 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -709,16 +709,17 @@ char *target_strerror(int err)
static abi_ulong target_brk;
static abi_ulong target_original_brk;
+static abi_ulong brk_page;
void target_set_brk(abi_ulong new_brk)
{
target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
+ brk_page = HOST_PAGE_ALIGN(target_brk);
}
/* do_brk() must return target values and target errnos. */
abi_long do_brk(abi_ulong new_brk)
{
- abi_ulong brk_page;
abi_long mapped_addr;
int new_alloc_size;
@@ -727,9 +728,8 @@ abi_long do_brk(abi_ulong new_brk)
if (new_brk < target_original_brk)
return target_brk;
- brk_page = HOST_PAGE_ALIGN(target_brk);
-
- /* If the new brk is less than this, set it and we're done... */
+ /* If the new brk is less than the highest page reserved to the
+ * target heap allocation, set it and we're done... */
if (new_brk < brk_page) {
target_brk = new_brk;
return target_brk;
@@ -741,13 +741,14 @@ abi_long do_brk(abi_ulong new_brk)
* itself); instead we treat "mapped but at wrong address" as
* a failure and unmap again.
*/
- new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
+ new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, 0, 0));
if (mapped_addr == brk_page) {
target_brk = new_brk;
+ brk_page = HOST_PAGE_ALIGN(target_brk);
return target_brk;
} else if (mapped_addr != -1) {
/* Mapped but at wrong address, meaning there wasn't actually
--
1.7.4.1
- [Qemu-devel] [PATCH 00/18] pending linux-user patches, riku . voipio, 2011/06/20
- [Qemu-devel] [PATCH 01/18] Don't translate pointer when in restore_sigcontext, riku . voipio, 2011/06/20
- [Qemu-devel] [PATCH 05/18] arm-semi.c: Use correct check for failure of do_brk(), riku . voipio, 2011/06/20
- [Qemu-devel] [PATCH 04/18] linux-user: Don't use MAP_FIXED in do_brk(), riku . voipio, 2011/06/20
- [Qemu-devel] [PATCH 02/18] linux-user: Fix the load of ELF files that have no "useful" symbol, riku . voipio, 2011/06/20
- [Qemu-devel] [PATCH 07/18] linux-user: Fix the computation of the requested heap size,
riku . voipio <=
- [Qemu-devel] [PATCH 03/18] linux-user: Handle images where lowest vaddr is not page aligned, riku . voipio, 2011/06/20
- [Qemu-devel] [PATCH 06/18] m68k-semi.c: Use correct check for failure of do_brk(), riku . voipio, 2011/06/20
- [Qemu-devel] [PATCH 08/18] linux-user: add pselect6 syscall support, riku . voipio, 2011/06/20
- [Qemu-devel] [PATCH 09/18] linux-user: Define AT_RANDOM to support target stack protection mechanism., riku . voipio, 2011/06/20
- [Qemu-devel] [PATCH 10/18] linuxload: id_change was a write only variable, riku . voipio, 2011/06/20
- [Qemu-devel] [PATCH 11/18] syscall: really return ret code, riku . voipio, 2011/06/20
- [Qemu-devel] [PATCH 12/18] linux-user: syscall should use sanitized arg1, riku . voipio, 2011/06/20