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,13 +259,24 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, | ||
| 259 | host_start += offset - host_offset; | 259 | host_start += offset - host_offset; |
| 260 | start = h2g(host_start); | 260 | start = h2g(host_start); |
| 261 | } else { | 261 | } else { |
| 262 | + int flg; | ||
| 263 | + target_ulong addr; | ||
| 264 | + | ||
| 262 | if (start & ~TARGET_PAGE_MASK) { | 265 | if (start & ~TARGET_PAGE_MASK) { |
| 263 | errno = EINVAL; | 266 | errno = EINVAL; |
| 264 | return -1; | 267 | return -1; |
| 265 | } | 268 | } |
| 266 | end = start + len; | 269 | end = start + len; |
| 267 | real_end = HOST_PAGE_ALIGN(end); | 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 | /* worst case: we cannot map the file because the offset is not | 280 | /* worst case: we cannot map the file because the offset is not |
| 270 | aligned, so we read it */ | 281 | aligned, so we read it */ |
| 271 | if (!(flags & MAP_ANONYMOUS) && | 282 | if (!(flags & MAP_ANONYMOUS) && |
linux-user/syscall.c
| @@ -420,7 +420,7 @@ abi_long do_brk(abi_ulong new_brk) | @@ -420,7 +420,7 @@ abi_long do_brk(abi_ulong new_brk) | ||
| 420 | if (!new_brk) | 420 | if (!new_brk) |
| 421 | return target_brk; | 421 | return target_brk; |
| 422 | if (new_brk < target_original_brk) | 422 | if (new_brk < target_original_brk) |
| 423 | - return -TARGET_ENOMEM; | 423 | + return target_brk; |
| 424 | 424 | ||
| 425 | brk_page = HOST_PAGE_ALIGN(target_brk); | 425 | brk_page = HOST_PAGE_ALIGN(target_brk); |
| 426 | 426 | ||
| @@ -435,12 +435,11 @@ abi_long do_brk(abi_ulong new_brk) | @@ -435,12 +435,11 @@ abi_long do_brk(abi_ulong new_brk) | ||
| 435 | mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, | 435 | mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, |
| 436 | PROT_READ|PROT_WRITE, | 436 | PROT_READ|PROT_WRITE, |
| 437 | MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0)); | 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 | target_brk = new_brk; | 440 | target_brk = new_brk; |
| 442 | - return target_brk; | ||
| 443 | - } | 441 | + |
| 442 | + return target_brk; | ||
| 444 | } | 443 | } |
| 445 | 444 | ||
| 446 | static inline abi_long copy_from_user_fdset(fd_set *fds, | 445 | static inline abi_long copy_from_user_fdset(fd_set *fds, |