1 /* 2 * Copyright (C) 2012 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 <jni.h> 18 #include <unistd.h> 19 #include <sys/types.h> 20 #include <sys/stat.h> 21 #include <fcntl.h> 22 #include <sys/mman.h> 23 #include <cutils/log.h> 24 25 #define PHYS_OFFSET 0x40000000 26 27 /* 28 * Native methods used by 29 * cts/tests/tests/permission/src/android/security/cts/CharDeviceTest.java 30 */ 31 32 jboolean android_security_cts_CharDeviceTest_doExynosWriteTest(JNIEnv* env, jobject thiz) 33 { 34 int page_size = sysconf(_SC_PAGE_SIZE); 35 int length = page_size * page_size; 36 int fd = open("/dev/exynos-mem", O_RDWR); 37 if (fd < 0) { 38 return true; 39 } 40 41 char *addr = (char *) 42 mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, PHYS_OFFSET); 43 44 if (addr == MAP_FAILED) { 45 goto done2; 46 } 47 48 /* 49 * In the presence of the vulnerability, the code below will 50 * cause the device to crash, because we're scribbling all 51 * over kernel memory 52 */ 53 54 int i; 55 for (i = 0; i < length; i++) { 56 addr[i] = 'A'; 57 } 58 usleep(100000); 59 60 done1: 61 munmap(addr, length); 62 done2: 63 close(fd); 64 return true; 65 } 66 67 jboolean android_security_cts_CharDeviceTest_doExynosReadTest(JNIEnv* env, jobject thiz) 68 { 69 const char *MAGIC_STRING = "KHAAAAN!!! EXYNOS!!!"; 70 71 jboolean ret = true; 72 int page_size = sysconf(_SC_PAGE_SIZE); 73 int length = page_size * page_size; 74 int fd = open("/dev/exynos-mem", O_RDONLY); 75 if (fd < 0) { 76 return true; 77 } 78 79 char *addr = (char *) 80 mmap(NULL, length, PROT_READ, MAP_SHARED, fd, PHYS_OFFSET); 81 82 if (addr == MAP_FAILED) { 83 goto done2; 84 } 85 86 // Throw the magic string into the kernel ring buffer. Once 87 // there, we shouldn't be able to access it. 88 ALOGE("%s", MAGIC_STRING); 89 90 // Now see if we can scan kernel memory, looking for our magic 91 // string. If we find it, return false. 92 int i; 93 for (i = 0; i < (length - strlen(MAGIC_STRING)); i++) { 94 if (strncmp(&addr[i], MAGIC_STRING, strlen(MAGIC_STRING)) == 0) { 95 ret = false; 96 break; 97 } 98 } 99 100 done1: 101 munmap(addr, length); 102 done2: 103 close(fd); 104 return ret; 105 } 106 107 static JNINativeMethod gMethods[] = { 108 { "doExynosWriteTest", "()Z", 109 (void *) android_security_cts_CharDeviceTest_doExynosWriteTest }, 110 { "doExynosReadTest", "()Z", 111 (void *) android_security_cts_CharDeviceTest_doExynosReadTest }, 112 }; 113 114 int register_android_security_cts_CharDeviceTest(JNIEnv* env) 115 { 116 jclass clazz = env->FindClass("android/security/cts/CharDeviceTest"); 117 return env->RegisterNatives(clazz, gMethods, 118 sizeof(gMethods) / sizeof(JNINativeMethod)); 119 } 120