dl-cet.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /* x86 CET initializers function.
  2. Copyright (C) 2018-2019 Free Software Foundation, Inc.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <http://www.gnu.org/licenses/>. */
  14. #include <unistd.h>
  15. #include <errno.h>
  16. #include <libintl.h>
  17. #include <ldsodefs.h>
  18. #include <dl-cet.h>
  19. #include <cet-tunables.h>
  20. /* GNU_PROPERTY_X86_FEATURE_1_IBT and GNU_PROPERTY_X86_FEATURE_1_SHSTK
  21. are defined in <elf.h>, which are only available for C sources.
  22. X86_FEATURE_1_IBT and X86_FEATURE_1_SHSTK are defined in <sysdep.h>
  23. which are available for both C and asm sources. They must match. */
  24. #if GNU_PROPERTY_X86_FEATURE_1_IBT != X86_FEATURE_1_IBT
  25. # error GNU_PROPERTY_X86_FEATURE_1_IBT != X86_FEATURE_1_IBT
  26. #endif
  27. #if GNU_PROPERTY_X86_FEATURE_1_SHSTK != X86_FEATURE_1_SHSTK
  28. # error GNU_PROPERTY_X86_FEATURE_1_SHSTK != X86_FEATURE_1_SHSTK
  29. #endif
  30. static int
  31. dl_cet_mark_legacy_region (struct link_map *l)
  32. {
  33. /* Mark PT_LOAD segments with PF_X in legacy code page bitmap. */
  34. size_t i, phnum = l->l_phnum;
  35. const ElfW(Phdr) *phdr = l->l_phdr;
  36. #ifdef __x86_64__
  37. typedef unsigned long long word_t;
  38. #else
  39. typedef unsigned long word_t;
  40. #endif
  41. unsigned int bits_to_set;
  42. word_t mask_to_set;
  43. #define BITS_PER_WORD (sizeof (word_t) * 8)
  44. #define BITMAP_FIRST_WORD_MASK(start) \
  45. (~((word_t) 0) << ((start) & (BITS_PER_WORD - 1)))
  46. #define BITMAP_LAST_WORD_MASK(nbits) \
  47. (~((word_t) 0) >> (-(nbits) & (BITS_PER_WORD - 1)))
  48. word_t *bitmap = (word_t *) GL(dl_x86_legacy_bitmap)[0];
  49. word_t bitmap_size = GL(dl_x86_legacy_bitmap)[1];
  50. word_t *p;
  51. size_t page_size = GLRO(dl_pagesize);
  52. for (i = 0; i < phnum; i++)
  53. if (phdr[i].p_type == PT_LOAD && (phdr[i].p_flags & PF_X))
  54. {
  55. /* One bit in legacy bitmap represents a page. */
  56. ElfW(Addr) start = (phdr[i].p_vaddr + l->l_addr) / page_size;
  57. ElfW(Addr) len = (phdr[i].p_memsz + page_size - 1) / page_size;
  58. ElfW(Addr) end = start + len;
  59. if ((end / 8) > bitmap_size)
  60. return -EINVAL;
  61. p = bitmap + (start / BITS_PER_WORD);
  62. bits_to_set = BITS_PER_WORD - (start % BITS_PER_WORD);
  63. mask_to_set = BITMAP_FIRST_WORD_MASK (start);
  64. while (len >= bits_to_set)
  65. {
  66. *p |= mask_to_set;
  67. len -= bits_to_set;
  68. bits_to_set = BITS_PER_WORD;
  69. mask_to_set = ~((word_t) 0);
  70. p++;
  71. }
  72. if (len)
  73. {
  74. mask_to_set &= BITMAP_LAST_WORD_MASK (end);
  75. *p |= mask_to_set;
  76. }
  77. }
  78. return 0;
  79. }
  80. /* Check if object M is compatible with CET. */
  81. static void
  82. dl_cet_check (struct link_map *m, const char *program)
  83. {
  84. /* Check how IBT should be enabled. */
  85. unsigned int enable_ibt_type
  86. = GL(dl_x86_feature_1)[1] & ((1 << CET_MAX) - 1);
  87. /* Check how SHSTK should be enabled. */
  88. unsigned int enable_shstk_type
  89. = ((GL(dl_x86_feature_1)[1] >> CET_MAX) & ((1 << CET_MAX) - 1));
  90. /* No legacy object check if both IBT and SHSTK are always on. */
  91. if (enable_ibt_type == CET_ALWAYS_ON
  92. && enable_shstk_type == CET_ALWAYS_ON)
  93. return;
  94. /* Check if IBT is enabled by kernel. */
  95. bool ibt_enabled
  96. = (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0;
  97. /* Check if SHSTK is enabled by kernel. */
  98. bool shstk_enabled
  99. = (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0;
  100. if (ibt_enabled || shstk_enabled)
  101. {
  102. struct link_map *l = NULL;
  103. /* Check if IBT and SHSTK are enabled in object. */
  104. bool enable_ibt = (ibt_enabled
  105. && enable_ibt_type != CET_ALWAYS_OFF);
  106. bool enable_shstk = (shstk_enabled
  107. && enable_shstk_type != CET_ALWAYS_OFF);
  108. if (program)
  109. {
  110. /* Enable IBT and SHSTK only if they are enabled in executable.
  111. NB: IBT and SHSTK may be disabled by environment variable:
  112. GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK
  113. */
  114. enable_ibt &= (HAS_CPU_FEATURE (IBT)
  115. && (enable_ibt_type == CET_ALWAYS_ON
  116. || (m->l_cet & lc_ibt) != 0));
  117. enable_shstk &= (HAS_CPU_FEATURE (SHSTK)
  118. && (enable_shstk_type == CET_ALWAYS_ON
  119. || (m->l_cet & lc_shstk) != 0));
  120. }
  121. /* ld.so is CET-enabled by kernel. But shared objects may not
  122. support IBT nor SHSTK. */
  123. if (enable_ibt || enable_shstk)
  124. {
  125. int res;
  126. unsigned int i;
  127. unsigned int first_legacy, last_legacy;
  128. bool need_legacy_bitmap = false;
  129. i = m->l_searchlist.r_nlist;
  130. while (i-- > 0)
  131. {
  132. /* Check each shared object to see if IBT and SHSTK are
  133. enabled. */
  134. l = m->l_initfini[i];
  135. if (l->l_init_called)
  136. continue;
  137. #ifdef SHARED
  138. /* Skip CET check for ld.so since ld.so is CET-enabled.
  139. CET will be disabled later if CET isn't enabled in
  140. executable. */
  141. if (l == &GL(dl_rtld_map)
  142. || l->l_real == &GL(dl_rtld_map)
  143. || (program && l == m))
  144. continue;
  145. #endif
  146. if (enable_ibt
  147. && enable_ibt_type != CET_ALWAYS_ON
  148. && !(l->l_cet & lc_ibt))
  149. {
  150. /* Remember the first and last legacy objects. */
  151. if (!need_legacy_bitmap)
  152. last_legacy = i;
  153. first_legacy = i;
  154. need_legacy_bitmap = true;
  155. }
  156. /* SHSTK is enabled only if it is enabled in executable as
  157. well as all shared objects. */
  158. enable_shstk &= (enable_shstk_type == CET_ALWAYS_ON
  159. || (l->l_cet & lc_shstk) != 0);
  160. }
  161. if (need_legacy_bitmap)
  162. {
  163. if (GL(dl_x86_legacy_bitmap)[0])
  164. {
  165. /* Change legacy bitmap to writable. */
  166. if (__mprotect ((void *) GL(dl_x86_legacy_bitmap)[0],
  167. GL(dl_x86_legacy_bitmap)[1],
  168. PROT_READ | PROT_WRITE) < 0)
  169. {
  170. mprotect_failure:
  171. if (program)
  172. _dl_fatal_printf ("%s: mprotect legacy bitmap failed\n",
  173. l->l_name);
  174. else
  175. _dl_signal_error (EINVAL, l->l_name, "dlopen",
  176. N_("mprotect legacy bitmap failed"));
  177. }
  178. }
  179. else
  180. {
  181. /* Allocate legacy bitmap. */
  182. int res = dl_cet_allocate_legacy_bitmap
  183. (GL(dl_x86_legacy_bitmap));
  184. if (res != 0)
  185. {
  186. if (program)
  187. _dl_fatal_printf ("%s: legacy bitmap isn't available\n",
  188. l->l_name);
  189. else
  190. _dl_signal_error (EINVAL, l->l_name, "dlopen",
  191. N_("legacy bitmap isn't available"));
  192. }
  193. }
  194. /* Put legacy shared objects in legacy bitmap. */
  195. for (i = first_legacy; i <= last_legacy; i++)
  196. {
  197. l = m->l_initfini[i];
  198. if (l->l_init_called || (l->l_cet & lc_ibt))
  199. continue;
  200. #ifdef SHARED
  201. if (l == &GL(dl_rtld_map)
  202. || l->l_real == &GL(dl_rtld_map)
  203. || (program && l == m))
  204. continue;
  205. #endif
  206. /* If IBT is enabled in executable and IBT isn't enabled
  207. in this shard object, mark PT_LOAD segments with PF_X
  208. in legacy code page bitmap. */
  209. res = dl_cet_mark_legacy_region (l);
  210. if (res != 0)
  211. {
  212. if (program)
  213. _dl_fatal_printf ("%s: failed to mark legacy code region\n",
  214. l->l_name);
  215. else
  216. _dl_signal_error (-res, l->l_name, "dlopen",
  217. N_("failed to mark legacy code region"));
  218. }
  219. }
  220. /* Change legacy bitmap to read-only. */
  221. if (__mprotect ((void *) GL(dl_x86_legacy_bitmap)[0],
  222. GL(dl_x86_legacy_bitmap)[1], PROT_READ) < 0)
  223. goto mprotect_failure;
  224. }
  225. }
  226. bool cet_feature_changed = false;
  227. if (enable_ibt != ibt_enabled || enable_shstk != shstk_enabled)
  228. {
  229. if (!program
  230. && enable_shstk_type != CET_PERMISSIVE)
  231. {
  232. /* When SHSTK is enabled, we can't dlopening a shared
  233. object without SHSTK. */
  234. if (enable_shstk != shstk_enabled)
  235. _dl_signal_error (EINVAL, l->l_name, "dlopen",
  236. N_("shadow stack isn't enabled"));
  237. return;
  238. }
  239. /* Disable IBT and/or SHSTK if they are enabled by kernel, but
  240. disabled in executable or shared objects. */
  241. unsigned int cet_feature = 0;
  242. /* Disable IBT only during program startup. */
  243. if (program && !enable_ibt)
  244. cet_feature |= GNU_PROPERTY_X86_FEATURE_1_IBT;
  245. if (!enable_shstk)
  246. cet_feature |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
  247. int res = dl_cet_disable_cet (cet_feature);
  248. if (res != 0)
  249. {
  250. if (program)
  251. _dl_fatal_printf ("%s: can't disable CET\n", program);
  252. else
  253. _dl_signal_error (-res, l->l_name, "dlopen",
  254. N_("can't disable CET"));
  255. }
  256. /* Clear the disabled bits in dl_x86_feature_1. */
  257. GL(dl_x86_feature_1)[0] &= ~cet_feature;
  258. cet_feature_changed = true;
  259. }
  260. #ifdef SHARED
  261. if (program
  262. && (!shstk_enabled
  263. || enable_shstk_type != CET_PERMISSIVE)
  264. && (ibt_enabled || shstk_enabled))
  265. {
  266. /* Lock CET if IBT or SHSTK is enabled in executable. Don't
  267. lock CET if SHSTK is enabled permissively. */
  268. int res = dl_cet_lock_cet ();
  269. if (res != 0)
  270. _dl_fatal_printf ("%s: can't lock CET\n", program);
  271. cet_feature_changed = true;
  272. }
  273. #endif
  274. if (cet_feature_changed)
  275. {
  276. unsigned int feature_1 = 0;
  277. if (enable_ibt)
  278. feature_1 |= GNU_PROPERTY_X86_FEATURE_1_IBT;
  279. if (enable_shstk)
  280. feature_1 |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
  281. struct pthread *self = THREAD_SELF;
  282. THREAD_SETMEM (self, header.feature_1, feature_1);
  283. }
  284. }
  285. }
  286. void
  287. _dl_cet_open_check (struct link_map *l)
  288. {
  289. dl_cet_check (l, NULL);
  290. }
  291. #ifdef SHARED
  292. # ifndef LINKAGE
  293. # define LINKAGE
  294. # endif
  295. LINKAGE
  296. void
  297. _dl_cet_check (struct link_map *main_map, const char *program)
  298. {
  299. dl_cet_check (main_map, program);
  300. }
  301. #endif /* SHARED */