aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-07-31 13:52:03 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-07-31 13:52:03 +0100
commit42e76456cf68dc828b8dbd3c7e255197e9b5e57d (patch)
tree284bac556db55c9ffacbfcad371ece90cafaa856
parent45a505d0a4b396a013ab086948a8ba6e76096bf4 (diff)
parent5d9f3ea0817215ad4baac5aa30414e9ebbaaf0d6 (diff)
Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-3.0-pull-request' into staging
Fix safe_syscall() on ppc64 host Fix mmap() 0 length error case # gpg: Signature made Tue 31 Jul 2018 09:41:07 BST # gpg: using RSA key F30C38BD3F2FBE3C # gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" # gpg: aka "Laurent Vivier <laurent@vivier.eu>" # gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" # Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C * remotes/vivier2/tags/linux-user-for-3.0-pull-request: linux-user: ppc64: don't use volatile register during safe_syscall tests: add check_invalid_maps to test-mmap linux-user/mmap.c: handle invalid len maps correctly Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--linux-user/host/ppc64/safe-syscall.inc.S8
-rw-r--r--linux-user/mmap.c15
-rw-r--r--tests/tcg/multiarch/test-mmap.c22
3 files changed, 39 insertions, 6 deletions
diff --git a/linux-user/host/ppc64/safe-syscall.inc.S b/linux-user/host/ppc64/safe-syscall.inc.S
index d30050a67c..8ed73a5b86 100644
--- a/linux-user/host/ppc64/safe-syscall.inc.S
+++ b/linux-user/host/ppc64/safe-syscall.inc.S
@@ -49,7 +49,9 @@ safe_syscall_base:
* and returns the result in r3
* Shuffle everything around appropriately.
*/
- mr 11, 3 /* signal_pending */
+ std 14, 16(1) /* Preserve r14 in SP+16 */
+ .cfi_offset 14, 16
+ mr 14, 3 /* signal_pending */
mr 0, 4 /* syscall number */
mr 3, 5 /* syscall arguments */
mr 4, 6
@@ -67,12 +69,13 @@ safe_syscall_base:
*/
safe_syscall_start:
/* if signal_pending is non-zero, don't do the call */
- lwz 12, 0(11)
+ lwz 12, 0(14)
cmpwi 0, 12, 0
bne- 0f
sc
safe_syscall_end:
/* code path when we did execute the syscall */
+ ld 14, 16(1) /* restore r14 to its original value */
bnslr+
/* syscall failed; return negative errno */
@@ -81,6 +84,7 @@ safe_syscall_end:
/* code path when we didn't execute the syscall */
0: addi 3, 0, -TARGET_ERESTARTSYS
+ ld 14, 16(1) /* restore r14 to its orginal value */
blr
.cfi_endproc
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index d0c50e4888..41e0983ce8 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -391,14 +391,23 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
}
#endif
- if (offset & ~TARGET_PAGE_MASK) {
+ if (!len) {
errno = EINVAL;
goto fail;
}
+ /* Also check for overflows... */
len = TARGET_PAGE_ALIGN(len);
- if (len == 0)
- goto the_end;
+ if (!len) {
+ errno = ENOMEM;
+ goto fail;
+ }
+
+ if (offset & ~TARGET_PAGE_MASK) {
+ errno = EINVAL;
+ goto fail;
+ }
+
real_start = start & qemu_host_page_mask;
host_offset = offset & qemu_host_page_mask;
diff --git a/tests/tcg/multiarch/test-mmap.c b/tests/tcg/multiarch/test-mmap.c
index 5c0afe6e49..11d0e777b1 100644
--- a/tests/tcg/multiarch/test-mmap.c
+++ b/tests/tcg/multiarch/test-mmap.c
@@ -27,7 +27,7 @@
#include <stdint.h>
#include <string.h>
#include <unistd.h>
-
+#include <errno.h>
#include <sys/mman.h>
#define D(x)
@@ -435,6 +435,25 @@ void checked_write(int fd, const void *buf, size_t count)
fail_unless(rc == count);
}
+void check_invalid_mmaps(void)
+{
+ unsigned char *addr;
+
+ /* Attempt to map a zero length page. */
+ addr = mmap(NULL, 0, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ fprintf(stdout, "%s addr=%p", __func__, (void *)addr);
+ fail_unless(addr == MAP_FAILED);
+ fail_unless(errno == EINVAL);
+
+ /* Attempt to map a over length page. */
+ addr = mmap(NULL, -4, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ fprintf(stdout, "%s addr=%p", __func__, (void *)addr);
+ fail_unless(addr == MAP_FAILED);
+ fail_unless(errno == ENOMEM);
+
+ fprintf(stdout, " passed\n");
+}
+
int main(int argc, char **argv)
{
char tempname[] = "/tmp/.cmmapXXXXXX";
@@ -476,6 +495,7 @@ int main(int argc, char **argv)
check_file_fixed_mmaps();
check_file_fixed_eof_mmaps();
check_file_unfixed_eof_mmaps();
+ check_invalid_mmaps();
/* Fails at the moment. */
/* check_aligned_anonymous_fixed_mmaps_collide_with_host(); */