Bug 1450793 - Guard against mprotect() failure when manipulating link map r=glandium draft
authorJames Willcox <snorp@snorp.net>
Wed, 11 Apr 2018 16:49:11 -0500
changeset 780837 0bb3a0f0d20b0858134569ed4af78fd4ef3aacf6
parent 779934 5b37b68e62c8a8a30f6e50c6bb1473a1a6962770
child 780838 862737f90cf5f1f76210f1d99cc8e6b0de3bc76d
child 781061 cefa2f0064089c6d464bfe55d5d64ca6cbca1a09
push id106136
push userbmo:snorp@snorp.net
push dateThu, 12 Apr 2018 02:48:02 +0000
reviewersglandium
bugs1450793
milestone61.0a1
Bug 1450793 - Guard against mprotect() failure when manipulating link map r=glandium MozReview-Commit-ID: 7orhBmf4j5j
mozglue/linker/ElfLoader.cpp
--- a/mozglue/linker/ElfLoader.cpp
+++ b/mozglue/linker/ElfLoader.cpp
@@ -898,22 +898,30 @@ public:
     prot = getProt(start, &end);
     if (prot == -1 || (start + length) > end)
       MOZ_CRASH();
 
     if (prot & PROT_WRITE)
       return;
 
     page = firstPage;
-    mprotect(page, length, prot | PROT_WRITE);
+    success = (mprotect(page, length, prot | PROT_WRITE) == 0);
+    if (!success) {
+      ERROR("Failed to make %p - 0x%x writable: %s\n", ptr,
+            intptr_t(ptr) + length, strerror(errno));
+    }
+  }
+
+  bool IsWritable() {
+    return success;
   }
 
   ~EnsureWritable()
   {
-    if (page != MAP_FAILED) {
+    if (success && page != MAP_FAILED) {
       mprotect(page, length, prot);
 }
   }
 
 private:
   int getProt(uintptr_t addr, uintptr_t *end)
   {
     /* The interesting part of the /proc/self/maps format looks like:
@@ -943,16 +951,17 @@ private:
       return result;
     }
     return -1;
   }
 
   int prot;
   void *page;
   size_t length;
+  bool success;
 };
 
 /**
  * The system linker maintains a doubly linked list of library it loads
  * for use by the debugger. Unfortunately, it also uses the list pointers
  * in a lot of operations and adding our data in the list is likely to
  * trigger crashes when the linker tries to use data we don't provide or
  * that fall off the amount data we allocated. Fortunately, the linker only
@@ -975,16 +984,20 @@ ElfLoader::DebuggerHelper::Add(ElfLoader
   dbg->r_brk();
   map->l_prev = nullptr;
   map->l_next = dbg->r_map;
   if (!firstAdded) {
     firstAdded = map;
     /* When adding a library for the first time, r_map points to data
      * handled by the system linker, and that data may be read-only */
     EnsureWritable w(&dbg->r_map->l_prev);
+    if (!w.IsWritable()) {
+      return;
+    }
+
     dbg->r_map->l_prev = map;
   } else
     dbg->r_map->l_prev = map;
   dbg->r_map = map;
   dbg->r_state = r_debug::RT_CONSISTENT;
   dbg->r_brk();
 }
 
@@ -1000,16 +1013,20 @@ ElfLoader::DebuggerHelper::Remove(ElfLoa
   else if (map->l_prev) {
     map->l_prev->l_next = map->l_next;
   }
   if (map == firstAdded) {
     firstAdded = map->l_prev;
     /* When removing the first added library, its l_next is going to be
      * data handled by the system linker, and that data may be read-only */
     EnsureWritable w(&map->l_next->l_prev);
+    if (!w.IsWritable()) {
+      return;
+    }
+
     map->l_next->l_prev = map->l_prev;
   } else if (map->l_next) {
     map->l_next->l_prev = map->l_prev;
   }
   dbg->r_state = r_debug::RT_CONSISTENT;
   dbg->r_brk();
 }