Set mmap_rnd_bits to maximum value.

This is a cherry-pick of internal commit:
f611291688 which was a revert of a
revert, specifically a  revert of commit:
c8f026fc9c.

The above revert was meant only for AOSP, since the kernel prebuilts
were not yet available there.  The revert was reverted internally so
that internal builds, which have the appropriate kernel prebuilts,
operated properly.

The very first commit was originally done in nougat-dev and cherry-picked
to AOSP, so it was not picked up again when nougat landed in master.  Add
it now.

Bug: 27681085
Test: Builds and boots.
Change-Id: If1cb6308e61aaaabca5b5bd30df78aab49e7b0d5
This commit is contained in:
Daniel Cashman 2016-03-25 23:49:05 +00:00 committed by dcashman
parent d619026c07
commit baccc40841
1 changed files with 108 additions and 5 deletions

View File

@ -18,6 +18,7 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <fstream>
#include <inttypes.h>
#include <libgen.h>
#include <paths.h>
@ -256,6 +257,112 @@ ret:
return result;
}
static void security_failure() {
LOG(ERROR) << "Security failure...";
panic();
}
#define MMAP_RND_PATH "/proc/sys/vm/mmap_rnd_bits"
#define MMAP_RND_COMPAT_PATH "/proc/sys/vm/mmap_rnd_compat_bits"
/* __attribute__((unused)) due to lack of mips support: see mips block
* in set_mmap_rnd_bits_action */
static bool __attribute__((unused)) set_mmap_rnd_bits_min(int start, int min, bool compat) {
std::string path;
if (compat) {
path = MMAP_RND_COMPAT_PATH;
} else {
path = MMAP_RND_PATH;
}
std::ifstream inf(path, std::fstream::in);
if (!inf) {
LOG(ERROR) << "Cannot open for reading: " << path;
return false;
}
while (start >= min) {
// try to write out new value
std::string str_val = std::to_string(start);
std::ofstream of(path, std::fstream::out);
if (!of) {
LOG(ERROR) << "Cannot open for writing: " << path;
return false;
}
of << str_val << std::endl;
of.close();
// check to make sure it was recorded
inf.seekg(0);
std::string str_rec;
inf >> str_rec;
if (str_val.compare(str_rec) == 0) {
break;
}
start--;
}
inf.close();
if (start < min) {
LOG(ERROR) << "Unable to set minimum required entropy " << min << " in " << path;
return false;
}
return true;
}
/*
* Set /proc/sys/vm/mmap_rnd_bits and potentially
* /proc/sys/vm/mmap_rnd_compat_bits to the maximum supported values.
* Returns -1 if unable to set these to an acceptable value.
*
* To support this sysctl, the following upstream commits are needed:
*
* d07e22597d1d mm: mmap: add new /proc tunable for mmap_base ASLR
* e0c25d958f78 arm: mm: support ARCH_MMAP_RND_BITS
* 8f0d3aa9de57 arm64: mm: support ARCH_MMAP_RND_BITS
* 9e08f57d684a x86: mm: support ARCH_MMAP_RND_BITS
* ec9ee4acd97c drivers: char: random: add get_random_long()
* 5ef11c35ce86 mm: ASLR: use get_random_long()
*/
static int set_mmap_rnd_bits_action(const std::vector<std::string>& args)
{
int ret = -1;
/* values are arch-dependent */
#if defined(__aarch64__)
/* arm64 supports 18 - 33 bits depending on pagesize and VA_SIZE */
if (set_mmap_rnd_bits_min(33, 24, false)
&& set_mmap_rnd_bits_min(16, 16, true)) {
ret = 0;
}
#elif defined(__x86_64__)
/* x86_64 supports 28 - 32 bits */
if (set_mmap_rnd_bits_min(32, 32, false)
&& set_mmap_rnd_bits_min(16, 16, true)) {
ret = 0;
}
#elif defined(__arm__) || defined(__i386__)
/* check to see if we're running on 64-bit kernel */
bool h64 = !access(MMAP_RND_COMPAT_PATH, F_OK);
/* supported 32-bit architecture must have 16 bits set */
if (set_mmap_rnd_bits_min(16, 16, h64)) {
ret = 0;
}
#elif defined(__mips__) || defined(__mips64__)
// TODO: add mips support b/27788820
ret = 0;
#else
ERROR("Unknown architecture\n");
#endif
#ifdef __BRILLO__
// TODO: b/27794137
ret = 0;
#endif
if (ret == -1) {
LOG(ERROR) << "Unable to set adequate mmap entropy value!";
security_failure();
}
return ret;
}
static int keychord_init_action(const std::vector<std::string>& args)
{
keychord_init();
@ -414,11 +521,6 @@ static int audit_callback(void *data, security_class_t /*cls*/, char *buf, size_
return 0;
}
static void security_failure() {
LOG(ERROR) << "Security failure...";
panic();
}
static void selinux_initialize(bool in_kernel_domain) {
Timer t;
@ -712,6 +814,7 @@ int main(int argc, char** argv) {
am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done");
// ... so that we can start queuing up actions that require stuff from /dev.
am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");
am.QueueBuiltinAction(keychord_init_action, "keychord_init");
am.QueueBuiltinAction(console_init_action, "console_init");