Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port runtime to ARM #362

Merged
merged 20 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
2152f51
partition-alloc: cmake: propagate LIBIA2_AARCH64 as ARCH_CPU_ARM64
fw-immunant Jun 10, 2024
7c27864
partition-alloc: hard-code 4K page size on ARM
fw-immunant Jun 10, 2024
8426a8f
partition-alloc: forbid compiling pkey thread isolation on ARM
fw-immunant Jun 10, 2024
7b14908
partition-alloc: add MTE codepaths (but do not yet tag memory)
fw-immunant Jul 22, 2024
71e6b12
partition-alloc: use PROT_MTE on mmap and mprotect
fw-immunant Jul 23, 2024
d19b90c
partition-alloc: only allow building MTE isolation on ARM
fw-immunant Jul 26, 2024
f34bf4a
runtime/partition-alloc: implement get_pkey for aarch64
fw-immunant Jul 24, 2024
80f9f9c
runtime/partition-alloc: cmake: link libstdc++ explicitly
fw-immunant Jul 23, 2024
28a7b65
runtime: do not try to build PKRU tools on arm
fw-immunant Jun 10, 2024
f1b4782
runtime/tracer: port syscall interpretation to arm64
fw-immunant Jun 10, 2024
f015b25
runtime/tracer: port memory map tracking to arm64
fw-immunant Jun 10, 2024
cdea690
runtime/seccomp-filter: avoid mentioning obsolete syscalls on arm64
fw-immunant Jun 10, 2024
544edcb
runtime/memory-map: cmake: adapt cargo integration for cross compilation
fw-immunant Jun 10, 2024
39fa729
runtime/memory-map: update cargo.toml syntax
fw-immunant Jun 10, 2024
5fb0ecc
runtime/memory-map: silence rustc check-cfg warnings
fw-immunant Jul 18, 2024
71d3dae
cmake: add library path needed for libstdc++ to qemu invocation
fw-immunant Jul 24, 2024
e8063d9
cmake: put glibc sysroot in LD_LIBRARY_PATH
fw-immunant Jul 26, 2024
cdcfe77
cmake: also use partition-alloc on arm
fw-immunant Jul 22, 2024
7e1cf19
cmake: tests: always use partition-alloc
fw-immunant Jul 23, 2024
04d3006
cmake: enable heap tests on ARM64
fw-immunant Jul 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmake/define-test.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ function(define_test)
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR}
"-one-insn-per-tb"
"-L" "${CMAKE_BINARY_DIR}/external/glibc/sysroot/usr/"
"-E" "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/external/glibc/sysroot/usr/lib:/usr/aarch64-linux-gnu/lib:/usr/aarch64-linux-gnu/lib64"
${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
elseif (DEFINE_TEST_WITHOUT_SANDBOX OR NOT ${IA2_TRACER})
Expand Down
4 changes: 1 addition & 3 deletions cmake/ia2.cmake
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
if(LIBIA2_AARCH64)
set(UBSAN_FLAG "")
set(PARTITION_ALLOC "")
else()
set(UBSAN_FLAG "-fsanitize=undefined")
set(PARTITION_ALLOC "partition-alloc")
endif()
# Creates a compartmentalized IA2 target
#
Expand Down Expand Up @@ -71,7 +69,7 @@ function(add_ia2_compartment NAME TYPE)
target_link_options(${NAME} PRIVATE ${UBSAN_FLAG})
endif()

target_link_libraries(${NAME} PRIVATE dl libia2 ${PARTITION_ALLOC})
target_link_libraries(${NAME} PRIVATE dl libia2 partition-alloc)
target_link_options(${NAME} PRIVATE "-Wl,--export-dynamic")

target_link_libraries(${NAME} PRIVATE ${ARG_LIBRARIES})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@ PageAllocationGranularityShift() {
#endif
}

PA_ALWAYS_INLINE constexpr size_t SystemPageSizeMax() {
#if BUILDFLAG(IS_LINUX) && defined(ARCH_CPU_ARM64)
return 4*1024;
#else
return 1 << PageAllocationGranularityShift();
#endif
}

PA_ALWAYS_INLINE PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR size_t
PageAllocationGranularity() {
#if BUILDFLAG(IS_APPLE) && defined(ARCH_CPU_64_BITS)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ uintptr_t SystemAllocPagesInternal(uintptr_t hint,
}
#endif

#if BUILDFLAG(ENABLE_MTE_ISOLATION)
access_flag |= PROT_MTE;
#endif

void* ret = mmap(reinterpret_cast<void*>(hint), length, access_flag,
map_flags, fd, 0);
if (ret == MAP_FAILED) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionAddressSpace {
#endif
};
#if BUILDFLAG(ENABLE_THREAD_ISOLATION)
static_assert(sizeof(PoolSetup) % SystemPageSize() == 0,
static_assert(sizeof(PoolSetup) % SystemPageSizeMax() == 0,
"PoolSetup has to fill a page(s)");
#else
static_assert(sizeof(PoolSetup) % kPartitionCachelineSize == 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,13 @@
#define BUILDFLAG_INTERNAL_USE_FREELIST_POOL_OFFSETS() (0)
#define BUILDFLAG_INTERNAL_USE_STARSCAN() (1)
#define BUILDFLAG_INTERNAL_PCSCAN_STACK_SUPPORTED() (0)
#ifdef ARCH_CPU_ARM64
#define BUILDFLAG_INTERNAL_ENABLE_PKEYS() (0)
#define BUILDFLAG_INTERNAL_ENABLE_MTE_ISOLATION() (1)
#else
#define BUILDFLAG_INTERNAL_ENABLE_PKEYS() (1)
#define BUILDFLAG_INTERNAL_ENABLE_MTE_ISOLATION() (0)
#endif
#define BUILDFLAG_INTERNAL_ENABLE_THREAD_ISOLATION() (1)
#define BUILDFLAG_INTERNAL_WRAP_SHIM() (1)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

#include "base/allocator/partition_allocator/page_allocator_constants.h"

#define PA_THREAD_ISOLATED_ALIGN_SZ partition_alloc::internal::SystemPageSize()
#define PA_THREAD_ISOLATED_ALIGN_SZ partition_alloc::internal::SystemPageSizeMax()
#define PA_THREAD_ISOLATED_ALIGN_OFFSET_MASK (PA_THREAD_ISOLATED_ALIGN_SZ - 1)
#define PA_THREAD_ISOLATED_ALIGN_BASE_MASK \
(~PA_THREAD_ISOLATED_ALIGN_OFFSET_MASK)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/allocator/partition_allocator/thread_isolation/mte.h"

#if BUILDFLAG(ENABLE_MTE_ISOLATION)

#include <errno.h>
#include <sys/auxv.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <unistd.h>

#include "base/allocator/partition_allocator/partition_alloc_base/cpu.h"
#include "base/allocator/partition_allocator/partition_alloc_check.h"
#include "base/allocator/partition_allocator/thread_isolation/thread_isolation.h"

#if !BUILDFLAG(IS_LINUX)
#error "This MTE code is currently only supported on Linux"
#endif

#ifndef ARCH_CPU_ARM64
#error "MTE is only available on the AArch64 architecture"
#endif

namespace partition_alloc::internal {

PA_COMPONENT_EXPORT(PARTITION_ALLOC)
bool CPUHasMteSupport() {
// Check for Armv8.5-A MTE support, exposed via HWCAP2
unsigned long hwcap2 = getauxval(AT_HWCAP2);
return hwcap2 & HWCAP2_MTE;
}

extern "C" int ia2_mprotect_with_tag(void *addr, size_t len, int prot, int tag);

PA_COMPONENT_EXPORT(PARTITION_ALLOC)
int MteMprotect(void* addr, size_t len, int prot, int tag) {
return ia2_mprotect_with_tag(addr, len, prot, tag);
}

PA_COMPONENT_EXPORT(PARTITION_ALLOC)
void TagMemoryWithMte(int tag, void *address, size_t size) {
PA_DCHECK((reinterpret_cast<uintptr_t>(address) &
PA_THREAD_ISOLATED_ALIGN_OFFSET_MASK) == 0);
PA_PCHECK(ia2_mprotect_with_tag(address, size, PROT_READ|PROT_WRITE, tag) == 0);
}

} // namespace partition_alloc::internal

#endif // BUILDFLAG(ENABLE_MTE_ISOLATION)
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_THREAD_ISOLATION_MTE_H_
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_THREAD_ISOLATION_MTE_H_

#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"

#if BUILDFLAG(ENABLE_MTE_ISOLATION)

#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
#include "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h"
#include "base/allocator/partition_allocator/thread_isolation/alignment.h"

#include <cstddef>
#include <cstdint>

namespace partition_alloc::internal {

constexpr int kDefaultPkey = 0;
constexpr int kInvalidPkey = -1;

// Check if the CPU supports pkeys.
bool CPUHasMteSupport();

int MteMprotect(void* addr, size_t len, int prot, int tag);

void TagMemoryWithMte(int tag, void* address, size_t size);

} // namespace partition_alloc::internal

#endif // BUILDFLAG(ENABLE_MTE_ISOLATION)

#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_THREAD_ISOLATION_MTE_H_
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
#error "This pkey code is currently only supported on Linux"
#endif

#ifdef ARCH_CPU_ARM64
#error "This pkey code is supported only on x86_64 architecture"
#endif

namespace partition_alloc::internal {

PA_COMPONENT_EXPORT(PARTITION_ALLOC)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
#include "base/allocator/partition_allocator/thread_isolation/pkey.h"
#endif

#if BUILDFLAG(ENABLE_MTE_ISOLATION)
#include "base/allocator/partition_allocator/thread_isolation/mte.h"
#endif

namespace partition_alloc::internal {

#if BUILDFLAG(PA_DCHECK_IS_ON)
Expand All @@ -30,6 +34,10 @@ void WriteProtectThreadIsolatedMemory(ThreadIsolationOption thread_isolation,
partition_alloc::internal::TagMemoryWithPkey(
thread_isolation.enabled ? thread_isolation.pkey : kDefaultPkey, address,
size);
#elif BUILDFLAG(ENABLE_MTE_ISOLATION)
partition_alloc::internal::TagMemoryWithMte(
thread_isolation.enabled ? thread_isolation.pkey : kDefaultPkey, address,
size);
#else
#error unexpected thread isolation mode
#endif
Expand All @@ -49,6 +57,10 @@ int MprotectWithThreadIsolation(void* addr,
ThreadIsolationOption thread_isolation) {
#if BUILDFLAG(ENABLE_PKEYS)
return PkeyMprotect(addr, len, prot, thread_isolation.pkey);
#elif BUILDFLAG(ENABLE_MTE_ISOLATION)
return MteMprotect(addr, len, prot, thread_isolation.pkey);
#else
#error unexpected thread isolation mode
#endif
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
#include "base/allocator/partition_allocator/thread_isolation/pkey.h"
#endif

#if BUILDFLAG(ENABLE_MTE_ISOLATION)
#include "base/allocator/partition_allocator/thread_isolation/mte.h"
#endif

#if !BUILDFLAG(HAS_64_BIT_POINTERS)
#error "thread isolation support requires 64 bit pointers"
#endif
Expand All @@ -33,23 +37,23 @@ struct ThreadIsolationOption {
constexpr ThreadIsolationOption() = default;
explicit ThreadIsolationOption(bool enabled) : enabled(enabled) {}

#if BUILDFLAG(ENABLE_PKEYS)
#if BUILDFLAG(ENABLE_PKEYS) || BUILDFLAG(ENABLE_MTE_ISOLATION)
explicit ThreadIsolationOption(int pkey, size_t compartment)
: pkey(pkey), compartment(compartment) {
enabled = pkey != internal::kInvalidPkey;
}
int pkey = -1;
Compartment compartment = 0;
#endif // BUILDFLAG(ENABLE_PKEYS)
#endif // BUILDFLAG(ENABLE_PKEYS) || BUILDFLAG(ENABLE_MTE_ISOLATION)

bool enabled = false;

bool operator==(const ThreadIsolationOption& other) const {
#if BUILDFLAG(ENABLE_PKEYS)
#if BUILDFLAG(ENABLE_PKEYS) || BUILDFLAG(ENABLE_MTE_ISOLATION)
if (pkey != other.pkey) {
return false;
}
#endif // BUILDFLAG(ENABLE_PKEYS)
#endif // BUILDFLAG(ENABLE_PKEYS) || BUILDFLAG(ENABLE_MTE_ISOLATION)
return enabled == other.enabled;
}
};
Expand All @@ -69,7 +73,12 @@ struct PA_THREAD_ISOLATED_ALIGN ThreadIsolationSettings {

using LiftThreadIsolationScope = DoNotLiftPkeyRestrictionsScope;

#elif BUILDFLAG(ENABLE_MTE_ISOLATION)

using LiftThreadIsolationScope = void*;

#endif // BUILDFLAG(ENABLE_PKEYS)

#endif // BUILDFLAG(PA_DCHECK_IS_ON)

void WriteProtectThreadIsolatedGlobals(
Expand Down
13 changes: 13 additions & 0 deletions runtime/partition-alloc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ set(PA_SRCS
partition_page.cc
partition_root.cc
partition_stats.cc
thread_isolation/mte.cc
thread_isolation/pkey.cc
thread_isolation/thread_isolation.cc
random.cc
Expand Down Expand Up @@ -73,6 +74,10 @@ add_library(partition-alloc_unpadded SHARED

pad_tls_library(partition-alloc_unpadded partition-alloc)

target_link_libraries(partition-alloc_unpadded PRIVATE
stdc++
)

target_include_directories(partition-alloc BEFORE
INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/include
Expand All @@ -84,6 +89,14 @@ target_include_directories(partition-alloc_unpadded BEFORE
PRIVATE
${EXTERNAL_DIR}/chromium/src)

# Propagage ARM64 define
if(LIBIA2_AARCH64)
target_compile_options(partition-alloc_unpadded
PRIVATE
"-DARCH_CPU_ARM64"
)
endif()

target_compile_options(partition-alloc_unpadded
PRIVATE
"-fPIC"
Expand Down
11 changes: 11 additions & 0 deletions runtime/partition-alloc/src/get_pkey.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// the allocator against libia2 itself. We want users with libia2 disabled to
// still be able to call `shared_malloc` etc.

#ifdef __x86_64__
__attribute__((__visibility__("hidden")))
uint32_t ia2_get_pkru() {
uint32_t pkru = 0;
Expand Down Expand Up @@ -75,3 +76,13 @@ size_t ia2_get_pkey() {
}
}
}
#endif

#ifdef __aarch64__
__attribute__((__visibility__("hidden")))
size_t ia2_get_pkey() {
size_t x18;
asm("mov %0, x18" : "=r"(x18));
return x18 >> 56;
}
#endif
17 changes: 13 additions & 4 deletions runtime/tracer/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
cmake_minimum_required(VERSION 3.12)
project(tracer)

if (LIBIA2_AARCH64)
set(CARGO_TARGET_FLAG "--target=aarch64-unknown-linux-gnu" "--config" "target.aarch64-unknown-linux-gnu.linker=\\\"aarch64-linux-gnu-gcc\\\"")
set(CARGO_ARCH_SUFFIX "aarch64-unknown-linux-gnu")
else()
set(CARGO_TARGET_FLAG "")
set(CARGO_ARCH_SUFFIX "")
endif()
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/release/libmemory_map.so
COMMAND CARGO_TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR} cargo build --manifest-path ${CMAKE_CURRENT_SOURCE_DIR}/memory-map/Cargo.toml --release
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CARGO_ARCH_SUFFIX}/release/libmemory_map.so
COMMAND CARGO_TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR} cargo build ${CARGO_TARGET_FLAG} --manifest-path ${CMAKE_CURRENT_SOURCE_DIR}/memory-map/Cargo.toml --release
DEPENDS memory-map/Cargo.toml memory-map/src/lib.rs
)

add_library(memory-map STATIC IMPORTED)
set_property(TARGET memory-map PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/release/libmemory_map.so)
add_custom_target(memory-map-tgt DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/release/libmemory_map.so)
set_property(TARGET memory-map PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${CARGO_ARCH_SUFFIX}/release/libmemory_map.so)
add_custom_target(memory-map-tgt DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CARGO_ARCH_SUFFIX}/release/libmemory_map.so)
add_dependencies(memory-map memory-map-tgt)

if(LIBIA2_X86_64)
add_executable(read-pkru
read_pkru_demo.c
get_inferior_pkru.c
)
endif()

add_executable(track-memory-map
track_memory_map_demo.c
Expand Down
2 changes: 2 additions & 0 deletions runtime/tracer/get_inferior_pkru.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#ifdef __x86_64__
#include <cpuid.h>
#include <linux/elf.h>
#include <stdio.h>
Expand Down Expand Up @@ -64,3 +65,4 @@ bool get_inferior_pkru(pid_t pid, uint32_t *pkru_out) {
memcpy(pkru_out, &xstateregs[xstate_pkru_offset], sizeof(*pkru_out));
return true;
}
#endif
7 changes: 5 additions & 2 deletions runtime/tracer/memory-map/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ name = "memory-map"
version = "0.1.0"
edition = "2021"
[lib]
crate_type = ["cdylib"]
crate-type = ["cdylib"]

[dependencies]
libc_alloc = "1.0.5"
nonoverlapping_interval_tree = { version = "0.1.5", default_features = false }
nonoverlapping_interval_tree = { version = "0.1.5", default-features = false }

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(debug)', 'cfg(list_regions)'] }

[profile.dev]
panic = "abort"
Expand Down
Loading