blob: 32f204fdf4e0bcbb3e73b17a568a1f9c2aa7d5de [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <cutils/log.h>
#define PHYS_OFFSET 0x40000000
/*
* Native methods used by
* cts/tests/tests/permission/src/android/security/cts/CharDeviceTest.java
*/
jboolean android_security_cts_CharDeviceTest_doExynosWriteTest(JNIEnv* env, jobject thiz)
{
int page_size = sysconf(_SC_PAGE_SIZE);
int length = page_size * page_size;
int fd = open("/dev/exynos-mem", O_RDWR);
if (fd < 0) {
return true;
}
char *addr = (char *)
mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, PHYS_OFFSET);
if (addr == MAP_FAILED) {
goto done2;
}
/*
* In the presence of the vulnerability, the code below will
* cause the device to crash, because we're scribbling all
* over kernel memory
*/
int i;
for (i = 0; i < length; i++) {
addr[i] = 'A';
}
usleep(100000);
done1:
munmap(addr, length);
done2:
close(fd);
return true;
}
jboolean android_security_cts_CharDeviceTest_doExynosReadTest(JNIEnv* env, jobject thiz)
{
const char *MAGIC_STRING = "KHAAAAN!!! EXYNOS!!!";
jboolean ret = true;
int page_size = sysconf(_SC_PAGE_SIZE);
int length = page_size * page_size;
int fd = open("/dev/exynos-mem", O_RDONLY);
if (fd < 0) {
return true;
}
char *addr = (char *)
mmap(NULL, length, PROT_READ, MAP_SHARED, fd, PHYS_OFFSET);
if (addr == MAP_FAILED) {
goto done2;
}
// Throw the magic string into the kernel ring buffer. Once
// there, we shouldn't be able to access it.
ALOGE("%s", MAGIC_STRING);
// Now see if we can scan kernel memory, looking for our magic
// string. If we find it, return false.
int i;
for (i = 0; i < (length - strlen(MAGIC_STRING)); i++) {
if (strncmp(&addr[i], MAGIC_STRING, strlen(MAGIC_STRING)) == 0) {
ret = false;
break;
}
}
done1:
munmap(addr, length);
done2:
close(fd);
return ret;
}
static JNINativeMethod gMethods[] = {
{ "doExynosWriteTest", "()Z",
(void *) android_security_cts_CharDeviceTest_doExynosWriteTest },
{ "doExynosReadTest", "()Z",
(void *) android_security_cts_CharDeviceTest_doExynosReadTest },
};
int register_android_security_cts_CharDeviceTest(JNIEnv* env)
{
jclass clazz = env->FindClass("android/security/cts/CharDeviceTest");
return env->RegisterNatives(clazz, gMethods,
sizeof(gMethods) / sizeof(JNINativeMethod));
}