1/* Linux/x86-64 CET initializers function.
2 Copyright (C) 2023-2024 Free Software Foundation, Inc.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
17
18#include <sys/prctl.h>
19#include <asm/prctl.h>
20#include <features-offsets.h>
21
22static __always_inline int
23dl_cet_disable_cet (unsigned int cet_feature)
24{
25 if (cet_feature != GNU_PROPERTY_X86_FEATURE_1_SHSTK)
26 return -1;
27 long long int kernel_feature = ARCH_SHSTK_SHSTK;
28 return (int) INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_DISABLE,
29 kernel_feature);
30}
31
32static __always_inline int
33dl_cet_lock_cet (unsigned int cet_feature)
34{
35 if (cet_feature != GNU_PROPERTY_X86_FEATURE_1_SHSTK)
36 return -1;
37 /* Lock all SHSTK features. */
38 long long int kernel_feature = -1;
39 return (int) INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_LOCK,
40 kernel_feature);
41}
42
43static __always_inline unsigned int
44dl_cet_get_cet_status (void)
45{
46 unsigned long long kernel_feature;
47 unsigned int status = 0;
48 if (INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_STATUS,
49 &kernel_feature) == 0)
50 {
51 if ((kernel_feature & ARCH_SHSTK_SHSTK) != 0)
52 status = GNU_PROPERTY_X86_FEATURE_1_SHSTK;
53 }
54 return status;
55}
56
57static __always_inline bool
58dl_cet_ibt_enabled (void)
59{
60 unsigned int feature_1 = THREAD_GETMEM (THREAD_SELF,
61 header.feature_1);
62 return (feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0;
63}
64
65/* Enable shadow stack with a macro to avoid shadow stack underflow. */
66#define ENABLE_X86_CET(cet_feature) \
67 if ((cet_feature & GNU_PROPERTY_X86_FEATURE_1_SHSTK)) \
68 { \
69 long long int kernel_feature = ARCH_SHSTK_SHSTK; \
70 INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_ENABLE, \
71 kernel_feature); \
72 }
73
74#define X86_STRINGIFY_1(x) #x
75#define X86_STRINGIFY(x) X86_STRINGIFY_1 (x)
76
77/* Enable shadow stack before calling _dl_init if it is enabled in
78 GL(dl_x86_feature_1). Call _dl_setup_x86_features to setup shadow
79 stack. */
80#define RTLD_START_ENABLE_X86_FEATURES \
81"\
82 # Check if shadow stack is enabled in GL(dl_x86_feature_1).\n\
83 movl _rtld_local+" X86_STRINGIFY (RTLD_GLOBAL_DL_X86_FEATURE_1_OFFSET) "(%rip), %edx\n\
84 testl $" X86_STRINGIFY (X86_FEATURE_1_SHSTK) ", %edx\n\
85 jz 1f\n\
86 # Enable shadow stack if enabled in GL(dl_x86_feature_1).\n\
87 movl $" X86_STRINGIFY (ARCH_SHSTK_SHSTK) ", %esi\n\
88 movl $" X86_STRINGIFY (ARCH_SHSTK_ENABLE) ", %edi\n\
89 movl $" X86_STRINGIFY (__NR_arch_prctl) ", %eax\n\
90 syscall\n\
911:\n\
92 # Pass GL(dl_x86_feature_1) to _dl_cet_setup_features.\n\
93 movl %edx, %edi\n\
94 # Align stack for the _dl_cet_setup_features call.\n\
95 and $-16, %" RSP_LP "\n\
96 call _dl_cet_setup_features\n\
97 # Restore %rax and %rsp from %r12 and %r13.\n\
98 mov %" R12_LP ", %" RAX_LP "\n\
99 mov %" R13_LP ", %" RSP_LP "\n\
100"
101

source code of glibc/sysdeps/unix/sysv/linux/x86_64/dl-cet.h