| Index: content/test/content_android_linker_unittest.cc
|
| diff --git a/content/test/content_android_linker_unittest.cc b/content/test/content_android_linker_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..aaab0f9b82621366e7ca70b0cc3d2554188158dc
|
| --- /dev/null
|
| +++ b/content/test/content_android_linker_unittest.cc
|
| @@ -0,0 +1,129 @@
|
| +// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef CONTENT_TEST_CONTENT_LINKER_UNITTEST_H
|
| +#define CONTENT_TEST_CONTENT_LINKER_UNITTEST_H
|
| +
|
| +#include <errno.h>
|
| +#include <sys/mman.h>
|
| +#include <stdio.h>
|
| +#include <string>
|
| +
|
| +#include "base/basictypes.h"
|
| +#include "base/debug/proc_maps_linux.h"
|
| +#include "base/strings/stringprintf.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace content {
|
| +
|
| +namespace {
|
| +
|
| +// The RELRO section(s), after being copied into an ashmem region, will
|
| +// appear in /proc/self/maps as a mapped memory region for a file name
|
| +// that begins with the following prefix.
|
| +//
|
| +// Note that the full name will be something like:
|
| +// "/dev/ashmem/RELRO:<libname> (deleted)"
|
| +//
|
| +// Where <libname> is the library name and '(deleted)' is actually
|
| +// added by the kernel to indicate there is no corresponding file
|
| +// on the filesystem.
|
| +//
|
| +// For regular builds, there is only one library, and thus one RELRO
|
| +// section, but for the component build, there are several libraries,
|
| +// each one with its own RELRO.
|
| +static const char kRelroSectionPrefix[] = "/dev/ashmem/RELRO:";
|
| +
|
| +using base::debug::MappedMemoryRegion;
|
| +
|
| +class ContentLinkerTest : public ::testing::Test {
|
| + public:
|
| + ContentLinkerTest()
|
| + : regions_(), relro_section_prefix_(kRelroSectionPrefix) {}
|
| +
|
| + protected:
|
| + virtual void SetUp() {
|
| + regions_.clear();
|
| + std::string maps;
|
| + base::debug::ReadProcMaps(&maps);
|
| + base::debug::ParseProcMaps(maps, ®ions_);
|
| + }
|
| +
|
| + virtual void TearDown() {}
|
| +
|
| + std::vector<MappedMemoryRegion> regions_;
|
| + std::string relro_section_prefix_;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +// This test checks that our content-based library has been loaded
|
| +// and that its RELRO section is in an ashmem region, with a name
|
| +// that begins with /dev/ashmem/RELRO:
|
| +//
|
| +TEST_F(ContentLinkerTest, RelroInAshmem) {
|
| + size_t count = 0;
|
| +
|
| + for (size_t n = 0; n < regions_.size(); ++n) {
|
| + MappedMemoryRegion& region = regions_[n];
|
| +
|
| + if (region.path.find(relro_section_prefix_) == 0)
|
| + count++;
|
| + }
|
| +
|
| + // Can't use EXPECT_EQ here due to the component build having
|
| + // many libraries loaded through our linker, each one with its own
|
| + // shared RELRO section. There are also plenty of system libraries
|
| + // without a shared RELRO section as well.
|
| + EXPECT_GE(count, 1U)
|
| + << "The number of RELRO sections in ashmem regions in this process\n";
|
| +}
|
| +
|
| +// This test checks that every shared RELRO section is always read-only
|
| +// and non-executable.
|
| +TEST_F(ContentLinkerTest, RelroIsReadOnly) {
|
| + uint8 expected_flags = MappedMemoryRegion::READ;
|
| + uint8 expected_mask = MappedMemoryRegion::READ | MappedMemoryRegion::WRITE |
|
| + MappedMemoryRegion::EXECUTE;
|
| +
|
| + for (size_t n = 0; n < regions_.size(); ++n) {
|
| + MappedMemoryRegion& region = regions_[n];
|
| +
|
| + if (region.path.find(relro_section_prefix_) != 0)
|
| + continue;
|
| +
|
| + EXPECT_EQ(expected_flags, region.permissions & expected_mask)
|
| + << base::StringPrintf(
|
| + "Checking permissions for RELRO region at %p-%p\n",
|
| + reinterpret_cast<void*>(region.start),
|
| + reinterpret_cast<void*>(region.end));
|
| + }
|
| +}
|
| +
|
| +// This test checks that each RELRO section cannot be remapped read-write
|
| +// with mprotect(), for security reasons.
|
| +TEST_F(ContentLinkerTest, RelroCantBeRemappedWritable) {
|
| + for (size_t n = 0; n < regions_.size(); ++n) {
|
| + MappedMemoryRegion& region = regions_[n];
|
| +
|
| + if (region.path.find(relro_section_prefix_) != 0)
|
| + continue;
|
| +
|
| + std::string text = base::StringPrintf(
|
| + "Checking non-writability for RELRO region at %p-%p\n",
|
| + reinterpret_cast<void*>(region.start),
|
| + reinterpret_cast<void*>(region.end));
|
| +
|
| + EXPECT_EQ(-1,
|
| + ::mprotect(reinterpret_cast<void*>(region.start),
|
| + region.end - region.start,
|
| + PROT_READ | PROT_WRITE))
|
| + << text;
|
| + EXPECT_EQ(EACCES, errno) << text;
|
| + }
|
| +}
|
| +
|
| +} // namespace content
|
| +
|
| +#endif // CONTENT_TEST_CONTENT_LINKER_UNITTEST_H
|
|
|