Skip to content

[libc] fortify jmp buffer for x86-64 #112769

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

Open
wants to merge 17 commits into
base: main
Choose a base branch
from

Conversation

SchrodingerZhu
Copy link
Contributor

supersedes ##101110

@llvmbot
Copy link
Member

llvmbot commented Oct 17, 2024

@llvm/pr-subscribers-libc

Author: Schrodinger ZHU Yifan (SchrodingerZhu)

Changes

supersedes ##101110


Full diff: https://github.com/llvm/llvm-project/pull/112769.diff

10 Files Affected:

  • (modified) libc/config/config.json (+4)
  • (modified) libc/docs/configure.rst (+1)
  • (modified) libc/include/llvm-libc-types/jmp_buf.h (+2)
  • (modified) libc/src/setjmp/CMakeLists.txt (+18)
  • (added) libc/src/setjmp/checksum.h (+46)
  • (modified) libc/src/setjmp/x86_64/CMakeLists.txt (+4)
  • (modified) libc/src/setjmp/x86_64/longjmp.cpp (+63-15)
  • (modified) libc/src/setjmp/x86_64/setjmp.cpp (+68-17)
  • (modified) libc/startup/linux/CMakeLists.txt (+1)
  • (modified) libc/startup/linux/do_start.cpp (+2-1)
diff --git a/libc/config/config.json b/libc/config/config.json
index 2e4f878778e6e0..88110ab29152c3 100644
--- a/libc/config/config.json
+++ b/libc/config/config.json
@@ -99,6 +99,10 @@
     "LIBC_CONF_SETJMP_AARCH64_RESTORE_PLATFORM_REGISTER": {
       "value": true,
       "doc": "Make setjmp save the value of x18, and longjmp restore it. The AArch64 ABI delegates this register to platform ABIs, which can choose whether to make it caller-saved."
+    },
+    "LIBC_CONF_SETJMP_ENABLE_FORTIFICATION": {
+      "value": true,
+      "doc": "Enable fortification for setjmp and longjmp."
     }
   },
   "time": {
diff --git a/libc/docs/configure.rst b/libc/docs/configure.rst
index 867bb807d10ac9..2704b47f13cb36 100644
--- a/libc/docs/configure.rst
+++ b/libc/docs/configure.rst
@@ -54,6 +54,7 @@ to learn about the defaults for your platform and target.
     - ``LIBC_CONF_SCANF_DISABLE_INDEX_MODE``: Disable index mode in the scanf format string.
 * **"setjmp" options**
     - ``LIBC_CONF_SETJMP_AARCH64_RESTORE_PLATFORM_REGISTER``: Make setjmp save the value of x18, and longjmp restore it. The AArch64 ABI delegates this register to platform ABIs, which can choose whether to make it caller-saved.
+    - ``LIBC_CONF_SETJMP_ENABLE_FORTIFICATION``: Enable fortification for setjmp and longjmp.
 * **"string" options**
     - ``LIBC_CONF_MEMSET_X86_USE_SOFTWARE_PREFETCHING``: Inserts prefetch for write instructions (PREFETCHW) for memset on x86 to recover performance when hardware prefetcher is disabled.
     - ``LIBC_CONF_STRING_UNSAFE_WIDE_READ``: Read more than a byte at a time to perform byte-string operations like strlen.
diff --git a/libc/include/llvm-libc-types/jmp_buf.h b/libc/include/llvm-libc-types/jmp_buf.h
index 60e033c6c65a95..c89bfc5afcbd3b 100644
--- a/libc/include/llvm-libc-types/jmp_buf.h
+++ b/libc/include/llvm-libc-types/jmp_buf.h
@@ -43,6 +43,8 @@ typedef struct {
 #else
 #error "__jmp_buf not available for your target architecture."
 #endif
+  // unused if checksum feature is not enabled.
+  __UINT64_TYPE__ __chksum;
 } __jmp_buf;
 
 typedef __jmp_buf jmp_buf[1];
diff --git a/libc/src/setjmp/CMakeLists.txt b/libc/src/setjmp/CMakeLists.txt
index d85c532e8636c8..a90c3e177fb739 100644
--- a/libc/src/setjmp/CMakeLists.txt
+++ b/libc/src/setjmp/CMakeLists.txt
@@ -2,6 +2,24 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_ARCHITECTURE})
   add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_ARCHITECTURE})
 endif()
 
+if (LIBC_CONF_SETJMP_ENABLE_FORTIFICATION)
+  set(checksum_flags "-DLIBC_SETJMP_ENABLE_FORTIFICATION=1")
+else()
+  set(checksum_flags "-DLIBC_SETJMP_ENABLE_FORTIFICATION=0")
+endif()
+
+
+add_header_library(
+  checksum
+  HDRS
+    checksum.h
+  DEPENDS
+    libc.src.__support.common
+    libc.src.__support.OSUtil.osutil
+  COMPILE_OPTIONS
+    ${checksum_flags}
+)
+
 add_entrypoint_object(
   setjmp
   ALIAS
diff --git a/libc/src/setjmp/checksum.h b/libc/src/setjmp/checksum.h
new file mode 100644
index 00000000000000..df6a12d185c3ee
--- /dev/null
+++ b/libc/src/setjmp/checksum.h
@@ -0,0 +1,46 @@
+//===-- Implementation header for jmpbuf checksum ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SETJMP_CHECKSUM_H
+#define LLVM_LIBC_SRC_SETJMP_CHECKSUM_H
+
+#ifndef LIBC_COPT_SETJMP_ENABLE_FORTIFICATION
+#define LIBC_COPT_SETJMP_ENABLE_FORTIFICATION 1
+#endif
+
+#if LIBC_COPT_SETJMP_ENABLE_FORTIFICATION
+#include "src/__support/OSUtil/syscall.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h>
+
+namespace LIBC_NAMESPACE_DECL {
+namespace jmpbuf {
+// random bytes from https://www.random.org/cgi-bin/randbyte?nbytes=8&format=h
+LIBC_INLINE __UINTPTR_TYPE__ value_mask = 0x3899'f0d3'5005'd953;
+LIBC_INLINE __UINT64_TYPE__ checksum_cookie = 0xc7d9'd341'6afc'33f2;
+// abitrary prime number
+LIBC_INLINE constexpr __UINT64_TYPE__ ROTATION = 13;
+// initialize the checksum state
+LIBC_INLINE void initialize() {
+  union {
+    struct {
+      __UINTPTR_TYPE__ entropy0;
+      __UINT64_TYPE__ entropy1;
+    };
+    char buffer[sizeof(__UINTPTR_TYPE__) + sizeof(__UINT64_TYPE__)];
+  };
+  syscall_impl<long>(SYS_getrandom, buffer, sizeof(buffer), 0);
+  // add in additional entropy
+  jmpbuf::value_mask ^= entropy0;
+  jmpbuf::checksum_cookie ^= entropy1;
+}
+} // namespace jmpbuf
+} // namespace LIBC_NAMESPACE_DECL
+#endif // LIBC_SETJMP_ENABLE_FORTIFICATION
+
+#endif // LLVM_LIBC_SRC_SETJMP_CHECKSUM_H
diff --git a/libc/src/setjmp/x86_64/CMakeLists.txt b/libc/src/setjmp/x86_64/CMakeLists.txt
index b5b0d9ba65599c..571f3681887106 100644
--- a/libc/src/setjmp/x86_64/CMakeLists.txt
+++ b/libc/src/setjmp/x86_64/CMakeLists.txt
@@ -6,6 +6,7 @@ add_entrypoint_object(
     ../setjmp_impl.h
   DEPENDS
     libc.hdr.types.jmp_buf
+    libc.src.setjmp.checksum
   COMPILE_OPTIONS
     -O3
 )
@@ -18,6 +19,9 @@ add_entrypoint_object(
     ../longjmp.h
   DEPENDS
     libc.hdr.types.jmp_buf
+    libc.src.stdlib.abort
+    libc.src.__support.OSUtil.osutil
+    libc.src.setjmp.checksum
   COMPILE_OPTIONS
     -O3
     -fomit-frame-pointer
diff --git a/libc/src/setjmp/x86_64/longjmp.cpp b/libc/src/setjmp/x86_64/longjmp.cpp
index c293c55a6f9fb2..09aa189f2b87bd 100644
--- a/libc/src/setjmp/x86_64/longjmp.cpp
+++ b/libc/src/setjmp/x86_64/longjmp.cpp
@@ -8,8 +8,11 @@
 
 #include "src/setjmp/longjmp.h"
 #include "include/llvm-libc-macros/offsetof-macro.h"
+#include "src/__support/OSUtil/io.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
+#include "src/setjmp/checksum.h"
+#include "src/stdlib/abort.h"
 
 #if !defined(LIBC_TARGET_ARCH_IS_X86_64)
 #error "Invalid file include"
@@ -17,26 +20,71 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
+#if LIBC_COPT_SETJMP_ENABLE_FORTIFICATION
+extern "C" [[gnu::cold, noreturn]] void __libc_jmpbuf_corruption() {
+  write_to_stderr("invalid checksum detected in longjmp\n");
+  abort();
+}
+#define LOAD_CHKSUM_STATE_REGISTERS()                                          \
+  asm("mov %0, %%rcx\n\t" ::"m"(jmpbuf::value_mask) : "rcx");                  \
+  asm("mov %0, %%rdx\n\t" ::"m"(jmpbuf::checksum_cookie) : "rdx");
+
+#define RESTORE_REG(DST)                                                       \
+  "movq %c[" #DST "](%%rdi), %%rax\n\t"                                        \
+  "movq %%rax, %%" #DST "\n\t"                                                 \
+  "xor %%rcx, %%" #DST "\n\t"                                                  \
+  "mul %%rdx\n\t"                                                              \
+  "xor %%rax, %%rdx\n\t"                                                       \
+  "rol $%c[rotation], %%rdx\n\t"
+
+#define RESTORE_RIP()                                                          \
+  "movq %c[rip](%%rdi), %%rax\n\t"                                             \
+  "xor %%rax, %%rcx\n\t"                                                       \
+  "mul %%rdx\n\t"                                                              \
+  "xor %%rax, %%rdx\n\t"                                                       \
+  "rol $%c[rotation], %%rdx\n\t"                                               \
+  "cmp %c[chksum](%%rdi), %%rdx\n\t"                                           \
+  "jne __libc_jmpbuf_corruption\n\t"                                           \
+  "cmpl $0x1, %%esi\n\t"                                                       \
+  "adcl $0x0, %%esi\n\t"                                                       \
+  "movq %%rsi, %%rax\n\t"                                                      \
+  "jmp *%%rcx\n\t"
+#else
+#define LOAD_CHKSUM_STATE_REGISTERS()
+#define RESTORE_REG(DST) "movq %c[" #DST "](%%rdi), %%" #DST "\n\t"
+#define RESTORE_RIP()                                                          \
+  "cmpl $0x1, %%esi\n\t"                                                       \
+  "adcl $0x0, %%esi\n\t"                                                       \
+  "movq %%rsi, %%rax\n\t"                                                      \
+  "jmpq *%c[rip](%%rdi)\n\t"
+#endif
+
 [[gnu::naked]]
 LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf, int)) {
-  asm(R"(
-      cmpl $0x1, %%esi
-      adcl $0x0, %%esi
-      movq %%rsi, %%rax
-
-      movq %c[rbx](%%rdi), %%rbx
-      movq %c[rbp](%%rdi), %%rbp
-      movq %c[r12](%%rdi), %%r12
-      movq %c[r13](%%rdi), %%r13
-      movq %c[r14](%%rdi), %%r14
-      movq %c[r15](%%rdi), %%r15
-      movq %c[rsp](%%rdi), %%rsp
-      jmpq *%c[rip](%%rdi)
-      )" ::[rbx] "i"(offsetof(__jmp_buf, rbx)),
+  LOAD_CHKSUM_STATE_REGISTERS()
+  asm(
+      // clang-format off
+      RESTORE_REG(rbx)
+      RESTORE_REG(rbp)
+      RESTORE_REG(r12)
+      RESTORE_REG(r13)
+      RESTORE_REG(r14)
+      RESTORE_REG(r15)
+      RESTORE_REG(rsp)
+      RESTORE_RIP()
+      // clang-format on
+      ::[rbx] "i"(offsetof(__jmp_buf, rbx)),
       [rbp] "i"(offsetof(__jmp_buf, rbp)), [r12] "i"(offsetof(__jmp_buf, r12)),
       [r13] "i"(offsetof(__jmp_buf, r13)), [r14] "i"(offsetof(__jmp_buf, r14)),
       [r15] "i"(offsetof(__jmp_buf, r15)), [rsp] "i"(offsetof(__jmp_buf, rsp)),
-      [rip] "i"(offsetof(__jmp_buf, rip)));
+      [rip] "i"(offsetof(__jmp_buf, rip))
+#if LIBC_COPT_SETJMP_ENABLE_FORTIFICATION
+      // clang-format off
+      ,[rotation] "i"(jmpbuf::ROTATION)
+      , [chksum] "i"(offsetof(__jmp_buf, __chksum))
+  // clang-format on
+#endif
+      : "rax", "rdx", "rcx", "rsi");
 }
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/setjmp/x86_64/setjmp.cpp b/libc/src/setjmp/x86_64/setjmp.cpp
index f6e82642edd7da..56e2f55cd3a9ff 100644
--- a/libc/src/setjmp/x86_64/setjmp.cpp
+++ b/libc/src/setjmp/x86_64/setjmp.cpp
@@ -9,37 +9,88 @@
 #include "include/llvm-libc-macros/offsetof-macro.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
+#include "src/setjmp/checksum.h"
 #include "src/setjmp/setjmp_impl.h"
 
 #if !defined(LIBC_TARGET_ARCH_IS_X86_64)
 #error "Invalid file include"
 #endif
 
-namespace LIBC_NAMESPACE_DECL {
+#if LIBC_COPT_SETJMP_ENABLE_FORTIFICATION
+#define LOAD_CHKSUM_STATE_REGISTERS()                                          \
+  asm("mov %0, %%rcx\n\t" ::"m"(jmpbuf::value_mask) : "rcx");                  \
+  asm("mov %0, %%rdx\n\t" ::"m"(jmpbuf::checksum_cookie) : "rdx");
 
-[[gnu::naked]]
-LLVM_LIBC_FUNCTION(int, setjmp, (jmp_buf buf)) {
-  asm(R"(
-      mov %%rbx, %c[rbx](%%rdi)
-      mov %%rbp, %c[rbp](%%rdi)
-      mov %%r12, %c[r12](%%rdi)
-      mov %%r13, %c[r13](%%rdi)
-      mov %%r14, %c[r14](%%rdi)
-      mov %%r15, %c[r15](%%rdi)
+#define STORE_REG(SRC)                                                         \
+  "mov %%" #SRC ", %%rax\n\t"                                                  \
+  "xor %%rcx, %%rax\n\t"                                                       \
+  "mov %%rax, %c[" #SRC "](%%rdi)\n\t"                                         \
+  "mul %%rdx\n\t"                                                              \
+  "xor %%rax, %%rdx\n\t"                                                       \
+  "rol $%c[rotation], %%rdx\n\t"
+
+#define STORE_RSP()                                                            \
+  "lea 8(%%rsp), %%rax\n\t"                                                    \
+  "xor %%rcx, %%rax\n\t"                                                       \
+  "mov %%rax, %c[rsp](%%rdi)\n\t"                                              \
+  "mul %%rdx\n\t"                                                              \
+  "xor %%rax, %%rdx\n\t"                                                       \
+  "rolq $%c[rotation], %%rdx\n\t"
 
-      lea 8(%%rsp), %%rax
-      mov %%rax, %c[rsp](%%rdi)
+#define STORE_RIP()                                                            \
+  "mov (%%rsp), %%rax\n\t"                                                     \
+  "xor %%rcx, %%rax\n\t"                                                       \
+  "mov %%rax, %c[rip](%%rdi)\n\t"                                              \
+  "mul %%rdx\n\t"                                                              \
+  "xor %%rax, %%rdx\n\t"                                                       \
+  "rolq $%c[rotation], %%rdx\n\t"
 
-      mov (%%rsp), %%rax
-      mov %%rax, %c[rip](%%rdi)
+#define STORE_CHECKSUM() "mov %%rdx, %c[chksum](%%rdi)\n\t"
+#else
+#define LOAD_CHKSUM_STATE_REGISTERS()
+#define STORE_REG(SRC) "mov %%" #SRC ", %c[" #SRC "](%%rdi)\n\t"
+#define STORE_RSP()                                                            \
+  "lea 8(%%rsp), %%rax\n\t"                                                    \
+  "mov %%rax, %c[rsp](%%rdi)\n\t"
+#define STORE_RIP()                                                            \
+  "mov (%%rsp), %%rax\n\t"                                                     \
+  "mov %%rax, %c[rip](%%rdi)\n\t"
+#define STORE_CHECKSUM()
+#endif
 
-      xorl %%eax, %%eax
-      retq)" ::[rbx] "i"(offsetof(__jmp_buf, rbx)),
+namespace LIBC_NAMESPACE_DECL {
+[[gnu::naked]]
+LLVM_LIBC_FUNCTION(int, setjmp, (jmp_buf buf)) {
+  LOAD_CHKSUM_STATE_REGISTERS()
+  asm(
+      // clang-format off
+    STORE_REG(rbx)
+    STORE_REG(rbp)
+    STORE_REG(r12)
+    STORE_REG(r13)
+    STORE_REG(r14)
+    STORE_REG(r15)
+    STORE_RSP()
+    STORE_RIP()
+    STORE_CHECKSUM()
+      // clang-format on
+      ::[rbx] "i"(offsetof(__jmp_buf, rbx)),
       [rbp] "i"(offsetof(__jmp_buf, rbp)), [r12] "i"(offsetof(__jmp_buf, r12)),
       [r13] "i"(offsetof(__jmp_buf, r13)), [r14] "i"(offsetof(__jmp_buf, r14)),
       [r15] "i"(offsetof(__jmp_buf, r15)), [rsp] "i"(offsetof(__jmp_buf, rsp)),
       [rip] "i"(offsetof(__jmp_buf, rip))
-      : "rax");
+#if LIBC_COPT_SETJMP_ENABLE_FORTIFICATION
+      // clang-format off
+      ,[rotation] "i"(jmpbuf::ROTATION)
+      ,[chksum] "i"(offsetof(__jmp_buf, __chksum))
+  // clang-format on
+#endif
+      : "rax", "rdx");
+
+  asm(R"(
+    xorl %eax, %eax
+    retq
+  )");
 }
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/startup/linux/CMakeLists.txt b/libc/startup/linux/CMakeLists.txt
index eaa724e41f1685..34c870f98b1f1c 100644
--- a/libc/startup/linux/CMakeLists.txt
+++ b/libc/startup/linux/CMakeLists.txt
@@ -104,6 +104,7 @@ add_object_library(
     libc.src.stdlib.exit
     libc.src.stdlib.atexit
     libc.src.unistd.environ
+    libc.src.setjmp.checksum
   COMPILE_OPTIONS
     -ffreestanding       # To avoid compiler warnings about calling the main function.
     -fno-builtin         # avoid emit unexpected calls
diff --git a/libc/startup/linux/do_start.cpp b/libc/startup/linux/do_start.cpp
index ff104c7f0d1d2f..fc40ac0b1b1095 100644
--- a/libc/startup/linux/do_start.cpp
+++ b/libc/startup/linux/do_start.cpp
@@ -11,6 +11,7 @@
 #include "src/__support/OSUtil/syscall.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/threads/thread.h"
+#include "src/setjmp/checksum.h"
 #include "src/stdlib/atexit.h"
 #include "src/stdlib/exit.h"
 #include "src/unistd/environ.h"
@@ -130,7 +131,7 @@ void teardown_main_tls() { cleanup_tls(tls.addr, tls.size); }
   init_tls(tls);
   if (tls.size != 0 && !set_thread_ptr(tls.tp))
     syscall_impl<long>(SYS_exit, 1);
-
+  jmpbuf::initialize();
   self.attrib = &main_thread_attrib;
   main_thread_attrib.atexit_callback_mgr =
       internal::get_thread_atexit_callback_mgr();

@SchrodingerZhu
Copy link
Contributor Author

Some performance data.

Iterations:        100
Instructions:      5500
Total Cycles:      2475
Total uOps:        6300

Dispatch Width:    6
uOps Per Cycle:    2.55
IPC:               2.22
Block RThroughput: 24.0


Cycles with backend pressure increase [ 28.53% ]
Throughput Bottlenecks: 
  Resource Pressure       [ 27.88% ]
  - Zn4ALU1  [ 27.88% ]
  Data Dependencies:      [ 28.48% ]
  - Register Dependencies [ 28.48% ]
  - Memory Dependencies   [ 0.00% ]

Critical sequence based on the simulation:

              Instruction                                 Dependency Information
        0.    movq	_ZN22__llvm_libc_20_0_0_git6jmpbuf10value_maskE(%rip), %rcx
        1.    movq	_ZN22__llvm_libc_20_0_0_git6jmpbuf15checksum_cookieE(%rip), %rdx
        2.    movq	(%rdi), %rax
        3.    movq	%rax, %rbx
        4.    xorq	%rcx, %rbx
        5.    mulq	%rdx
        6.    xorq	%rax, %rdx
        7.    rolq	$13, %rdx
 +----< 8.    movq	8(%rdi), %rax
 |      9.    movq	%rax, %rbp
 |      10.   xorq	%rcx, %rbp
 +----> 11.   mulq	%rdx                              ## REGISTER dependency:  %rax
 +----> 12.   xorq	%rax, %rdx                        ## REGISTER dependency:  %rax
 +----> 13.   rolq	$13, %rdx                         ## REGISTER dependency:  %rdx
        14.   movq	16(%rdi), %rax
        15.   movq	%rax, %r12
        16.   xorq	%rcx, %r12
        17.   mulq	%rdx
        18.   xorq	%rax, %rdx
        19.   rolq	$13, %rdx
        20.   movq	24(%rdi), %rax
        21.   movq	%rax, %r13
        22.   xorq	%rcx, %r13
        23.   mulq	%rdx
        24.   xorq	%rax, %rdx
        25.   rolq	$13, %rdx
        26.   movq	32(%rdi), %rax
        27.   movq	%rax, %r14
        28.   xorq	%rcx, %r14
        29.   mulq	%rdx
        30.   xorq	%rax, %rdx
        31.   rolq	$13, %rdx
        32.   movq	40(%rdi), %rax
        33.   movq	%rax, %r15
        34.   xorq	%rcx, %r15
        35.   mulq	%rdx
        36.   xorq	%rax, %rdx
        37.   rolq	$13, %rdx
        38.   movq	48(%rdi), %rax
        39.   movq	%rax, %rsp
        40.   xorq	%rcx, %rsp
        41.   mulq	%rdx
        42.   xorq	%rax, %rdx
        43.   rolq	$13, %rdx
        44.   movq	56(%rdi), %rax
        45.   xorq	%rax, %rcx
        46.   mulq	%rdx
        47.   xorq	%rax, %rdx
        48.   rolq	$13, %rdx
        49.   cmpq	64(%rdi), %rdx
        50.   jne	__libc_jmpbuf_corruption
        51.   cmpl	$1, %esi
        52.   adcl	$0, %esi
        53.   movq	%rsi, %rax
        54.   jmpq	*%rcx


Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)

[1]    [2]    [3]    [4]    [5]    [6]    Instructions:
 1      5     0.33    *                   movq	_ZN22__llvm_libc_20_0_0_git6jmpbuf10value_maskE(%rip), %rcx
 1      5     0.33    *                   movq	_ZN22__llvm_libc_20_0_0_git6jmpbuf15checksum_cookieE(%rip), %rdx
 1      5     0.33    *                   movq	(%rdi), %rax
 1      0     0.17                        movq	%rax, %rbx
 1      1     0.25                        xorq	%rcx, %rbx
 2      3     3.00                        mulq	%rdx
 1      1     0.25                        xorq	%rax, %rdx
 1      1     0.50                        rolq	$13, %rdx
 1      5     0.33    *                   movq	8(%rdi), %rax
 1      0     0.17                        movq	%rax, %rbp
 1      1     0.25                        xorq	%rcx, %rbp
 2      3     3.00                        mulq	%rdx
 1      1     0.25                        xorq	%rax, %rdx
 1      1     0.50                        rolq	$13, %rdx
 1      5     0.33    *                   movq	16(%rdi), %rax
 1      0     0.17                        movq	%rax, %r12
 1      1     0.25                        xorq	%rcx, %r12
 2      3     3.00                        mulq	%rdx
 1      1     0.25                        xorq	%rax, %rdx
 1      1     0.50                        rolq	$13, %rdx
 1      5     0.33    *                   movq	24(%rdi), %rax
 1      0     0.17                        movq	%rax, %r13
 1      1     0.25                        xorq	%rcx, %r13
 2      3     3.00                        mulq	%rdx
 1      1     0.25                        xorq	%rax, %rdx
 1      1     0.50                        rolq	$13, %rdx
 1      5     0.33    *                   movq	32(%rdi), %rax
 1      0     0.17                        movq	%rax, %r14
 1      1     0.25                        xorq	%rcx, %r14
 2      3     3.00                        mulq	%rdx
 1      1     0.25                        xorq	%rax, %rdx
 1      1     0.50                        rolq	$13, %rdx
 1      5     0.33    *                   movq	40(%rdi), %rax
 1      0     0.17                        movq	%rax, %r15
 1      1     0.25                        xorq	%rcx, %r15
 2      3     3.00                        mulq	%rdx
 1      1     0.25                        xorq	%rax, %rdx
 1      1     0.50                        rolq	$13, %rdx
 1      5     0.33    *                   movq	48(%rdi), %rax
 1      0     0.17                        movq	%rax, %rsp
 1      1     0.25                        xorq	%rcx, %rsp
 2      3     3.00                        mulq	%rdx
 1      1     0.25                        xorq	%rax, %rdx
 1      1     0.50                        rolq	$13, %rdx
 1      5     0.33    *                   movq	56(%rdi), %rax
 1      1     0.25                        xorq	%rax, %rcx
 2      3     3.00                        mulq	%rdx
 1      1     0.25                        xorq	%rax, %rdx
 1      1     0.50                        rolq	$13, %rdx
 1      5     0.33    *                   cmpq	64(%rdi), %rdx
 1      1     0.50                        jne	__libc_jmpbuf_corruption
 1      1     0.25                        cmpl	$1, %esi
 1      1     1.00                        adcl	$0, %esi
 1      0     0.17                        movq	%rsi, %rax
 1      1     0.50                        jmpq	*%rcx


Resources:
[0]   - Zn4AGU0
[1]   - Zn4AGU1
[2]   - Zn4AGU2
[3]   - Zn4ALU0
[4]   - Zn4ALU1
[5]   - Zn4ALU2
[6]   - Zn4ALU3
[7]   - Zn4BRU1
[8]   - Zn4FP0
[9]   - Zn4FP1
[10]  - Zn4FP2
[11]  - Zn4FP3
[12.0] - Zn4FP45
[12.1] - Zn4FP45
[13]  - Zn4FPSt
[14.0] - Zn4LSU
[14.1] - Zn4LSU
[14.2] - Zn4LSU
[15.0] - Zn4Load
[15.1] - Zn4Load
[15.2] - Zn4Load
[16.0] - Zn4Store
[16.1] - Zn4Store


Resource pressure per iteration:
[0]    [1]    [2]    [3]    [4]    [5]    [6]    [7]    [8]    [9]    [10]   [11]   [12.0] [12.1] [13]   [14.0] [14.1] [14.2] [15.0] [15.1] [15.2] [16.0] [16.1] 
3.66   3.67   3.67   10.96  24.53  9.52   8.99   2.00    -      -      -      -      -      -      -     3.66   3.67   3.67   3.66   3.67   3.67    -      -     

Resource pressure by instruction:
[0]    [1]    [2]    [3]    [4]    [5]    [6]    [7]    [8]    [9]    [10]   [11]   [12.0] [12.1] [13]   [14.0] [14.1] [14.2] [15.0] [15.1] [15.2] [16.0] [16.1] Instructions:
0.33   0.33   0.34    -      -      -      -      -      -      -      -      -      -      -      -     0.33   0.33   0.34   0.33   0.33   0.34    -      -     movq	_ZN22__llvm_libc_20_0_0_git6jmpbuf10value_maskE(%rip), %rcx
0.33   0.34   0.33    -      -      -      -      -      -      -      -      -      -      -      -     0.33   0.34   0.33   0.33   0.34   0.33    -      -     movq	_ZN22__llvm_libc_20_0_0_git6jmpbuf15checksum_cookieE(%rip), %rdx
0.34   0.33   0.33    -      -      -      -      -      -      -      -      -      -      -      -     0.34   0.33   0.33   0.34   0.33   0.33    -      -     movq	(%rdi), %rax
 -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     movq	%rax, %rbx
 -      -      -     0.02    -      -     0.98    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     xorq	%rcx, %rbx
 -      -      -      -     3.00    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     mulq	%rdx
 -      -      -     0.98    -      -     0.02    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     xorq	%rax, %rdx
 -      -      -      -      -     1.00    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     rolq	$13, %rdx
0.33   0.33   0.34    -      -      -      -      -      -      -      -      -      -      -      -     0.33   0.33   0.34   0.33   0.33   0.34    -      -     movq	8(%rdi), %rax
 -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     movq	%rax, %rbp
 -      -      -     0.97    -     0.01   0.02    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     xorq	%rcx, %rbp
 -      -      -      -     3.00    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     mulq	%rdx
 -      -      -     0.02    -     0.01   0.97    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     xorq	%rax, %rdx
 -      -      -      -      -     1.00    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     rolq	$13, %rdx
0.33   0.34   0.33    -      -      -      -      -      -      -      -      -      -      -      -     0.33   0.34   0.33   0.33   0.34   0.33    -      -     movq	16(%rdi), %rax
 -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     movq	%rax, %r12
 -      -      -     0.50    -     0.48   0.02    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     xorq	%rcx, %r12
 -      -      -      -     3.00    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     mulq	%rdx
 -      -      -     0.99    -     0.01    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     xorq	%rax, %rdx
 -      -      -      -      -     1.00    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     rolq	$13, %rdx
0.34   0.33   0.33    -      -      -      -      -      -      -      -      -      -      -      -     0.34   0.33   0.33   0.34   0.33   0.33    -      -     movq	24(%rdi), %rax
 -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     movq	%rax, %r13
 -      -      -     0.51   0.01    -     0.48    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     xorq	%rcx, %r13
 -      -      -      -     3.00    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     mulq	%rdx
 -      -      -     0.01   0.48   0.01   0.50    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     xorq	%rax, %rdx
 -      -      -      -      -     1.00    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     rolq	$13, %rdx
0.33   0.34   0.33    -      -      -      -      -      -      -      -      -      -      -      -     0.33   0.34   0.33   0.33   0.34   0.33    -      -     movq	32(%rdi), %rax
 -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     movq	%rax, %r14
 -      -      -     0.01    -     0.01   0.98    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     xorq	%rcx, %r14
 -      -      -      -     3.00    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     mulq	%rdx
 -      -      -     0.48    -     0.01   0.51    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     xorq	%rax, %rdx
 -      -      -      -     0.01   0.99    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     rolq	$13, %rdx
0.34   0.33   0.33    -      -      -      -      -      -      -      -      -      -      -      -     0.34   0.33   0.33   0.34   0.33   0.33    -      -     movq	40(%rdi), %rax
 -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     movq	%rax, %r15
 -      -      -     0.01    -     0.01   0.98    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     xorq	%rcx, %r15
 -      -      -      -     3.00    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     mulq	%rdx
 -      -      -     0.50   0.01   0.48   0.01    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     xorq	%rax, %rdx
 -      -      -      -     0.01   0.99    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     rolq	$13, %rdx
0.33   0.33   0.34    -      -      -      -      -      -      -      -      -      -      -      -     0.33   0.33   0.34   0.33   0.33   0.34    -      -     movq	48(%rdi), %rax
 -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     movq	%rax, %rsp
 -      -      -     0.01    -     0.49   0.50    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     xorq	%rcx, %rsp
 -      -      -      -     3.00    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     mulq	%rdx
 -      -      -      -      -     0.01   0.99    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     xorq	%rax, %rdx
 -      -      -      -      -     1.00    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     rolq	$13, %rdx
0.33   0.34   0.33    -      -      -      -      -      -      -      -      -      -      -      -     0.33   0.34   0.33   0.33   0.34   0.33    -      -     movq	56(%rdi), %rax
 -      -      -      -     0.01   0.01   0.98    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     xorq	%rax, %rcx
 -      -      -      -     3.00    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     mulq	%rdx
 -      -      -     0.50    -      -     0.50    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     xorq	%rax, %rdx
 -      -      -      -      -     1.00    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     rolq	$13, %rdx
0.33   0.33   0.34   0.50    -      -     0.50    -      -      -      -      -      -      -      -     0.33   0.33   0.34   0.33   0.33   0.34    -      -     cmpq	64(%rdi), %rdx
 -      -      -      -      -      -      -     1.00    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     jne	__libc_jmpbuf_corruption
 -      -      -     0.99    -      -     0.01    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     cmpl	$1, %esi
 -      -      -     3.96    -      -     0.04    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     adcl	$0, %esi
 -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     movq	%rsi, %rax
 -      -      -      -      -      -      -     1.00    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     jmpq	*%rcx

Without fortification:

Iterations:        100
Instructions:      1100
Total Cycles:      274
Total uOps:        1100

Dispatch Width:    6
uOps Per Cycle:    4.01
IPC:               4.01
Block RThroughput: 2.7


Cycles with backend pressure increase [ 90.88% ]
Throughput Bottlenecks: 
  Resource Pressure       [ 90.88% ]
  - Zn4AGU0  [ 90.88% ]
  - Zn4AGU1  [ 90.88% ]
  - Zn4AGU2  [ 90.88% ]
  - Zn4ALU0  [ 11.68% ]
  - Zn4BRU1  [ 11.68% ]
  - Zn4LSU  [ 90.88% ]
  - Zn4Load  [ 90.88% ]
  Data Dependencies:      [ 44.16% ]
  - Register Dependencies [ 44.16% ]
  - Memory Dependencies   [ 0.00% ]

Critical sequence based on the simulation:

              Instruction                                 Dependency Information
 +----< 5.    movq	40(%rdi), %r15
 |
 |    < loop carried > 
 |
 +----> 0.    movq	(%rdi), %rbx                      ## RESOURCE interference:  Zn4LSU [ probability: 99% ]
 +----> 1.    movq	8(%rdi), %rbp                     ## RESOURCE interference:  Zn4LSU [ probability: 99% ]
 +----> 2.    movq	16(%rdi), %r12                    ## RESOURCE interference:  Zn4LSU [ probability: 99% ]
 +----> 3.    movq	24(%rdi), %r13                    ## RESOURCE interference:  Zn4LSU [ probability: 100% ]
 +----> 4.    movq	32(%rdi), %r14                    ## RESOURCE interference:  Zn4LSU [ probability: 100% ]
 +----> 5.    movq	40(%rdi), %r15                    ## RESOURCE interference:  Zn4LSU [ probability: 100% ]
 +----> 6.    movq	48(%rdi), %rsp                    ## RESOURCE interference:  Zn4LSU [ probability: 100% ]
 |      7.    cmpl	$1, %esi
 |      8.    adcl	$0, %esi
 |      9.    movq	%rsi, %rax
 +----> 10.   jmpq	*56(%rdi)                         ## RESOURCE interference:  Zn4LSU [ probability: 100% ]
 |
 |    < loop carried > 
 |
 +----> 2.    movq	16(%rdi), %r12                    ## RESOURCE interference:  Zn4LSU [ probability: 99% ]


Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)

[1]    [2]    [3]    [4]    [5]    [6]    Instructions:
 1      5     0.33    *                   movq	(%rdi), %rbx
 1      5     0.33    *                   movq	8(%rdi), %rbp
 1      5     0.33    *                   movq	16(%rdi), %r12
 1      5     0.33    *                   movq	24(%rdi), %r13
 1      5     0.33    *                   movq	32(%rdi), %r14
 1      5     0.33    *                   movq	40(%rdi), %r15
 1      5     0.33    *                   movq	48(%rdi), %rsp
 1      1     0.25                        cmpl	$1, %esi
 1      1     1.00                        adcl	$0, %esi
 1      0     0.17                        movq	%rsi, %rax
 1      5     0.50    *                   jmpq	*56(%rdi)


Resources:
[0]   - Zn4AGU0
[1]   - Zn4AGU1
[2]   - Zn4AGU2
[3]   - Zn4ALU0
[4]   - Zn4ALU1
[5]   - Zn4ALU2
[6]   - Zn4ALU3
[7]   - Zn4BRU1
[8]   - Zn4FP0
[9]   - Zn4FP1
[10]  - Zn4FP2
[11]  - Zn4FP3
[12.0] - Zn4FP45
[12.1] - Zn4FP45
[13]  - Zn4FPSt
[14.0] - Zn4LSU
[14.1] - Zn4LSU
[14.2] - Zn4LSU
[15.0] - Zn4Load
[15.1] - Zn4Load
[15.2] - Zn4Load
[16.0] - Zn4Store
[16.1] - Zn4Store


Resource pressure per iteration:
[0]    [1]    [2]    [3]    [4]    [5]    [6]    [7]    [8]    [9]    [10]   [11]   [12.0] [12.1] [13]   [14.0] [14.1] [14.2] [15.0] [15.1] [15.2] [16.0] [16.1] 
2.66   2.67   2.67   1.16   1.28   1.52   1.32   0.72    -      -      -      -      -      -      -     2.66   2.67   2.67   2.66   2.67   2.67    -      -     

Resource pressure by instruction:
[0]    [1]    [2]    [3]    [4]    [5]    [6]    [7]    [8]    [9]    [10]   [11]   [12.0] [12.1] [13]   [14.0] [14.1] [14.2] [15.0] [15.1] [15.2] [16.0] [16.1] Instructions:
0.33   0.33   0.34    -      -      -      -      -      -      -      -      -      -      -      -     0.33   0.33   0.34   0.33   0.33   0.34    -      -     movq	(%rdi), %rbx
0.33   0.34   0.33    -      -      -      -      -      -      -      -      -      -      -      -     0.33   0.34   0.33   0.33   0.34   0.33    -      -     movq	8(%rdi), %rbp
0.34   0.33   0.33    -      -      -      -      -      -      -      -      -      -      -      -     0.34   0.33   0.33   0.34   0.33   0.33    -      -     movq	16(%rdi), %r12
0.33   0.33   0.34    -      -      -      -      -      -      -      -      -      -      -      -     0.33   0.33   0.34   0.33   0.33   0.34    -      -     movq	24(%rdi), %r13
0.33   0.34   0.33    -      -      -      -      -      -      -      -      -      -      -      -     0.33   0.34   0.33   0.33   0.34   0.33    -      -     movq	32(%rdi), %r14
0.34   0.33   0.33    -      -      -      -      -      -      -      -      -      -      -      -     0.34   0.33   0.33   0.34   0.33   0.33    -      -     movq	40(%rdi), %r15
0.33   0.33   0.34    -      -      -      -      -      -      -      -      -      -      -      -     0.33   0.33   0.34   0.33   0.33   0.34    -      -     movq	48(%rdi), %rsp
 -      -      -     0.12   0.32   0.24   0.32    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     cmpl	$1, %esi
 -      -      -     0.76   0.96   1.28   1.00    -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     adcl	$0, %esi
 -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -      -     movq	%rsi, %rax
0.33   0.34   0.33   0.28    -      -      -     0.72    -      -      -      -      -      -      -     0.33   0.34   0.33   0.33   0.34   0.33    -      -     jmpq	*56(%rdi)

@statham-arm
Copy link
Collaborator

Thanks for the updates. I'm happy with this now, but @nickdesaulniers has been looking at completely different aspects of the patch, so I think he needs to be happy too.

(In another system like Gerrit I'd indicate this by setting +1 but not +2. Not sure what the corresponding Github etiquette is.)

@SchrodingerZhu
Copy link
Contributor Author

@nickdesaulniers a gentle ping~

Copy link
Member

@nickdesaulniers nickdesaulniers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, boy, this is getting harder and harder to follow. This code has maximally factored any repetition via macro expansion. While I'm a big fan of DRY (don't repeat yourself), I don't think we want that for inline asm.

I think rather than having this pattern of:

#ifdef __i386
...lots of #defines
#else
...lots of #defines
#endif

#ifdef LIBC_COPT_SETJMP_FORTIFICATION
...
#else
...lots of #defines
#endif

asm (
  MACRO_EXPANSION
  MACRO_EXPANSION
  MACRO_EXPANSION
  ...

it would be easier to maintain/read/understand if:

  1. we move i386 implementations to their own file. I split out i386 sources recently; I should have done that for jmp_buf.
  2. write checksum in C and call it from inline asm, so that the checksum routine is the same between architectures.
  3. perhaps have separate .cpp files selected via cmake depending on LIBC_COPT_SETJMP_FORTIFICATION. Then we can have longjump.cpp and longjump_fortified.cpp, setjump.cpp and setjump_fortified.cpp.

With inline asm, you really want to keep it straightforward what assembler you'll get. As is, I feel like I would need to preprocess setjmp.cpp and longjump.cpp just to fully review the sequence of instructions.


Please file an issue to track jmp_buf fortification for all architectures, then add a link to it in the PR description so that we can track implementing this for all other architectures.

@SchrodingerZhu
Copy link
Contributor Author

Yet another try. PTAL.

Copy link
Member

@nickdesaulniers nickdesaulniers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I think this approach is clearer!

Copy link

github-actions bot commented Nov 18, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@SchrodingerZhu
Copy link
Contributor Author

fixed

@SchrodingerZhu
Copy link
Contributor Author

@nickdesaulniers PTAL.

Copy link
Member

@nickdesaulniers nickdesaulniers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making progress on this. Sorry for hanging on code review a lot for it, but to me it is a very important feature, so it does require more scrutiny IMO.

DEPENDS
libc.hdr.types.jmp_buf
COMPILE_OPTIONS
-O3
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to make these -O3's libc_opt_high_flag after #117638?

Comment on lines +27 to +28
LIBC_INLINE constexpr __UINTPTR_TYPE__ MULTIPLE =
static_cast<__UINTPTR_TYPE__>(6364136223846793005ull);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
LIBC_INLINE constexpr __UINTPTR_TYPE__ MULTIPLE =
static_cast<__UINTPTR_TYPE__>(6364136223846793005ull);
LIBC_INLINE constexpr auto MULTIPLE =
static_cast<__UINTPTR_TYPE__>(6364136223846793005ull);

https://llvm.org/docs/CodingStandards.html#use-auto-type-deduction-to-make-code-more-readable

Comment on lines +18 to +21
__UINTPTR_TYPE__ value_mask =
static_cast<__UINTPTR_TYPE__>(0x3899'f0d3'5005'd953ull);
__UINTPTR_TYPE__ checksum_cookie =
static_cast<__UINTPTR_TYPE__>(0xc7d9'd341'6afc'33f2ull);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
__UINTPTR_TYPE__ value_mask =
static_cast<__UINTPTR_TYPE__>(0x3899'f0d3'5005'd953ull);
__UINTPTR_TYPE__ checksum_cookie =
static_cast<__UINTPTR_TYPE__>(0xc7d9'd341'6afc'33f2ull);
auto value_mask =
static_cast<__UINTPTR_TYPE__>(0x3899'f0d3'5005'd953ull);
auto checksum_cookie =
static_cast<__UINTPTR_TYPE__>(0xc7d9'd341'6afc'33f2ull);

Comment on lines +28 to +29
jmpbuf::value_mask ^= entropy[0];
jmpbuf::checksum_cookie ^= entropy[0];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a previous version of this PR use entropy[1]? Otherwise why is entropy a 2 element array?

asm(R"(
mov %c[rbx](%%rdi), %%rbx
xor %%rbx, %[cookie]
xor %[mask], %%rbx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to modify mask, right? In that case, I'd make mask an output that's also read "+m", rather than an input. Same for setjmp.

},
"LIBC_CONF_SETJMP_FORTIFICATION": {
"value": false,
"doc": "Protect jmp_buf by masking its contents and storing a simple checksum, to make it harder for an attacker to read meaningful information from a jmp_buf or to modify it. This is only supported on x86-64 Linux."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will eventually need to support shadow stacks (part of Intel's CET): https://libc-alpha.sourceware.narkive.com/KcCIyBg9/patch-linux-x86-support-shadow-stack-pointer-in-setjmp-longjmp. It's perhaps worth discussing if we'll want to have 2 or 3 configs for fortification.

For instance, I'd imaging we'd want full fortification or no fortification. But I wonder if shadow stacks make checksumming irrelevant? Hmm...I'll need to think about that more.

"setjmp": {
"LIBC_CONF_SETJMP_FORTIFICATION": {
"value": true,
"doc": "Protect jmp_buf by masking its contents and storing a simple checksum, to make it harder for an attacker to read meaningful information from a jmp_buf or to modify it. This is only supported on x86-64 Linux."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this should be one config. Otherwise, if the user flips one but not the other, then setjmp/longjmp will fail at runtime, right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants