Bug 828894 - Fix possible off-by-one-page in custom linker. r=nfroyd
authorMike Hommey <mh+mozilla@glandium.org>
Fri, 11 Jan 2013 12:24:31 +0100
changeset 118560 b88aa014ffa625287e66797324052c40f800ce71
parent 118559 a4d691c7bacbe01c0043a129d2590c5c17a525af
child 118561 dd30a971ed826e38f78f4da26eb648aedb6288b0
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersnfroyd
bugs828894
milestone21.0a1
Bug 828894 - Fix possible off-by-one-page in custom linker. r=nfroyd
mozglue/linker/Mappable.cpp
--- a/mozglue/linker/Mappable.cpp
+++ b/mozglue/linker/Mappable.cpp
@@ -192,22 +192,23 @@ public:
     strlcpy(str, name, sizeof(str));
     ioctl(fd, ASHMEM_SET_NAME, str);
     if (ioctl(fd, ASHMEM_SET_SIZE, length))
       return NULL;
 
     /* The Gecko crash reporter is confused by adjacent memory mappings of
      * the same file. On Android, subsequent mappings are growing in memory
      * address, and chances are we're going to map from the same file
-     * descriptor right away. Allocate one page more than requested so that
-     * there is a gap between this mapping and the subsequent one. */
+     * descriptor right away. To avoid problems with the crash reporter,
+     * create an empty anonymous page after the ashmem mapping. To do so,
+     * allocate one page more than requested, then replace the last page with
+     * an anonymous mapping. */
     void *buf = ::mmap(NULL, length + PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
     if (buf != MAP_FAILED) {
-      /* Actually create the gap with anonymous memory */
-      ::mmap(reinterpret_cast<char *>(buf) + ((length + PAGE_SIZE) & PAGE_MASK),
+      ::mmap(reinterpret_cast<char *>(buf) + ((length + PAGE_SIZE - 1) & PAGE_MASK),
              PAGE_SIZE, PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
              -1, 0);
       debug("Decompression buffer of size %d in ashmem \"%s\", mapped @%p",
             length, str, buf);
       return new _MappableBuffer(fd.forget(), buf, length);
     }
 #else
     /* On Linux, use /dev/shm as base directory for temporary files, assuming
@@ -243,17 +244,17 @@ public:
     }
 #endif
     return ::mmap(const_cast<void *>(addr), length, prot, flags, fd, offset);
   }
 
 #ifdef ANDROID
   ~_MappableBuffer() {
     /* Free the additional page we allocated. See _MappableBuffer::Create */
-    ::munmap(*this + ((GetLength() + PAGE_SIZE) & ~(PAGE_SIZE - 1)), PAGE_SIZE);
+    ::munmap(*this + ((GetLength() + PAGE_SIZE - 1) & PAGE_MASK), PAGE_SIZE);
   }
 #endif
 
 private:
   _MappableBuffer(int fd, void *buf, size_t length)
   : MappedPtr(buf, length), fd(fd) { }
 
   /* File descriptor for the temporary file or ashmem */