Skip to content

Commit

Permalink
[compiler-rt][hwasan] Support for new Intel LAM API
Browse files Browse the repository at this point in the history
New version of Intel LAM patches
(https://lore.kernel.org/linux-mm/20220712231328.5294-1-kirill.shutemov@linux.intel.com/)
uses a different interface based on arch_prctl():
 - arch_prctl(ARCH_GET_UNTAG_MASK, &mask) returns the current mask for
   untagging the pointers. We use it to detect kernel LAM support.
 - arch_prctl(ARCH_ENABLE_TAGGED_ADDR, nr_bits) enables pointer tagging
   for the current process.

Because __NR_arch_prctl is defined in different headers, and no other
platforms need it at the moment, we only declare internal_arch_prctl()
on x86_64.

Reviewed By: vitalybuka

Differential Revision: https://reviews.llvm.org/D129645
  • Loading branch information
ramosian-glider authored and vitalybuka committed Jul 14, 2022
1 parent cef0716 commit b191056
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 11 deletions.
26 changes: 15 additions & 11 deletions compiler-rt/lib/hwasan/hwasan_linux.cpp
Expand Up @@ -114,11 +114,21 @@ void InitializeOsSupport() {
# define PR_SET_TAGGED_ADDR_CTRL 55
# define PR_GET_TAGGED_ADDR_CTRL 56
# define PR_TAGGED_ADDR_ENABLE (1UL << 0)
# define ARCH_GET_UNTAG_MASK 0x4001
# define ARCH_ENABLE_TAGGED_ADDR 0x4002
// Check we're running on a kernel that can use the tagged address ABI.
int local_errno = 0;
if (internal_iserror(internal_prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0),
bool has_abi;
# if defined(__x86_64__)
has_abi = (internal_iserror(internal_arch_prctl(ARCH_GET_UNTAG_MASK, 0),
&local_errno) &&
local_errno == EINVAL) {
local_errno == EINVAL);
# else
has_abi = (internal_iserror(internal_prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0),
&local_errno) &&
local_errno == EINVAL);
# endif
if (has_abi) {
# if SANITIZER_ANDROID || defined(HWASAN_ALIASING_MODE)
// Some older Android kernels have the tagged pointer ABI on
// unconditionally, and hence don't have the tagged-addr prctl while still
Expand All @@ -142,17 +152,11 @@ void InitializeOsSupport() {
!internal_prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0))) {
# if defined(__x86_64__) && !defined(HWASAN_ALIASING_MODE)
// Try the new prctl API for Intel LAM. The API is based on a currently
// unsubmitted patch to the Linux kernel (as of May 2021) and is thus
// unsubmitted patch to the Linux kernel (as of July 2022) and is thus
// subject to change. Patch is here:
// https://lore.kernel.org/linux-mm/20210205151631.43511-12-kirill.shutemov@linux.intel.com/
int tag_bits = kTagBits;
int tag_shift = kAddressTagShift;
// https://lore.kernel.org/linux-mm/20220712231328.5294-1-kirill.shutemov@linux.intel.com/
if (!internal_iserror(
internal_prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE,
reinterpret_cast<unsigned long>(&tag_bits),
reinterpret_cast<unsigned long>(&tag_shift), 0))) {
CHECK_EQ(tag_bits, kTagBits);
CHECK_EQ(tag_shift, kAddressTagShift);
internal_arch_prctl(ARCH_ENABLE_TAGGED_ADDR, kTagBits))) {
return;
}
# endif // defined(__x86_64__) && !defined(HWASAN_ALIASING_MODE)
Expand Down
7 changes: 7 additions & 0 deletions compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
Expand Up @@ -763,6 +763,13 @@ uptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
return internal_syscall(SYSCALL(prctl), option, arg2, arg3, arg4, arg5);
}
# if defined(__x86_64__)
#include <asm/unistd_64.h>
// Currently internal_arch_prctl() is only needed on x86_64.
uptr internal_arch_prctl(int option, uptr arg2) {
return internal_syscall(__NR_arch_prctl, option, arg2);
}
# endif
#endif

uptr internal_sigaltstack(const void *ss, void *oss) {
Expand Down
3 changes: 3 additions & 0 deletions compiler-rt/lib/sanitizer_common/sanitizer_linux.h
Expand Up @@ -69,6 +69,9 @@ uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp);
// Linux-only syscalls.
#if SANITIZER_LINUX
uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5);
# if defined(__x86_64__)
uptr internal_arch_prctl(int option, uptr arg2);
# endif
// Used only by sanitizer_stoptheworld. Signal handlers that are actually used
// (like the process-wide error reporting SEGV handler) must use
// internal_sigaction instead.
Expand Down

0 comments on commit b191056

Please sign in to comment.