Skip to content

Commit 447585a

Browse files
committed
[𝘀𝗽𝗿] initial version
Created using spr 1.3.6-beta.1
2 parents 2b8cc65 + 3d91c48 commit 447585a

File tree

26 files changed

+691
-412
lines changed

26 files changed

+691
-412
lines changed

compiler-rt/cmake/Modules/AddCompilerRT.cmake

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ function(add_compiler_rt_runtime name type)
172172
cmake_parse_arguments(LIB
173173
""
174174
"PARENT_TARGET"
175-
"OS;ARCHS;SOURCES;CFLAGS;LINK_FLAGS;DEFS;DEPS;LINK_LIBS;OBJECT_LIBS;ADDITIONAL_HEADERS;EXTENSIONS"
175+
"OS;ARCHS;SOURCES;CFLAGS;LINK_FLAGS;DEFS;DEPS;LINK_LIBS;OBJECT_LIBS;ADDITIONAL_HEADERS;EXTENSIONS;C_STANDARD;CXX_STANDARD"
176176
${ARGN})
177177
set(libnames)
178178
# Until we support this some other way, build compiler-rt runtime without LTO
@@ -360,6 +360,12 @@ function(add_compiler_rt_runtime name type)
360360
set_target_link_flags(${libname} ${extra_link_flags_${libname}})
361361
set_property(TARGET ${libname} APPEND PROPERTY
362362
COMPILE_DEFINITIONS ${LIB_DEFS})
363+
if(LIB_C_STANDARD)
364+
set_property(TARGET ${libname} PROPERTY C_STANDARD ${LIB_C_STANDARD})
365+
endif()
366+
if(LIB_CXX_STANDARD)
367+
set_property(TARGET ${libname} PROPERTY CXX_STANDARD ${LIB_CXX_STANDARD})
368+
endif()
363369
set_target_output_directories(${libname} ${output_dir_${libname}})
364370
install(TARGETS ${libname}
365371
ARCHIVE DESTINATION ${install_dir_${libname}}

compiler-rt/cmake/builtin-config-ix.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ builtin_check_c_compiler_flag(-fconvergent-functions COMPILER_RT_HAS_FCONVERGENT
2525
builtin_check_c_compiler_flag(-Wbuiltin-declaration-mismatch COMPILER_RT_HAS_WBUILTIN_DECLARATION_MISMATCH_FLAG)
2626
builtin_check_c_compiler_flag(/Zl COMPILER_RT_HAS_ZL_FLAG)
2727
builtin_check_c_compiler_flag(-fcf-protection=full COMPILER_RT_HAS_FCF_PROTECTION_FLAG)
28+
builtin_check_c_compiler_flag(-nostdinc++ COMPILER_RT_HAS_NOSTDINCXX_FLAG)
2829

2930
builtin_check_c_compiler_source(COMPILER_RT_HAS_ATOMIC_KEYWORD
3031
"

compiler-rt/lib/builtins/CMakeLists.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
66
cmake_minimum_required(VERSION 3.20.0)
77

88
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
9-
project(CompilerRTBuiltins C ASM)
9+
project(CompilerRTBuiltins C CXX ASM)
1010
set(COMPILER_RT_STANDALONE_BUILD TRUE)
1111
set(COMPILER_RT_BUILTINS_STANDALONE_BUILD TRUE)
1212

@@ -64,6 +64,8 @@ include(CMakePushCheckState)
6464
option(COMPILER_RT_BUILTINS_HIDE_SYMBOLS
6565
"Do not export any symbols from the static library." ON)
6666

67+
include_directories(../../../third-party/siphash/include)
68+
6769
# TODO: Need to add a mechanism for logging errors when builtin source files are
6870
# added to a sub-directory and not this CMakeLists file.
6971
set(GENERIC_SOURCES
@@ -570,6 +572,7 @@ set(aarch64_SOURCES
570572
${GENERIC_TF_SOURCES}
571573
${GENERIC_SOURCES}
572574
cpu_model/aarch64.c
575+
aarch64/emupac.cpp
573576
aarch64/fp_mode.c
574577
)
575578

@@ -802,7 +805,7 @@ else ()
802805
append_list_if(COMPILER_RT_ENABLE_CET -fcf-protection=full BUILTIN_CFLAGS)
803806
endif()
804807

805-
append_list_if(COMPILER_RT_HAS_STD_C11_FLAG -std=c11 BUILTIN_CFLAGS)
808+
append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ BUILTIN_CFLAGS)
806809
append_list_if(COMPILER_RT_HAS_WBUILTIN_DECLARATION_MISMATCH_FLAG -Werror=builtin-declaration-mismatch BUILTIN_CFLAGS)
807810

808811
# Don't embed directives for picking any specific CRT
@@ -913,6 +916,8 @@ else ()
913916
SOURCES ${${arch}_SOURCES}
914917
DEFS ${BUILTIN_DEFS}
915918
CFLAGS ${BUILTIN_CFLAGS_${arch}}
919+
C_STANDARD 11
920+
CXX_STANDARD 17
916921
PARENT_TARGET builtins)
917922
cmake_pop_check_state()
918923
endif ()
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
//===--- emupac.cpp - Emulated PAC implementation -------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file implements Emulated PAC using SipHash_1_3 as the IMPDEF hashing
10+
// scheme.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include <stdint.h>
15+
16+
#include "siphash/SipHash.h"
17+
18+
// EmuPAC implements runtime emulation of PAC instructions. If the current
19+
// CPU supports PAC, EmuPAC uses real PAC instructions. Otherwise, it uses the
20+
// emulation, which is effectively an implementation of PAC with an IMPDEF
21+
// hashing scheme based on SipHash_1_3.
22+
//
23+
// The purpose of the emulation is to allow programs to be built to be portable
24+
// to machines without PAC support, with some performance loss and increased
25+
// probability of false positives (due to not being able to portably determine
26+
// the VA size), while being functionally almost equivalent to running on a
27+
// machine with PAC support. One example of a use case is if PAC is used in
28+
// production as a security mitigation, but the testing environment is
29+
// heterogeneous (i.e. some machines lack PAC support). In this case we would
30+
// like the testing machines to be able to detect issues resulting
31+
// from the use of PAC instructions that would affect production by running
32+
// tests. This can be achieved by building test binaries with EmuPAC and
33+
// production binaries with real PAC.
34+
//
35+
// The emulation assumes that the VA size is at most 48 bits. The architecture
36+
// as of ARMv8.2, which was the last architecture version in which PAC was not
37+
// mandatory, permitted VA size up to 52 bits via ARMv8.2-LVA, but we are
38+
// unaware of an ARMv8.2 CPU that implemented ARMv8.2-LVA.
39+
40+
const uint64_t kMaxVASize = 48;
41+
const uint64_t kPACMask = ((1ULL << 55) - 1) & ~((1ULL << kMaxVASize) - 1);
42+
const uint64_t kTTBR1Mask = 1ULL << 55;
43+
44+
// Determine whether PAC is supported without accessing memory. This utilizes
45+
// the XPACLRI instruction which will copy bit 55 of x30 into at least bit 54 if
46+
// PAC is supported and acts as a NOP if PAC is not supported.
47+
static bool pac_supported() {
48+
register uintptr_t x30 __asm__("x30") = 1ULL << 55;
49+
__asm__ __volatile__("xpaclri" : "+r"(x30));
50+
return x30 & (1ULL << 54);
51+
}
52+
53+
// This asm snippet is used to force the creation of a frame record when
54+
// calling the EmuPAC functions. This is important because the EmuPAC functions
55+
// may crash if an auth failure is detected and may be unwound past using a
56+
// frame pointer based unwinder.
57+
#ifdef __GCC_HAVE_DWARF2_CFI_ASM
58+
#define CFI_INST(inst) inst
59+
#else
60+
#define CFI_INST(inst)
61+
#endif
62+
63+
// clang-format off
64+
#define FRAME_POINTER_WRAP(sym) \
65+
"stp x29, x30, [sp, #-16]!\n" \
66+
CFI_INST(".cfi_def_cfa_offset 16\n") \
67+
"mov x29, sp\n" \
68+
CFI_INST(".cfi_def_cfa w29, 16\n") \
69+
CFI_INST(".cfi_offset w30, -8\n") \
70+
CFI_INST(".cfi_offset w29, -16\n") \
71+
"bl " #sym "\n" \
72+
CFI_INST(".cfi_def_cfa wsp, 16\n") \
73+
"ldp x29, x30, [sp], #16\n" \
74+
CFI_INST(".cfi_def_cfa_offset 0\n") \
75+
CFI_INST(".cfi_restore w30\n") \
76+
CFI_INST(".cfi_restore w29\n") \
77+
"ret"
78+
// clang-format on
79+
80+
static const uint8_t K[16] = {0xb5, 0xd4, 0xc9, 0xeb, 0x79, 0x10, 0x4a, 0x79,
81+
0x6f, 0xec, 0x8b, 0x1b, 0x42, 0x87, 0x81, 0xd4};
82+
83+
__attribute__((flatten)) extern "C" uint64_t
84+
__emupac_pacda_impl(uint64_t ptr, uint64_t disc) {
85+
if (pac_supported()) {
86+
__asm__ __volatile__(".arch_extension pauth\npacda %0, %1"
87+
: "+r"(ptr)
88+
: "r"(disc));
89+
return ptr;
90+
}
91+
if (ptr & kTTBR1Mask) {
92+
if ((ptr & kPACMask) != kPACMask) {
93+
return ptr | kPACMask;
94+
}
95+
} else {
96+
if (ptr & kPACMask) {
97+
return ptr & ~kPACMask;
98+
}
99+
}
100+
uint64_t hash;
101+
siphash<1, 3>(reinterpret_cast<uint8_t *>(&ptr), 8, K,
102+
*reinterpret_cast<uint8_t(*)[8]>(&hash));
103+
return (ptr & ~kPACMask) | (hash & kPACMask);
104+
}
105+
106+
extern "C" __attribute__((naked)) uint64_t __emupac_pacda(uint64_t ptr,
107+
uint64_t disc) {
108+
__asm__(FRAME_POINTER_WRAP(__emupac_pacda_impl));
109+
}
110+
111+
__attribute__((flatten)) extern "C" uint64_t
112+
__emupac_autda_impl(uint64_t ptr, uint64_t disc) {
113+
if (pac_supported()) {
114+
__asm__ __volatile__(".arch_extension pauth\nautda %0, %1"
115+
: "+r"(ptr)
116+
: "r"(disc));
117+
return ptr;
118+
}
119+
uint64_t ptr_without_pac =
120+
(ptr & kTTBR1Mask) ? (ptr | kPACMask) : (ptr & ~kPACMask);
121+
uint64_t hash;
122+
siphash<1, 3>(reinterpret_cast<uint8_t *>(&ptr_without_pac), 8, K,
123+
*reinterpret_cast<uint8_t(*)[8]>(&hash));
124+
if (((ptr & ~kPACMask) | (hash & kPACMask)) != ptr) {
125+
__builtin_trap();
126+
}
127+
return ptr_without_pac;
128+
}
129+
130+
extern "C" __attribute__((naked)) uint64_t __emupac_autda(uint64_t ptr,
131+
uint64_t disc) {
132+
__asm__(FRAME_POINTER_WRAP(__emupac_autda_impl));
133+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// REQUIRES: librt_has_emupac
2+
// RUN: %clang_builtins %s %librt -o %t
3+
// RUN: %run %t 1
4+
// RUN: %run %t 2
5+
// RUN: %expect_crash %run %t 3
6+
// RUN: %expect_crash %run %t 4
7+
8+
#include <stdint.h>
9+
#include <stdio.h>
10+
#include <stdlib.h>
11+
12+
uint64_t __emupac_pacda(uint64_t ptr, uint64_t disc);
13+
uint64_t __emupac_autda(uint64_t ptr, uint64_t disc);
14+
15+
int main(int argc, char **argv) {
16+
char stack_object1;
17+
uint64_t ptr1 = (uint64_t)stack_object1;
18+
19+
char stack_object2;
20+
uint64_t ptr2 = (uint64_t)stack_object2;
21+
22+
switch (atoi(argv[1])) {
23+
case 1: {
24+
// Normal case: test that a pointer authenticated with the same
25+
// discriminator is equal to the original pointer.
26+
uint64_t signed_ptr = __emupac_pacda(ptr1, ptr2);
27+
uint64_t authed_ptr = __emupac_autda(signed_ptr, ptr2);
28+
if (authed_ptr != ptr1) {
29+
printf("0x%lx != 0x%lx\n", authed_ptr, ptr1);
30+
return 1;
31+
}
32+
break;
33+
}
34+
case 2: {
35+
// Test that negative addresses (addressses controlled by TTBR1,
36+
// conventionally kernel addresses) can be signed and authenticated.
37+
uint64_t unsigned_ptr = -1ULL;
38+
uint64_t signed_ptr = __emupac_pacda(unsigned_ptr, ptr2);
39+
uint64_t authed_ptr = __emupac_autda(signed_ptr, ptr2);
40+
if (authed_ptr != unsigned_ptr) {
41+
printf("0x%lx != 0x%lx\n", authed_ptr, unsigned_ptr);
42+
return 1;
43+
}
44+
break;
45+
}
46+
case 3: {
47+
// Test that a corrupted signature crashes the program.
48+
uint64_t signed_ptr = __emupac_pacda(ptr1, ptr2);
49+
__emupac_autda(signed_ptr + (1ULL << 48), ptr2);
50+
break;
51+
}
52+
case 4: {
53+
// Test that signing a pointer with signature bits already set produces a pointer
54+
// that would fail auth.
55+
uint64_t signed_ptr = __emupac_pacda(ptr1 + (1ULL << 48), ptr2);
56+
__emupac_autda(signed_ptr, ptr2);
57+
break;
58+
}
59+
}
60+
61+
return 0;
62+
}

libcxx/test/libcxx/gdb/gdb_pretty_printer_test.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
# we exit.
3131
has_run_tests = False
3232

33-
has_execute_mi = tuple(map(int, gdb.VERSION.split("."))) >= (14, 2)
33+
has_execute_mi = getattr(gdb, "execute_mi", None) is not None
34+
3435

3536
class CheckResult(gdb.Command):
3637
def __init__(self):

lld/ELF/Relocations.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -847,9 +847,8 @@ static void addRelativeReloc(Ctx &ctx, InputSectionBase &isec,
847847
Partition &part = isec.getPartition(ctx);
848848

849849
if (sym.isTagged()) {
850-
std::lock_guard<std::mutex> lock(ctx.relocMutex);
851-
part.relaDyn->addRelativeReloc(ctx.target->relativeRel, isec, offsetInSec,
852-
sym, addend, type, expr);
850+
part.relaDyn->addRelativeReloc<shard>(ctx.target->relativeRel, isec,
851+
offsetInSec, sym, addend, type, expr);
853852
// With MTE globals, we always want to derive the address tag by `ldg`-ing
854853
// the symbol. When we have a RELATIVE relocation though, we no longer have
855854
// a reference to the symbol. Because of this, when we have an addend that

llvm/lib/Support/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,3 +369,8 @@ if(LLVM_WITH_Z3)
369369
${Z3_INCLUDE_DIR}
370370
)
371371
endif()
372+
373+
target_include_directories(LLVMSupport SYSTEM
374+
PRIVATE
375+
${LLVM_THIRD_PARTY_DIR}/siphash/include
376+
)

0 commit comments

Comments
 (0)