sim: invalid alignment checks in mmap and mremap
authorTom Jablin <tjablin@gmail.com>
Mon, 20 Oct 2014 21:45:25 +0000 (16:45 -0500)
committerTom Jablin <tjablin@gmail.com>
Mon, 20 Oct 2014 21:45:25 +0000 (16:45 -0500)
Presently, the alignment checks in the mmap and mremap implementations
in syscall_emul.hh are wrong. The checks are implemented as:

if ((start % TheISA::PageBytes) != 0 ||
        (length % TheISA::PageBytes) != 0) {
    warn("mmap failing: arguments not page-aligned: "
            "start 0x%x length 0x%x",
            start, length);
    return -EINVAL;
}

This checks that both the start and the length arguments of the mmap
syscall are checked for page-alignment. However, the POSIX specification says:

The off argument is constrained to be aligned and sized according to the value
returned by sysconf() when passed _SC_PAGESIZE or _SC_PAGE_SIZE. When MAP_FIXED
is specified, the application shall ensure that the argument addr also meets
these constraints. The implementation performs mapping operations over whole
pages. Thus, while the argument len need not meet a size or alignment
constraint, the implementation shall include, in any mapping operation, any
partial page specified by the range [pa,pa+len).

So the length parameter should not be checked for page-alignment. By contrast,
the current implementation fails to check the offset argument, which must be
page aligned.

Committed by: Nilay Vaish <nilay@cs.wisc.edu>

src/sim/syscall_emul.hh

index 034a7043b656e79b5f49695709dfbcc85f584d5b..f793bc41f47de68f32afb3e27847d970f1008332 100644 (file)
@@ -831,12 +831,13 @@ mremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *
         provided_address = process->getSyscallArg(tc, index);
 
     if ((start % TheISA::PageBytes != 0) ||
-        (new_length % TheISA::PageBytes != 0) ||
         (provided_address % TheISA::PageBytes != 0)) {
         warn("mremap failing: arguments not page aligned");
         return -EINVAL;
     }
 
+    new_length = roundUp(new_length, TheISA::PageBytes);
+
     if (new_length > old_length) {
         if ((start + old_length) == process->mmap_end &&
             (!use_provided_address || provided_address == start)) {
@@ -1213,7 +1214,7 @@ mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
     index++; // int prot = p->getSyscallArg(tc, index);
     int flags = p->getSyscallArg(tc, index);
     int tgt_fd = p->getSyscallArg(tc, index);
-    // int offset = p->getSyscallArg(tc, index);
+    int offset = p->getSyscallArg(tc, index);
 
     if (length > 0x100000000ULL)
         warn("mmap length argument %#x is unreasonably large.\n", length);
@@ -1234,11 +1235,13 @@ mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
         }
     }
 
+    length = roundUp(length, TheISA::PageBytes);
+
     if ((start  % TheISA::PageBytes) != 0 ||
-        (length % TheISA::PageBytes) != 0) {
+        (offset % TheISA::PageBytes) != 0) {
         warn("mmap failing: arguments not page-aligned: "
-             "start 0x%x length 0x%x",
-             start, length);
+             "start 0x%x offset 0x%x",
+             start, offset);
         return -EINVAL;
     }