1 /* x86 CET initializers function.
2 Copyright (C) 2018-2021 Free Software Foundation, Inc.
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.
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.
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/>. */
24 /* GNU_PROPERTY_X86_FEATURE_1_IBT and GNU_PROPERTY_X86_FEATURE_1_SHSTK
25 are defined in <elf.h>, which are only available for C sources.
26 X86_FEATURE_1_IBT and X86_FEATURE_1_SHSTK are defined in <sysdep.h>
27 which are available for both C and asm sources. They must match. */
28 #if GNU_PROPERTY_X86_FEATURE_1_IBT != X86_FEATURE_1_IBT
29 # error GNU_PROPERTY_X86_FEATURE_1_IBT != X86_FEATURE_1_IBT
31 #if GNU_PROPERTY_X86_FEATURE_1_SHSTK != X86_FEATURE_1_SHSTK
32 # error GNU_PROPERTY_X86_FEATURE_1_SHSTK != X86_FEATURE_1_SHSTK
35 /* Check if object M is compatible with CET. */
38 dl_cet_check (struct link_map
*m
, const char *program
)
40 /* Check how IBT should be enabled. */
41 enum dl_x86_cet_control enable_ibt_type
42 = GL(dl_x86_feature_control
).ibt
;
43 /* Check how SHSTK should be enabled. */
44 enum dl_x86_cet_control enable_shstk_type
45 = GL(dl_x86_feature_control
).shstk
;
47 /* No legacy object check if both IBT and SHSTK are always on. */
48 if (enable_ibt_type
== cet_always_on
49 && enable_shstk_type
== cet_always_on
)
51 THREAD_SETMEM (THREAD_SELF
, header
.feature_1
, GL(dl_x86_feature_1
));
55 /* Check if IBT is enabled by kernel. */
57 = (GL(dl_x86_feature_1
) & GNU_PROPERTY_X86_FEATURE_1_IBT
) != 0;
58 /* Check if SHSTK is enabled by kernel. */
60 = (GL(dl_x86_feature_1
) & GNU_PROPERTY_X86_FEATURE_1_SHSTK
) != 0;
62 if (ibt_enabled
|| shstk_enabled
)
64 struct link_map
*l
= NULL
;
65 unsigned int ibt_legacy
= 0, shstk_legacy
= 0;
66 bool found_ibt_legacy
= false, found_shstk_legacy
= false;
68 /* Check if IBT and SHSTK are enabled in object. */
69 bool enable_ibt
= (ibt_enabled
70 && enable_ibt_type
!= cet_always_off
);
71 bool enable_shstk
= (shstk_enabled
72 && enable_shstk_type
!= cet_always_off
);
75 /* Enable IBT and SHSTK only if they are enabled in executable.
76 NB: IBT and SHSTK may be disabled by environment variable:
78 GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK
80 enable_ibt
&= (CPU_FEATURE_USABLE (IBT
)
81 && (enable_ibt_type
== cet_always_on
82 || (m
->l_x86_feature_1_and
83 & GNU_PROPERTY_X86_FEATURE_1_IBT
) != 0));
84 enable_shstk
&= (CPU_FEATURE_USABLE (SHSTK
)
85 && (enable_shstk_type
== cet_always_on
86 || (m
->l_x86_feature_1_and
87 & GNU_PROPERTY_X86_FEATURE_1_SHSTK
) != 0));
90 /* ld.so is CET-enabled by kernel. But shared objects may not
91 support IBT nor SHSTK. */
92 if (enable_ibt
|| enable_shstk
)
96 i
= m
->l_searchlist
.r_nlist
;
99 /* Check each shared object to see if IBT and SHSTK are
101 l
= m
->l_initfini
[i
];
103 if (l
->l_init_called
)
107 /* Skip CET check for ld.so since ld.so is CET-enabled.
108 CET will be disabled later if CET isn't enabled in
110 if (l
== &GL(dl_rtld_map
)
111 || l
->l_real
== &GL(dl_rtld_map
)
112 || (program
&& l
== m
))
116 /* IBT is enabled only if it is enabled in executable as
117 well as all shared objects. */
118 enable_ibt
&= (enable_ibt_type
== cet_always_on
119 || (l
->l_x86_feature_1_and
120 & GNU_PROPERTY_X86_FEATURE_1_IBT
) != 0);
121 if (!found_ibt_legacy
&& enable_ibt
!= ibt_enabled
)
123 found_ibt_legacy
= true;
127 /* SHSTK is enabled only if it is enabled in executable as
128 well as all shared objects. */
129 enable_shstk
&= (enable_shstk_type
== cet_always_on
130 || (l
->l_x86_feature_1_and
131 & GNU_PROPERTY_X86_FEATURE_1_SHSTK
) != 0);
132 if (enable_shstk
!= shstk_enabled
)
134 found_shstk_legacy
= true;
140 bool cet_feature_changed
= false;
142 if (enable_ibt
!= ibt_enabled
|| enable_shstk
!= shstk_enabled
)
146 if (enable_ibt_type
!= cet_permissive
)
148 /* When IBT is enabled, we cannot dlopen a shared
149 object without IBT. */
150 if (found_ibt_legacy
)
152 m
->l_initfini
[ibt_legacy
]->l_name
,
154 N_("rebuild shared object with IBT support enabled"));
157 if (enable_shstk_type
!= cet_permissive
)
159 /* When SHSTK is enabled, we cannot dlopen a shared
160 object without SHSTK. */
161 if (found_shstk_legacy
)
163 m
->l_initfini
[shstk_legacy
]->l_name
,
165 N_("rebuild shared object with SHSTK support enabled"));
168 if (enable_ibt_type
!= cet_permissive
169 && enable_shstk_type
!= cet_permissive
)
173 /* Disable IBT and/or SHSTK if they are enabled by kernel, but
174 disabled in executable or shared objects. */
175 unsigned int cet_feature
= 0;
178 cet_feature
|= GNU_PROPERTY_X86_FEATURE_1_IBT
;
180 cet_feature
|= GNU_PROPERTY_X86_FEATURE_1_SHSTK
;
182 int res
= dl_cet_disable_cet (cet_feature
);
186 _dl_fatal_printf ("%s: can't disable CET\n", program
);
189 if (found_ibt_legacy
)
190 l
= m
->l_initfini
[ibt_legacy
];
192 l
= m
->l_initfini
[shstk_legacy
];
193 _dl_signal_error (-res
, l
->l_name
, "dlopen",
194 N_("can't disable CET"));
198 /* Clear the disabled bits in dl_x86_feature_1. */
199 GL(dl_x86_feature_1
) &= ~cet_feature
;
201 cet_feature_changed
= true;
205 if (program
&& (ibt_enabled
|| shstk_enabled
))
208 || enable_ibt_type
!= cet_permissive
)
210 || enable_shstk_type
!= cet_permissive
))
212 /* Lock CET if IBT or SHSTK is enabled in executable unless
213 IBT or SHSTK is enabled permissively. */
214 int res
= dl_cet_lock_cet ();
216 _dl_fatal_printf ("%s: can't lock CET\n", program
);
219 /* Set feature_1 if IBT or SHSTK is enabled in executable. */
220 cet_feature_changed
= true;
224 if (cet_feature_changed
)
226 unsigned int feature_1
= 0;
228 feature_1
|= GNU_PROPERTY_X86_FEATURE_1_IBT
;
230 feature_1
|= GNU_PROPERTY_X86_FEATURE_1_SHSTK
;
231 struct pthread
*self
= THREAD_SELF
;
232 THREAD_SETMEM (self
, header
.feature_1
, feature_1
);
238 _dl_cet_open_check (struct link_map
*l
)
240 dl_cet_check (l
, NULL
);
251 _dl_cet_check (struct link_map
*main_map
, const char *program
)
253 dl_cet_check (main_map
, program
);