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, |