From beeeee705bcf16d705748713ea40dca3486cc7b7 Mon Sep 17 00:00:00 2001
From: Nick Kralevich <nnk@google.com>
Date: Thu, 6 May 2010 15:05:52 -0700
Subject: [PATCH] Allow pixelflinger to work when NX (No Execute) is enabled.

Instead of allocating memory from the (non executable) heap,
allocate memory using mspace and ensure that we use mprotect
to mark it as PROT_EXEC.  This allows pixelflinger to
continue to work even when NX protections are enabled.

Testing: Using the ApiDemos market app, verify that
Apidemos -> Graphics -> OpenGL ES -> GLSurfaceView
works when "adb shell setprop debug.egl.hw 0" is set.

Change-Id: Ib569cd2543c6fa25688ee76325a712bc2347450b
---
 libpixelflinger/codeflinger/CodeCache.cpp | 34 +++++++++++++++++++----
 libpixelflinger/codeflinger/CodeCache.h   |  6 +++-
 2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/libpixelflinger/codeflinger/CodeCache.cpp b/libpixelflinger/codeflinger/CodeCache.cpp
index 29410c8ab6..5877ff4a56 100644
--- a/libpixelflinger/codeflinger/CodeCache.cpp
+++ b/libpixelflinger/codeflinger/CodeCache.cpp
@@ -19,6 +19,8 @@
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
 
 #include <cutils/log.h>
 #include <cutils/atomic.h>
@@ -39,15 +41,14 @@ namespace android {
 Assembly::Assembly(size_t size)
     : mCount(1), mSize(0)
 {
-    mBase = (uint32_t*)malloc(size);
-    if (mBase) {
-        mSize = size;
-    }
+    mBase = (uint32_t*)mspace_malloc(getMspace(), size);
+    mSize = size;
+    ensureMbaseExecutable();
 }
 
 Assembly::~Assembly()
 {
-    free(mBase);
+    mspace_free(getMspace(), mBase);
 }
 
 void Assembly::incStrong(const void*) const
@@ -75,11 +76,32 @@ uint32_t* Assembly::base() const
 
 ssize_t Assembly::resize(size_t newSize)
 {
-    mBase = (uint32_t*)realloc(mBase, newSize);
+    mBase = (uint32_t*)mspace_realloc(getMspace(), mBase, newSize);
     mSize = newSize;
+    ensureMbaseExecutable();
     return size();
 }
 
+mspace Assembly::getMspace()
+{
+    static mspace msp = create_contiguous_mspace(2 * 1024, 1024 * 1024, /*locked=*/ false);
+    return msp;
+}
+
+void Assembly::ensureMbaseExecutable()
+{
+    long pagesize = sysconf(_SC_PAGESIZE);
+    long pagemask = ~(pagesize - 1);  // assumes pagesize is a power of 2
+
+    uint32_t* pageStart = (uint32_t*) (((uintptr_t) mBase) & pagemask);
+    size_t adjustedLength = mBase - pageStart + mSize;
+
+    if (mBase && mprotect(pageStart, adjustedLength, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) {
+        mspace_free(getMspace(), mBase);
+        mBase = NULL;
+    }
+}
+
 // ----------------------------------------------------------------------------
 
 CodeCache::CodeCache(size_t size)
diff --git a/libpixelflinger/codeflinger/CodeCache.h b/libpixelflinger/codeflinger/CodeCache.h
index 8ff1366822..aaafd26cc9 100644
--- a/libpixelflinger/codeflinger/CodeCache.h
+++ b/libpixelflinger/codeflinger/CodeCache.h
@@ -22,6 +22,7 @@
 #include <stdint.h>
 #include <pthread.h>
 #include <sys/types.h>
+#include <cutils/mspace.h>
 
 #include "tinyutils/KeyedVector.h"
 #include "tinyutils/smartpointer.h"
@@ -67,9 +68,12 @@ public:
     typedef void    weakref_type;
 
 private:
+    static  mspace  getMspace();
+            void    ensureMbaseExecutable();
+
     mutable int32_t     mCount;
             uint32_t*   mBase;
-            ssize_t     mSize;
+            size_t      mSize;
 };
 
 // ----------------------------------------------------------------------------
-- 
GitLab