Do not try to read/write device memory.

Device memory might have certain alignment constraints that the unwind
code violates. Since we shouldn't be reading this memory, treat this
type of memory as not readable and not writable.

Bug: 17037053

(cherry picked from commit f360ccc06f3f086f41cf6ba4036b52571ed2a54f)

Change-Id: I912e8645fe1f9223100d00559f9cea1f87931e45
diff --git a/include/map_info.h b/include/map_info.h
index e5fe425..9e18c01 100644
--- a/include/map_info.h
+++ b/include/map_info.h
@@ -25,6 +25,9 @@
 #ifndef map_info_h
 #define map_info_h
 
+/* Must not conflict with PROT_{NONE,READ,WRITE}. */
+#define MAP_FLAGS_DEVICE_MEM  0x8000
+
 struct map_info
   {
     uintptr_t start;
diff --git a/src/Los-common.c b/src/Los-common.c
index c501732..cad43d0 100644
--- a/src/Los-common.c
+++ b/src/Los-common.c
@@ -126,7 +126,14 @@
   lock_rdwr_rd_acquire (&local_rdwr_lock, saved_mask);
   map = map_find_from_addr (local_map_list, addr);
   if (map != NULL)
-    ret = map->flags & flag;
+    {
+      if (map->flags & MAP_FLAGS_DEVICE_MEM)
+        {
+          lock_rdwr_release (&local_rdwr_lock, saved_mask);
+          return 0;
+        }
+      ret = map->flags & flag;
+    }
   lock_rdwr_release (&local_rdwr_lock, saved_mask);
 
   if (!ret && rebuild_if_necessary (addr, flag) == 0)
diff --git a/src/os-linux.c b/src/os-linux.c
index 647ddf9..b052e06 100644
--- a/src/os-linux.c
+++ b/src/os-linux.c
@@ -57,6 +57,16 @@
       cur_map->ei.size = 0;
       cur_map->ei.image = NULL;
 
+      /* Indicate mapped memory of devices is special and should not
+         be read or written. Use a special flag instead of zeroing the
+         flags to indicate that the maps do not need to be rebuilt if
+         any values ever wind up in these special maps.
+         /dev/ashmem/... maps are special and don't have any restrictions,
+         so don't mark them as device memory.  */
+      if (strncmp ("/dev/", cur_map->path, 5) == 0
+          && strncmp ("ashmem/", cur_map->path + 5, 7) != 0)
+        cur_map->flags |= MAP_FLAGS_DEVICE_MEM;
+
       map_list = cur_map;
     }