Commit 7ab240ad4be6cd57b0656d291a0a4a1dfc426035
1 parent
662caa6f
Teach mmap to not overwrite reserved pages and fix brk return value (Richard Purdie).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4255 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
17 additions
and
7 deletions
linux-user/mmap.c
| ... | ... | @@ -259,13 +259,24 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, |
| 259 | 259 | host_start += offset - host_offset; |
| 260 | 260 | start = h2g(host_start); |
| 261 | 261 | } else { |
| 262 | + int flg; | |
| 263 | + target_ulong addr; | |
| 264 | + | |
| 262 | 265 | if (start & ~TARGET_PAGE_MASK) { |
| 263 | 266 | errno = EINVAL; |
| 264 | 267 | return -1; |
| 265 | 268 | } |
| 266 | 269 | end = start + len; |
| 267 | 270 | real_end = HOST_PAGE_ALIGN(end); |
| 268 | - | |
| 271 | + | |
| 272 | + for(addr = real_start; addr < real_end; addr += TARGET_PAGE_SIZE) { | |
| 273 | + flg = page_get_flags(addr); | |
| 274 | + if (flg & PAGE_RESERVED) { | |
| 275 | + errno = ENXIO; | |
| 276 | + return -1; | |
| 277 | + } | |
| 278 | + } | |
| 279 | + | |
| 269 | 280 | /* worst case: we cannot map the file because the offset is not |
| 270 | 281 | aligned, so we read it */ |
| 271 | 282 | if (!(flags & MAP_ANONYMOUS) && | ... | ... |
linux-user/syscall.c
| ... | ... | @@ -420,7 +420,7 @@ abi_long do_brk(abi_ulong new_brk) |
| 420 | 420 | if (!new_brk) |
| 421 | 421 | return target_brk; |
| 422 | 422 | if (new_brk < target_original_brk) |
| 423 | - return -TARGET_ENOMEM; | |
| 423 | + return target_brk; | |
| 424 | 424 | |
| 425 | 425 | brk_page = HOST_PAGE_ALIGN(target_brk); |
| 426 | 426 | |
| ... | ... | @@ -435,12 +435,11 @@ abi_long do_brk(abi_ulong new_brk) |
| 435 | 435 | mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, |
| 436 | 436 | PROT_READ|PROT_WRITE, |
| 437 | 437 | MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0)); |
| 438 | - if (is_error(mapped_addr)) { | |
| 439 | - return mapped_addr; | |
| 440 | - } else { | |
| 438 | + | |
| 439 | + if (!is_error(mapped_addr)) | |
| 441 | 440 | target_brk = new_brk; |
| 442 | - return target_brk; | |
| 443 | - } | |
| 441 | + | |
| 442 | + return target_brk; | |
| 444 | 443 | } |
| 445 | 444 | |
| 446 | 445 | static inline abi_long copy_from_user_fdset(fd_set *fds, | ... | ... |