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

Add initial support for ARM MTE #311

Merged
merged 31 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
8b9e220
runtime: Move most of _IA2_INIT_RUNTIME to init.c
ayrtonm Mar 13, 2024
72e8f14
runtime: Add LIBIA2_AARCH64 flag for libia2
ayrtonm Mar 13, 2024
d1b8a51
runtime: Make exit arch-dependent
ayrtonm Mar 13, 2024
30cd581
runtime: Make libia2 main arch-dependent
ayrtonm Mar 13, 2024
fd1a42e
runtime: Make ia2_thread_begin arch-dependent
ayrtonm Mar 13, 2024
b262db3
runtime: Make memory tagging arch-dependent
ayrtonm Mar 13, 2024
05d6d04
runtime: Make scrub registers arch-dependent
ayrtonm Mar 13, 2024
008bab6
runtime: Make compartment init arch-dependent
ayrtonm Mar 13, 2024
057c1b2
runtime: Remove calls to pkey_alloc for aarch64
ayrtonm Mar 13, 2024
e6aa11a
tools: Add arch flag to rewriter
ayrtonm Mar 13, 2024
03d2ae4
tools: Use arch-dependent illegal instruction in rewriter
ayrtonm Mar 13, 2024
7277e17
tools: make rewriter call gate no-op transition on aarch64
ayrtonm Mar 13, 2024
429cea8
tools: Fix target passed to rewriter
ayrtonm Mar 14, 2024
8373dcf
tests: Add criterion-free test for aarch64
ayrtonm Mar 13, 2024
4d268a6
external/nginx: Use tools target in nginx build
ayrtonm Mar 14, 2024
74b999e
external/nginx: Set arch to x86-64 for nginx build
ayrtonm Mar 14, 2024
ff64490
external/nginx: Set arch for nginx call gate
ayrtonm Mar 14, 2024
d722ae7
docs: Update CMake target list
ayrtonm Mar 14, 2024
9f20a09
CI: Add basic CI for aarch64
ayrtonm Mar 13, 2024
d9357f4
CI: Fix qemu invocation for aarch64
ayrtonm Mar 14, 2024
04da869
cmake: Add aarch64 toolchain file
ayrtonm Mar 13, 2024
9bec906
cmake: Add support for building host tools when cross-compiling
ayrtonm Mar 14, 2024
dd3e078
cmake: Temporarily remove dependency on ubsan and partition-alloc on …
ayrtonm Mar 14, 2024
85f21c5
cmake: Disable tracer for aarch64
ayrtonm Mar 14, 2024
148b251
cmake: Add workaround for aarch64 ld.so lookup error
ayrtonm Mar 14, 2024
5c59a6e
cmake: Add arch flag to rewriter invocation
ayrtonm Mar 14, 2024
a8c6669
cmake: Add missing include for tests directory
ayrtonm Mar 14, 2024
2fb59b8
runtime/libia2: Fix CMake dependency on pad-tls
ayrtonm Mar 14, 2024
80b73f8
CI: Fix target name for WIP aarch64 test
ayrtonm Mar 14, 2024
7035d9b
runtime/libia2: Fix tag used in ia2_mprotect_with_tag
ayrtonm Mar 26, 2024
203f278
cmake: Fix dependency between rewrite targets and rewriter
ayrtonm Mar 26, 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
31 changes: 31 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,34 @@ jobs:
make
popd
popd
aarch64-wip-test:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Test ARM build
run: |
sudo apt-get update
sudo apt-get install -y \
gcc-aarch64-linux-gnu \
g++-aarch64-linux-gnu \
clang-15 pkg-config \
cmake ninja-build \
llvm-15-dev libclang-15-dev \
zlib1g-dev \
qemu-user-static
LLVM_DIR=`llvm-config-15 --cmakedir`
Clang_DIR=`realpath $LLVM_DIR/../clang`
mkdir build
pushd build
cmake .. \
-DCMAKE_TOOLCHAIN_FILE=../cmake/aarch64-toolchain.cmake \
-DClang_DIR=$Clang_DIR \
-DCLANG_EXE=`which clang-15` \
-DLLVM_DIR=$LLVM_DIR \
-G Ninja
ninja -v minimal_no_criterion
qemu-aarch64-static -L /usr/aarch64-linux-gnu/ \
tests/minimal_no_criterion/minimal_no_criterion
popd

14 changes: 12 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
cmake_minimum_required(VERSION 3.13)
project(IA2Phase2)
include(ExternalProject)

find_package(PkgConfig REQUIRED)

Expand All @@ -10,6 +11,15 @@ set(EXTERNAL_DIR ${PROJECT_SOURCE_DIR}/external)
# runtime needs to be first so it defines libia2_BINARY_DIR
add_subdirectory(runtime)

add_subdirectory(examples)
if (NOT LIBIA2_AARCH64)
add_subdirectory(examples)
endif()

add_subdirectory(tests)
add_subdirectory(tools)
ExternalProject_Add(tools
SOURCE_DIR ${CMAKE_SOURCE_DIR}/tools
BINARY_DIR ${CMAKE_BINARY_DIR}/tools
CMAKE_ARGS
-DClang_DIR=${Clang_DIR}
-DLLVM_DIR=${LLVM_DIR}
INSTALL_COMMAND "")
14 changes: 14 additions & 0 deletions cmake/aarch64-toolchain.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
set(LIBIA2_AARCH64 TRUE)

set(CMAKE_SYSTEM_NAME Linux)

set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)

set(CMAKE_C_HOST_COMPILER gcc)
set(CMAKE_CXX_HOST_COMPILER g++)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
4 changes: 4 additions & 0 deletions cmake/define-test.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ function(define_test)
set(DEFINE_TEST_LIBS ${TEST_NAME}_lib)
endif()

if (LIBIA2_AARCH64)
set(DEFINE_TEST_WITHOUT_SANDBOX TRUE)
endif()

# if(DEFINED DEFINE_TEST_INCLUDE_DIR)
# set(RELATIVE_INCLUDE_DIR ${DEFINE_TEST_INCLUDE_DIR})
# else()
Expand Down
44 changes: 37 additions & 7 deletions cmake/ia2.cmake
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
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
#
# add_ia2_compartment(<name> <EXECUTABLE|LIBRARY> PKEY <n> SOURCES <src>...
Expand Down Expand Up @@ -53,11 +60,11 @@ function(add_ia2_compartment NAME TYPE)

if (ARG_ENABLE_UBSAN)
# UBSAN requires passing this as both a compiler and linker flag
target_compile_options(${NAME} PRIVATE "-fsanitize=undefined")
target_link_options(${NAME} PRIVATE "-fsanitize=undefined")
target_compile_options(${NAME} PRIVATE ${UBSAN_FLAG})
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 Expand Up @@ -94,8 +101,8 @@ function(pad_tls_library INPUT OUTPUT)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lib${OUTPUT}.so
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${INPUT}> ${CMAKE_CURRENT_BINARY_DIR}/lib${OUTPUT}.so
COMMAND pad-tls --allow-no-tls ${CMAKE_CURRENT_BINARY_DIR}/lib${OUTPUT}.so
DEPENDS pad-tls $<TARGET_FILE:${INPUT}>
COMMAND ${CMAKE_BINARY_DIR}/tools/pad-tls/pad-tls --allow-no-tls ${CMAKE_CURRENT_BINARY_DIR}/lib${OUTPUT}.so
DEPENDS tools $<TARGET_FILE:${INPUT}>
COMMENT "Padding TLS segment of wrapped library"
)
add_custom_target(${OUTPUT}-padding DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/lib${OUTPUT}.so")
Expand Down Expand Up @@ -165,6 +172,15 @@ execute_process(COMMAND ${CLANG_EXE} -print-file-name=include-fixed
OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "Found Clang fixed headers: ${CLANG_HEADERS_INCLUDE_FIXED}")

file(GLOB REWRITER_SRCS ${CMAKE_SOURCE_DIR}/tools/rewriter/*.cpp)
# This cannot be in the tools directory CMakeLists.txt because the target is for
# the top-level CMake project
add_custom_target(rewriter
COMMAND ${CMAKE_COMMAND} --build . -t ia2-rewriter
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tools
# tools dependency is for the CMake config step
DEPENDS tools ${REWRITER_SRCS})

# Create call gates for a target
#
# Creates call gates for executable target <name> and all of its
Expand Down Expand Up @@ -234,6 +250,12 @@ function(add_ia2_call_gates NAME)
endif()
endif()

# FIXME: This shouldn't be necessary but it seems aarch64-gcc < v13 might
# default to --as-needed so this is needed to fix some runtime ld.so lookup
# error
if (LIBIA2_AARCH64)
target_link_options(${target} PRIVATE "-Wl,--no-as-needed")
endif()
target_link_libraries(${target} PRIVATE ${CALL_GATE_TARGET})

if("${target_pkey}" GREATER "0")
Expand All @@ -244,20 +266,28 @@ function(add_ia2_call_gates NAME)
endif()
endforeach()

if (LIBIA2_AARCH64)
set(ARCH_FLAG "--arch=aarch64")
endif()
add_custom_command(
OUTPUT ${CALL_GATE_SRC} ${CALL_GATE_HDR} ${LD_ARGS_FILES} ${REWRITTEN_SOURCES}
COMMAND ia2-rewriter
COMMAND ${CMAKE_BINARY_DIR}/tools/rewriter/ia2-rewriter
--output-prefix=${REWRITER_OUTPUT_PREFIX}
--root-directory=${CMAKE_CURRENT_SOURCE_DIR}
--output-directory=${CMAKE_CURRENT_BINARY_DIR}
${ARCH_FLAG}
# Set the build path so the rewriter can find the compile_commands JSON
-p=${CMAKE_BINARY_DIR}
--extra-arg=-isystem "--extra-arg=${CLANG_HEADERS_INCLUDE}"
--extra-arg=-isystem "--extra-arg=${CLANG_HEADERS_INCLUDE_FIXED}"
${ARG_EXTRA_REWRITER_ARGS}
${SOURCES}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
DEPENDS ia2-rewriter ${SOURCES}
# dependencies on custom targets (i.e. the rewriter) do not re-run this
# command so we need to add a dependency on the rewriter's sources. We still
# need the dependency on the custom rewriter target to make sure it gets
# built the first time.
DEPENDS ${SOURCES} ${REWRITER_SRCS} rewriter
VERBATIM
)

Expand Down
3 changes: 1 addition & 2 deletions docs/build_instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ cmake .. \
## CMake targets

- `check` - builds and runs the test suite. Pass `-v` to ninja to see build commands and output from failing tests.
- `ia2-rewriter` - builds the source-code rewriter. Depends on libclang-dev and llvm-dev.
- `pad-tls` - builds a script for padding ELF headers for TLS segments. Only required for compartmentalized DSOs that use thread-local storage.
- `tools` - builds the source-code rewriter and pad-tls script. The former depends on libclang-dev and llvm-dev. The latter is only required for compartmentalized DSOs that use thread-local storage.
- `libia2` - builds the runtime as a static library. This does not include call gate transitions as those are program-specific and generated by the rewriter.
- `partition-alloc-padding` - builds the compartment-aware shim for Chromium's PartitionAlloc allocator.
- `ia2-sandbox` - builds the syscall tracer.
Expand Down
4 changes: 3 additions & 1 deletion external/nginx/auto/make
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ IA2_CFLAGS = \\
-fPIC \\
-DPKEY=1 \\
-DIA2_ENABLE=\$(IA2_ENABLE) \\
-DLIBIA2_X86_64=1 \\
-DLIBIA2_DEBUG=1 \\
-I \$(C_SYSTEM_INCLUDE) \\
-I \$(C_SYSTEM_INCLUDE_FIXED) \\
Expand Down Expand Up @@ -91,6 +92,7 @@ IA2_MODULE_CFLAGS = \\
-fPIC \\
-DPKEY=2 \\
-DIA2_ENABLE=\$(IA2_ENABLE) \\
-DLIBIA2_X86_64=1 \\
-DLIBIA2_DEBUG=1 \\
-I \$(C_SYSTEM_INCLUDE) \\
-I \$(C_SYSTEM_INCLUDE_FIXED) \\
Expand Down Expand Up @@ -314,7 +316,7 @@ binary: $NGX_OBJS${ngx_dirsep}nginx$ngx_binext

\$(IA2_CALLGATES_TARGET):
\$(CC) -shared -fPIC -Wl,-z,now $NGX_OBJS/../wrapper.c \
-I \$(LIBIA2_DIR)/include -o \$(IA2_CALLGATES_TARGET)
-I \$(LIBIA2_DIR)/include -DLIBIA2_X86_64=1 -o \$(IA2_CALLGATES_TARGET)

$NGX_OBJS/ngx_rtmp_module_tls_padded.so: $NGX_OBJS/ngx_rtmp_module.so
cp $NGX_OBJS/ngx_rtmp_module.so $NGX_OBJS/ngx_rtmp_module_tls_padded.so
Expand Down
2 changes: 1 addition & 1 deletion external/nginx/reconfigure
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fi
mkdir -p $IA2_BUILD_DIR
pushd $IA2_BUILD_DIR
cmake -GNinja $REPO_ROOT ${IA2_CMAKE_FLAGS:-}
ninja ia2-rewriter libia2 pad-tls ${PA_LIBRARY}
ninja tools libia2 ${PA_LIBRARY}
popd

mkdir -p $NGINX_BUILD_DIR
Expand Down
13 changes: 10 additions & 3 deletions runtime/libia2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
cmake_minimum_required(VERSION 3.12)
project(libia2)

add_library(libia2 ia2.c threads.c main.c exit.c)
add_library(libia2 ia2.c init.c threads.c main.c exit.c)
target_compile_options(libia2 PRIVATE "-fPIC")

if (LIBIA2_AARCH64)
target_compile_definitions(libia2 PUBLIC LIBIA2_AARCH64=1)
target_compile_options(libia2 PUBLIC "-march=armv8.5-a+memtag" "-ffixed-x18")
else()
target_compile_definitions(libia2 PUBLIC LIBIA2_X86_64=1)
endif()

if(LIBIA2_DEBUG)
target_compile_definitions(libia2 PUBLIC LIBIA2_DEBUG=1)
endif()
Expand Down Expand Up @@ -53,8 +60,8 @@ endif()
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/libc.so.6
COMMAND ${CMAKE_COMMAND} -E copy ${LIBC_PATH} ${CMAKE_CURRENT_BINARY_DIR}/libc.so.6
COMMAND pad-tls --allow-no-tls ${CMAKE_CURRENT_BINARY_DIR}/libc.so.6
DEPENDS pad-tls
COMMAND ${CMAKE_BINARY_DIR}/tools/pad-tls/pad-tls --allow-no-tls ${CMAKE_CURRENT_BINARY_DIR}/libc.so.6
DEPENDS tools
COMMENT "Padding TLS segment of libc"
)

Expand Down
5 changes: 5 additions & 0 deletions runtime/libia2/exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ static void call_libc_exit(int status) {

__attribute__((naked)) void exit(int status) {
__asm__(
#if LIBIA2_X86_64
/* clang-format off */
"pushq %%rbp\n"
"movq %%rsp, %%rbp\n"
Expand All @@ -29,5 +30,9 @@ __attribute__((naked)) void exit(int status) {
// Call the real exit function.
"call call_libc_exit\n"
/* clang-format on */
#elif LIBIA2_AARCH64
#warning "libia2 does not properly wrap `exit` yet"
"udf #0\n"
#endif
::);
}
Loading
Loading