Skip to content

Commit ef9ccdb

Browse files
fix and rebase
1 parent e6ce912 commit ef9ccdb

File tree

5 files changed

+184
-156
lines changed

5 files changed

+184
-156
lines changed

libc/src/setjmp/linux/checksum.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ void initialize() {
2323
union {
2424
struct {
2525
__UINTPTR_TYPE__ entropy0;
26-
__UINT64_TYPE__ entropy1;
26+
__UINTPTR_TYPE__ entropy1;
2727
};
28-
char buffer[sizeof(__UINTPTR_TYPE__) + sizeof(__UINT64_TYPE__)];
28+
char buffer[sizeof(__UINTPTR_TYPE__) * 2];
2929
};
3030
syscall_impl<long>(SYS_getrandom, buffer, sizeof(buffer), 0);
3131
// add in additional entropy

libc/src/setjmp/x86_64/checksum.def

Lines changed: 0 additions & 34 deletions
This file was deleted.

libc/src/setjmp/x86_64/common.h

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
//===-- Common macros for jmpbuf -------------------------------*- C++ -*-===//
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+
#ifndef LIBC_SRC_SETJMP_X86_64_COMMON_H
10+
#define LIBC_SRC_SETJMP_X86_64_COMMON_H
11+
12+
#include "include/llvm-libc-macros/offsetof-macro.h"
13+
14+
//===----------------------------------------------------------------------===//
15+
// Architecture specific macros for x86_64.
16+
//===----------------------------------------------------------------------===//
17+
18+
#ifdef __i386__
19+
#define RET_REG eax
20+
#define BASE_REG ecx
21+
#define MUL_REG edx
22+
#define STACK_REG esp
23+
#define PC_REG eip
24+
#define NORMAL_STORE_REGS ebx, esi, edi, ebp
25+
#define STORE_ALL_REGS(M) M(ebx) M(esi) M(edi) M(ebp)
26+
#define LOAD_ALL_REGS(M) M(ebx) M(esi) M(edi) M(ebp) M(esp)
27+
#define DECLARE_ALL_REGS(M) M(ebx), M(esi), M(edi), M(ebp), M(esp), M(eip)
28+
#define LOAD_BASE() "mov 4(%%esp), %%ecx\n\t"
29+
#define CALCULATE_RETURN_VALUE() \
30+
"mov 0x8(%%esp), %%eax" \
31+
"cmp $0x1, %%eax\n\t" \
32+
"adc $0x0, %%eax\n\t"
33+
#else
34+
#define RET_REG rax
35+
#define BASE_REG rdi
36+
#define MUL_REG rdx
37+
#define STACK_REG rsp
38+
#define PC_REG rip
39+
#define STORE_ALL_REGS(M) M(rbx) M(rbp) M(r12) M(r13) M(r14) M(r15)
40+
#define LOAD_ALL_REGS(M) M(rbx) M(rbp) M(r12) M(r13) M(r14) M(r15) M(rsp)
41+
#define DECLARE_ALL_REGS(M) \
42+
M(rbx), M(rbp), M(r12), M(r13), M(r14), M(r15), M(rsp), M(rip)
43+
#define LOAD_BASE()
44+
#define CALCULATE_RETURN_VALUE() \
45+
"cmp $0x1, %%esi\n\t" \
46+
"adc $0x0, %%esi\n\t" \
47+
"mov %%rsi, %%rax\n\t"
48+
#endif
49+
50+
//===----------------------------------------------------------------------===//
51+
// Utility macros.
52+
//===----------------------------------------------------------------------===//
53+
54+
#define _STR(X) #X
55+
#define STR(X) _STR(X)
56+
#define REG(X) "%%" STR(X)
57+
#define XOR(X, Y) "xor " REG(X) ", " REG(Y) "\n\t"
58+
#define MOV(X, Y) "mov " REG(X) ", " REG(Y) "\n\t"
59+
#define STORE(R, OFFSET, BASE) \
60+
"mov " REG(R) ", %c[" STR(OFFSET) "](" REG(BASE) ")\n\t"
61+
#define LOAD(OFFSET, BASE, R) \
62+
"mov %c[" STR(OFFSET) "](" REG(BASE) "), " REG(R) "\n\t"
63+
#define COMPUTE_STACK_TO_RET() \
64+
"lea " STR(__SIZEOF_POINTER__) "(" REG(STACK_REG) "), " REG(RET_REG) "\n\t"
65+
#define COMPUTE_PC_TO_RET() "mov (" REG(STACK_REG) "), " REG(RET_REG) "\n\t"
66+
#define RETURN() "ret\n\t"
67+
#define DECLARE_OFFSET(X) [X] "i"(offsetof(__jmp_buf, X))
68+
#define CMP_MEM_REG(OFFSET, BASE, DST) \
69+
"cmp %c[" STR(OFFSET) "](" REG(BASE) "), " REG(DST) "\n\t"
70+
#define JNE_LABEL(LABEL) "jne " STR(LABEL) "\n\t"
71+
72+
//===----------------------------------------------------------------------===//
73+
// Checksum related macros.
74+
//===----------------------------------------------------------------------===//
75+
// For now, the checksum is computed with a simple multiply-xor-rotation
76+
// algorithm. The pesudo code is as follows:
77+
//
78+
// def checksum(x, acc):
79+
// masked = x ^ MASK
80+
// high, low = full_multiply(masked, acc)
81+
// return rotate(high ^ low, ROTATION)
82+
//
83+
// Similar other multiplication-based hashing, zero inputs
84+
// for the `full_multiply` function may pollute the checksum with zero.
85+
// However, user inputs are always masked where the initial ACC amd MASK are
86+
// generated with random entropy and ROTATION is a fixed prime number. It should
87+
// be of a ultra-low chance for masked or acc being zero given a good quality of
88+
// system-level entropy.
89+
//
90+
// Notice that on x86-64, one-operand form of `mul` instruction:
91+
// mul %rdx
92+
// has the following effect:
93+
// RAX = LOW(RDX * RAX)
94+
// RDX = HIGH(RDX * RAX)
95+
//===----------------------------------------------------------------------===//
96+
97+
#if LIBC_COPT_SETJMP_FORTIFICATION
98+
#define XOR_MASK(X) "xor %[value_mask], " REG(X) "\n\t"
99+
#define MUL(X) "mul " REG(X) "\n\t"
100+
#define ROTATE(X) "rol $%c[rotation], " REG(X) "\n\t"
101+
#define ACCUMULATE_CHECKSUM() MUL(MUL_REG) XOR(RET_REG, MUL_REG) ROTATE(MUL_REG)
102+
103+
#define LOAD_CHKSUM_STATE_REGS() "mov %[checksum_cookie], " REG(MUL_REG) "\n\t"
104+
105+
#define STORE_REG(SRC) \
106+
MOV(SRC, RET_REG) XOR_MASK(RET_REG) STORE(RET_REG, SRC, BASE_REG)
107+
#define STORE_STACK() \
108+
COMPUTE_STACK_TO_RET() \
109+
XOR_MASK(RET_REG) \
110+
STORE(RET_REG, STACK_REG, BASE_REG)
111+
112+
#define STORE_PC() \
113+
COMPUTE_PC_TO_RET() \
114+
XOR_MASK(RET_REG) \
115+
STORE(RET_REG, PC_REG, BASE_REG)
116+
117+
#define STORE_CHECKSUM() STORE(MUL_REG, __chksum, BASE_REG)
118+
#define EXAMINE_CHECKSUM() \
119+
LOAD(PC_REG, BASE_REG, RET_REG) \
120+
ACCUMULATE_CHECKSUM() \
121+
CMP_MEM_REG(__chksum, BASE_REG, MUL_REG) \
122+
JNE_LABEL(__libc_jmpbuf_corruption)
123+
124+
#define RESTORE_PC() \
125+
LOAD(PC_REG, BASE_REG, BASE_REG) \
126+
XOR_MASK(BASE_REG) \
127+
"jmp *" REG(BASE_REG)
128+
#define RESTORE_REG(SRC) \
129+
LOAD(SRC, BASE_REG, RET_REG) \
130+
MOV(RET_REG, SRC) \
131+
ACCUMULATE_CHECKSUM() XOR_MASK(SRC)
132+
#else
133+
#define XOR_MASK(X)
134+
#define ACCUMULATE_CHECKSUM()
135+
#define LOAD_CHKSUM_STATE_REGS()
136+
#define STORE_REG(SRC) STORE(SRC, SRC, BASE_REG)
137+
#define STORE_STACK() COMPUTE_STACK_TO_RET() STORE(RET_REG, STACK_REG, BASE_REG)
138+
#define STORE_PC() COMPUTE_PC_TO_RET() STORE(RET_REG, PC_REG, BASE_REG)
139+
#define STORE_CHECKSUM()
140+
#define EXAMINE_CHECKSUM()
141+
#define RESTORE_PC() "jmp *%c[" STR(PC_REG) "](" REG(BASE_REG) ")\n\t"
142+
#define RESTORE_REG(SRC) LOAD(SRC, BASE_REG, SRC)
143+
#endif
144+
145+
#define STORE_REG_ACCUMULATE(SRC) STORE_REG(SRC) ACCUMULATE_CHECKSUM()
146+
147+
#endif // LIBC_SRC_SETJMP_X86_64_COMMON_H

libc/src/setjmp/x86_64/longjmp.cpp

Lines changed: 17 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -7,86 +7,44 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "src/setjmp/longjmp.h"
10-
#include "include/llvm-libc-macros/offsetof-macro.h"
1110
#include "src/__support/common.h"
1211
#include "src/__support/macros/config.h"
1312

14-
#if LIBC_COPT_SETJMP_FORTIFICATION
15-
#include "src/setjmp/checksum.h"
16-
#endif
17-
1813
#if !defined(LIBC_TARGET_ARCH_IS_X86)
1914
#error "Invalid file include"
2015
#endif
2116

22-
namespace LIBC_NAMESPACE_DECL {
23-
24-
#define CALCULATE_RETURN_VALUE() \
25-
"cmpl $0x1, %%esi\n\t" \
26-
"adcl $0x0, %%esi\n\t" \
27-
"movq %%rsi, %%rax\n\t"
17+
#include "src/setjmp/x86_64/common.h"
2818

2919
#if LIBC_COPT_SETJMP_FORTIFICATION
30-
#include "src/setjmp/x86_64/checksum.def"
31-
32-
// clang-format off
33-
#define RESTORE_REG(DST) \
34-
"movq %c[" #DST "](%%rdi), %%rax\n\t" \
35-
"movq %%rax, %%" #DST "\n\t" \
36-
"xor %[mask], %%" #DST "\n\t" \
37-
ACCUMULATE_CHECKSUM()
38-
39-
#define RESTORE_RIP() \
40-
"movq %c[rip](%%rdi), %%rax\n\t" \
41-
"xor %%rax, %[mask]\n\t" \
42-
ACCUMULATE_CHECKSUM() \
43-
"cmp %c[__chksum](%%rdi), %%rdx\n\t" \
44-
"jne __libc_jmpbuf_corruption\n\t" \
45-
CALCULATE_RETURN_VALUE() \
46-
"jmp *%[mask]\n\t"
47-
// clang-format on
48-
#else
49-
#define LOAD_CHKSUM_STATE_REGISTERS()
50-
#define RESTORE_REG(DST) "movq %c[" #DST "](%%rdi), %%" #DST "\n\t"
51-
#define RESTORE_RIP() \
52-
CALCULATE_RETURN_VALUE() \
53-
"jmpq *%c[rip](%%rdi)\n\t"
20+
#include "src/setjmp/checksum.h"
5421
#endif
5522

56-
[[gnu::naked]] LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf, int)) {
57-
// use registers to make sure values propagate correctly across the asm blocks
58-
[[maybe_unused]] register __UINTPTR_TYPE__ mask asm("rcx");
59-
[[maybe_unused]] register __UINT64_TYPE__ checksum asm("rdx");
23+
namespace LIBC_NAMESPACE_DECL {
6024

61-
LOAD_CHKSUM_STATE_REGISTERS()
25+
[[gnu::naked]] LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf, int)) {
6226
asm volatile(
6327
// clang-format off
64-
RESTORE_REG(rbx)
65-
RESTORE_REG(rbp)
66-
RESTORE_REG(r12)
67-
RESTORE_REG(r13)
68-
RESTORE_REG(r14)
69-
RESTORE_REG(r15)
70-
RESTORE_REG(rsp)
71-
RESTORE_RIP()
28+
LOAD_BASE()
29+
LOAD_CHKSUM_STATE_REGS()
30+
LOAD_ALL_REGS(RESTORE_REG)
31+
EXAMINE_CHECKSUM()
32+
CALCULATE_RETURN_VALUE()
33+
RESTORE_PC()
7234
// clang-format on
73-
: /* outputs */
35+
:
7436
#if LIBC_COPT_SETJMP_FORTIFICATION
75-
[mask] "+r"(mask), [checksum] "+r"(checksum)
37+
[value_mask] "=m"(jmpbuf::value_mask)
7638
#endif
77-
: /* inputs */
78-
[rbx] "i"(offsetof(__jmp_buf, rbx)), [rbp] "i"(offsetof(__jmp_buf, rbp)),
79-
[r12] "i"(offsetof(__jmp_buf, r12)), [r13] "i"(offsetof(__jmp_buf, r13)),
80-
[r14] "i"(offsetof(__jmp_buf, r14)), [r15] "i"(offsetof(__jmp_buf, r15)),
81-
[rsp] "i"(offsetof(__jmp_buf, rsp)),
82-
[rip] "i"(offsetof(__jmp_buf, rip))
39+
: DECLARE_ALL_REGS(DECLARE_OFFSET)
8340
#if LIBC_COPT_SETJMP_FORTIFICATION
84-
// clang-format off
41+
// clang-format off
8542
,[rotation] "i"(jmpbuf::ROTATION)
8643
,[__chksum] "i"(offsetof(__jmp_buf, __chksum))
87-
// clang-format on
44+
,[checksum_cookie] "m"(jmpbuf::checksum_cookie)
45+
8846
#endif
89-
: "rax", "rsi");
47+
: STR(RET_REG), STR(BASE_REG), STR(MUL_REG));
9048
}
9149

9250
} // namespace LIBC_NAMESPACE_DECL

0 commit comments

Comments
 (0)