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>
diff --git a/linux-user/host/ppc64/safe-syscall.inc.S b/linux-user/host/ppc64/safe-syscall.inc.S
index d30050a..8ed73a5 100644
--- a/linux-user/host/ppc64/safe-syscall.inc.S
+++ b/linux-user/host/ppc64/safe-syscall.inc.S
@@ -49,7 +49,9 @@
* 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_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 @@
/* 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 d0c50e4..41e0983 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -391,14 +391,23 @@
}
#endif
+ if (!len) {
+ errno = EINVAL;
+ goto fail;
+ }
+
+ /* Also check for overflows... */
+ len = TARGET_PAGE_ALIGN(len);
+ if (!len) {
+ errno = ENOMEM;
+ goto fail;
+ }
+
if (offset & ~TARGET_PAGE_MASK) {
errno = EINVAL;
goto fail;
}
- len = TARGET_PAGE_ALIGN(len);
- if (len == 0)
- goto the_end;
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 5c0afe6..11d0e77 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 @@
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 @@
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(); */