x86: Add ENDBR at function entries

Intel Control-flow Enforcement Technology (CET):

https://software.intel.com/en-us/articles/intel-sdm

contains shadow stack (SHSTK) and indirect branch tracking (IBT). When
CET is enabled, ELF object files must be marked with .note.gnu.property
section. Also when IBT is enabled, all indirect branch targets must
start with ENDBR instruction which is NOP on non-CET processors.

This fixes:

https://gitlab.freedesktop.org/glvnd/libglvnd/issues/202
This commit is contained in:
H.J. Lu 2020-02-21 21:28:29 +00:00 committed by Matt Turner
parent cb7b1fb019
commit f96f6bde04
6 changed files with 21 additions and 4 deletions

View file

@ -39,4 +39,14 @@
extern char public_entry_start[];
extern char public_entry_end[];
#ifdef __CET__
#ifdef __x86_64__
#define ENDBR "endbr64\n\t"
#else
#define ENDBR "endbr32\n\t"
#endif
#else
#define ENDBR
#endif
#endif // ENTRY_COMMON_H

View file

@ -58,6 +58,7 @@ __asm__(".balign " U_STRINGIFY(GLDISPATCH_PAGE_SIZE) "\n"
#ifdef __ILP32__
#define STUB_ASM_CODE(slot) \
ENDBR \
"movq _glapi_tls_Current@GOTTPOFF(%rip), %rax\n\t" \
"movl %fs:(%rax), %r11d\n\t" \
"movl 4*" slot "(%r11d), %r11d\n\t" \
@ -66,6 +67,7 @@ __asm__(".balign " U_STRINGIFY(GLDISPATCH_PAGE_SIZE) "\n"
#else // __ILP32__
#define STUB_ASM_CODE(slot) \
ENDBR \
"movq _glapi_tls_Current@GOTTPOFF(%rip), %rax\n\t" \
"movq %fs:(%rax), %r11\n\t" \
"jmp *(8 * " slot ")(%r11)"

View file

@ -69,6 +69,7 @@ __asm__(".balign " U_STRINGIFY(GLDISPATCH_PAGE_SIZE) "\n"
* assume that they're within 2GB of %rip.
*/
#define STUB_ASM_CODE(slot) \
ENDBR \
"movq _glapi_Current@GOTPCREL(%rip), %rax\n\t" \
"movq (%rax), %rax\n" \
"test %rax, %rax\n\t" \

View file

@ -56,6 +56,7 @@ __asm__(".balign " U_STRINGIFY(GLDISPATCH_PAGE_SIZE) "\n"
func ":\n"
#define STUB_ASM_CODE(slot) \
ENDBR \
"call 1f\n\t" \
"1:\n\t" \
"popl %eax\n\t" \

View file

@ -56,6 +56,7 @@ __asm__(".balign " U_STRINGIFY(GLDISPATCH_PAGE_SIZE) "\n"
func ":\n"
#define STUB_ASM_CODE(slot) \
ENDBR \
"call 1f\n" \
"1:\n" \
"popl %ecx\n" \

View file

@ -44,6 +44,7 @@ static void patch_x86_64(char *writeEntry, const char *execEntry,
// that it's the right size for either build.
uint64_t incrementAddr = (uint64_t) ((uintptr_t) incrementPtr);
const char tmpl[] = {
0xf3, 0x0f, 0x1e, 0xfa, // endbr64
0xa1, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12, // movabs 0x123456789abcdef0, %eax
0x83, 0xc0, 0x01, // add $0x1,%eax
0xa3, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12, // movabs %eax,0x123456789abcdef0
@ -55,8 +56,8 @@ static void patch_x86_64(char *writeEntry, const char *execEntry,
}
memcpy(writeEntry, tmpl, sizeof(tmpl));
memcpy(writeEntry + 1, &incrementAddr, sizeof(incrementAddr));
memcpy(writeEntry + 13, &incrementAddr, sizeof(incrementAddr));
memcpy(writeEntry + 5, &incrementAddr, sizeof(incrementAddr));
memcpy(writeEntry + 17, &incrementAddr, sizeof(incrementAddr));
#else
assert(0); // Should not be calling this
@ -70,6 +71,7 @@ static void patch_x86(char *writeEntry, const char *execEntry,
#if defined(__i386__)
uintptr_t *p;
char tmpl[] = {
0xf3, 0x0f, 0x1e, 0xfb, // endbr32
0xa1, 0x0, 0x0, 0x0, 0x0, // mov 0x0, %eax
0x83, 0xc0, 0x01, // add $0x1, %eax
0xa3, 0x0, 0x0, 0x0, 0x0, // mov %eax, 0x0
@ -83,10 +85,10 @@ static void patch_x86(char *writeEntry, const char *execEntry,
}
// Patch the address of the incrementPtr variable.
p = (uintptr_t *)&tmpl[1];
p = (uintptr_t *)&tmpl[5];
*p = (uintptr_t) incrementPtr;
p = (uintptr_t *)&tmpl[9];
p = (uintptr_t *)&tmpl[13];
*p = (uintptr_t) incrementPtr;
memcpy(writeEntry, tmpl, sizeof(tmpl));