upload android base code part6
This commit is contained in:
parent
421e214c7d
commit
4e516ec6ed
35396 changed files with 9188716 additions and 0 deletions
248
android/system/extras/tests/kernel.config/aslr_test.cpp
Normal file
248
android/system/extras/tests/kernel.config/aslr_test.cpp
Normal file
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* Copyright (C) 2016 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 <ctype.h>
|
||||
|
||||
#include "aslr_test.h"
|
||||
|
||||
unsigned int get_mmap_rnd_bits(bool compat) {
|
||||
std::string path;
|
||||
|
||||
if (compat)
|
||||
path = PROCFS_COMPAT_PATH;
|
||||
else
|
||||
path = PROCFS_PATH;
|
||||
|
||||
std::ifstream bi_file(path);
|
||||
if (!bi_file)
|
||||
return false;
|
||||
std::string str_rec;
|
||||
bi_file >> str_rec;
|
||||
|
||||
return stoi(str_rec);
|
||||
}
|
||||
|
||||
bool set_mmap_rnd_bits(unsigned int new_val, bool compat) {
|
||||
std::string path;
|
||||
|
||||
if (compat)
|
||||
path = "/proc/sys/vm/mmap_rnd_compat_bits";
|
||||
else
|
||||
path = "/proc/sys/vm/mmap_rnd_bits";
|
||||
|
||||
std::ofstream bo_file(path, std::ios::out);
|
||||
if (!bo_file)
|
||||
return false;
|
||||
|
||||
std::string str_val = std::to_string(new_val);
|
||||
bo_file << str_val << std::flush;
|
||||
bo_file.close();
|
||||
|
||||
// check to make sure it was recorded
|
||||
std::ifstream bi_file(path);
|
||||
if (!bi_file)
|
||||
return false;
|
||||
std::string str_rec;
|
||||
bi_file >> str_rec;
|
||||
bi_file.close();
|
||||
if (str_val.compare(str_rec) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string scrape_addr(const char *exec_name, const char *lib_match) {
|
||||
pid_t pid;
|
||||
int fd[2];
|
||||
char buff[MAX_ADDR_LEN];
|
||||
int len, status;
|
||||
if(pipe(fd)) {
|
||||
std::cerr << "Error creating pipe:" << strerror(errno) << "\n";
|
||||
return std::string();
|
||||
}
|
||||
|
||||
if ((pid = fork()) < 0) {
|
||||
std::cerr << "Error creating new process: " << strerror(errno) << "\n";
|
||||
close(fd[0]);
|
||||
close(fd[1]);
|
||||
return std::string();
|
||||
} else if (pid > 0) {
|
||||
// parent
|
||||
close(fd[1]);
|
||||
wait(&status);
|
||||
if (status == -1) {
|
||||
std::cerr << "Unable to find starting address of mmapp'd libc. Aborting.\n";
|
||||
close(fd[0]);
|
||||
return std::string();
|
||||
}
|
||||
len = read(fd[0], buff, MAX_ADDR_LEN - 1);
|
||||
if (len < 0) {
|
||||
std::cerr << "Error reading pipe from child: " << strerror(errno) << "\n";
|
||||
close(fd[0]);
|
||||
return std::string();
|
||||
}
|
||||
buff[len] = '\0';
|
||||
close(fd[0]);
|
||||
} else {
|
||||
// child, dup 'n' exec
|
||||
close(fd[0]);
|
||||
if(dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
|
||||
std::cerr << "Error dup'n pipe to STDOUT of child: " << strerror(errno) << "\n";
|
||||
close(fd[1]);
|
||||
return std::string();
|
||||
}
|
||||
if(execlp(exec_name, exec_name, lib_match, (char *) NULL)) {
|
||||
std::cerr << "Error exec'ing mmap_scraper: " << strerror(errno) << "\n";
|
||||
close(fd[1]);
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
return std::string(buff, strlen(buff));
|
||||
}
|
||||
|
||||
unsigned int calc_mmap_entropy(const char *exec_name, const char *lib_match, size_t samp_sz) {
|
||||
uint64_t addr, min_addr, max_addr;
|
||||
|
||||
std::unordered_set<uint64_t> addrs = { };
|
||||
|
||||
// get our first value
|
||||
std::string addr_str = scrape_addr(exec_name, lib_match);
|
||||
if (addr_str.empty()) {
|
||||
std::cerr << "empty first address";
|
||||
return 0;
|
||||
}
|
||||
if (!isxdigit(addr_str[0])) {
|
||||
std::cerr << "invalid address: " << addr_str;
|
||||
return 0;
|
||||
}
|
||||
addr = min_addr = max_addr = std::stoll(addr_str, 0, 16);
|
||||
addrs.insert(addr);
|
||||
for (unsigned int i = 0; i < samp_sz - 1; ++i) {
|
||||
addr_str = scrape_addr(exec_name, lib_match);
|
||||
if (addr_str.empty()) {
|
||||
std::cerr << "empty address";
|
||||
return 0;
|
||||
}
|
||||
if (!isxdigit(addr_str[0])) {
|
||||
std::cerr << "invalid address: " << addr_str;
|
||||
return 0;
|
||||
}
|
||||
addr = std::stoll(addr_str, 0, 16);
|
||||
if (addr < min_addr)
|
||||
min_addr = addr;
|
||||
if (addr >= max_addr)
|
||||
max_addr = addr;
|
||||
addrs.insert(addr);
|
||||
}
|
||||
if (addrs.size() < (samp_sz >> 1)) {
|
||||
std::cerr << "> 50% collisions in mmap addresses, entropy appears to be rigged!";
|
||||
return 0;
|
||||
}
|
||||
unsigned int e_bits = (int) (std::ceil(std::log2(max_addr - min_addr)) - std::log2(getpagesize()));
|
||||
return e_bits;
|
||||
}
|
||||
|
||||
const char *AslrMmapTest::path;
|
||||
const char *AslrMmapTest::lib;
|
||||
unsigned int AslrMmapTest::def, AslrMmapTest::min, AslrMmapTest::max;
|
||||
bool AslrMmapTest::compat = false, AslrMmapTest::user32 = false;
|
||||
unsigned int AslrMmapTest::def_cmpt, AslrMmapTest::min_cmpt, AslrMmapTest::max_cmpt;
|
||||
|
||||
void AslrMmapTest::SetUpTestCase() {
|
||||
/* set up per-arch values */
|
||||
#if defined(__x86_64__)
|
||||
def = 32;
|
||||
min = 28;
|
||||
max = 32;
|
||||
path = SCRAPE_PATH_64;
|
||||
lib = SCRAPE_LIB_64;
|
||||
|
||||
compat = true;
|
||||
def_cmpt = 16;
|
||||
min_cmpt = 8;
|
||||
max_cmpt = 16;
|
||||
|
||||
#elif defined(__i386__)
|
||||
def = 16;
|
||||
min = 8;
|
||||
max = 16;
|
||||
path = SCRAPE_PATH_32;
|
||||
lib = SCRAPE_LIB_32;
|
||||
|
||||
if (!access(PROCFS_COMPAT_PATH, F_OK)) {
|
||||
// running 32 bit userspace over 64-bit kernel
|
||||
user32 = true;
|
||||
def_cmpt = 16;
|
||||
min_cmpt = 8;
|
||||
max_cmpt = 16;
|
||||
}
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
unsigned int pgbits = std::log2(getpagesize());
|
||||
def = 24;
|
||||
min = 18 - (pgbits - 12);
|
||||
max = 24;
|
||||
path = SCRAPE_PATH_64;
|
||||
lib = SCRAPE_LIB_64;
|
||||
|
||||
compat = true;
|
||||
def_cmpt = 16;
|
||||
min_cmpt = 11 - (pgbits - 12);
|
||||
max_cmpt = 16;
|
||||
|
||||
#elif defined(__arm__)
|
||||
unsigned int pgbits = std::log2(getpagesize());
|
||||
def = 16;
|
||||
min = 8;
|
||||
max = 16;
|
||||
path = SCRAPE_PATH_32;
|
||||
lib = SCRAPE_LIB_32;
|
||||
|
||||
if (!access(PROCFS_COMPAT_PATH, F_OK)) {
|
||||
// running 32 bit userspace over 64-bit kernel
|
||||
user32 = true;
|
||||
def_cmpt = 16;
|
||||
min_cmpt = 11 - (pgbits - 12);;
|
||||
max_cmpt = 16;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void AslrMmapTest::TearDown() {
|
||||
if (!user32)
|
||||
set_mmap_rnd_bits(def, false);
|
||||
if (user32 || compat)
|
||||
set_mmap_rnd_bits(def_cmpt, true);
|
||||
}
|
||||
|
||||
/* run tests only if on supported arch */
|
||||
#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || defined(__arm__)
|
||||
|
||||
TEST_F(AslrMmapTest, entropy_min_def) {
|
||||
if (user32) {
|
||||
// running 32-bit userspace on 64-bit kernel, only compat used.
|
||||
return;
|
||||
} else {
|
||||
EXPECT_GE(def, calc_mmap_entropy(path, lib, 16));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(AslrMmapTest, entropy_min_cmpt_def) {
|
||||
if (compat || user32) {
|
||||
EXPECT_GE(def_cmpt, calc_mmap_entropy(SCRAPE_PATH_32, SCRAPE_LIB_32, 16));
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* supported arch */
|
Loading…
Add table
Add a link
Reference in a new issue