Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  *
     16  */
     17 #include <errno.h>
     18 #include <jni.h>
     19 #include <string.h>
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 #include <unistd.h>
     23 #include <cutils/log.h>
     24 #include <inttypes.h>
     25 
     26 static jboolean isAddressExecutable(uintptr_t address) {
     27     char line[1024];
     28     jboolean retval = false;
     29     FILE *fp = fopen("/proc/self/maps", "re");
     30     if (fp == NULL) {
     31         ALOGE("Unable to open /proc/self/maps: %s", strerror(errno));
     32         return false;
     33     }
     34     while(fgets(line, sizeof(line), fp) != NULL) {
     35         uintptr_t start;
     36         uintptr_t end;
     37         char permissions[10];
     38         int scan = sscanf(line, "%" SCNxPTR "-%" SCNxPTR " %9s ", &start, &end, permissions);
     39         if ((scan == 3) && (start <= address) && (address < end)) {
     40             retval = (permissions[2] == 'x');
     41             break;
     42         }
     43     }
     44     fclose(fp);
     45     return retval;
     46 }
     47 
     48 static jboolean android_os_cts_NoExecutePermissionTest_isMyCodeExecutable(JNIEnv*, jobject)
     49 {
     50     return isAddressExecutable((uintptr_t) __builtin_return_address(0));
     51 }
     52 
     53 static jboolean android_os_cts_NoExecutePermissionTest_isStackExecutable(JNIEnv*, jobject)
     54 {
     55     unsigned int foo;
     56     return isAddressExecutable((uintptr_t) &foo);
     57 }
     58 
     59 
     60 static jboolean android_os_cts_NoExecutePermissionTest_isHeapExecutable(JNIEnv*, jobject)
     61 {
     62     unsigned int* foo = (unsigned int *) malloc(sizeof(unsigned int));
     63     if (foo == NULL) {
     64         ALOGE("Unable to allocate memory");
     65         return false;
     66     }
     67     jboolean result = isAddressExecutable((uintptr_t) foo);
     68     free(foo);
     69     return result;
     70 }
     71 
     72 static JNINativeMethod gMethods[] = {
     73     {  "isMyCodeExecutable", "()Z",
     74             (void *) android_os_cts_NoExecutePermissionTest_isMyCodeExecutable  },
     75     {  "isStackExecutable", "()Z",
     76             (void *) android_os_cts_NoExecutePermissionTest_isStackExecutable  },
     77     {  "isHeapExecutable", "()Z",
     78             (void *) android_os_cts_NoExecutePermissionTest_isHeapExecutable  }
     79 };
     80 
     81 int register_android_os_cts_NoExecutePermissionTest(JNIEnv* env)
     82 {
     83     jclass clazz = env->FindClass("android/os/cts/NoExecutePermissionTest");
     84 
     85     return env->RegisterNatives(clazz, gMethods,
     86             sizeof(gMethods) / sizeof(JNINativeMethod));
     87 }
     88