tst-sprintf-fortify-rdonly.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /* Testcase for BZ 30932.
  2. Copyright (C) 2023-2026 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  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. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #include <errno.h>
  16. #include <setjmp.h>
  17. #include <stdbool.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <sys/resource.h>
  21. #include <unistd.h>
  22. #include <support/check.h>
  23. #include <support/support.h>
  24. #include <support/temp_file.h>
  25. #include <support/xdlfcn.h>
  26. static sigjmp_buf chk_fail_buf;
  27. static volatile int ret;
  28. static bool chk_fail_ok;
  29. static void
  30. handler (int sig)
  31. {
  32. if (chk_fail_ok)
  33. {
  34. chk_fail_ok = false;
  35. longjmp (chk_fail_buf, 1);
  36. }
  37. else
  38. _exit (127);
  39. }
  40. #define FORTIFY_FAIL \
  41. do { printf ("Failure on line %d\n", __LINE__); ret = 1; } while (0)
  42. #define CHK_FAIL_START \
  43. chk_fail_ok = true; \
  44. if (! sigsetjmp (chk_fail_buf, 1)) \
  45. {
  46. #define CHK_FAIL_END \
  47. chk_fail_ok = false; \
  48. FORTIFY_FAIL; \
  49. }
  50. static const char *str2 = "F";
  51. static char writeable_format[10] = "%s";
  52. static char relro_format[10] __attribute__ ((section (".data.rel.ro"))) =
  53. "%s%n%s%n";
  54. extern void init_writable (void);
  55. extern int sprintf_writable (int *, int *);
  56. extern int sprintf_relro (int *, int *);
  57. extern int sprintf_writable_malloc (int *, int *);
  58. #define str(__x) # __x
  59. void (*init_writable_dlopen)(void);
  60. int (*sprintf_writable_dlopen)(int *, int *);
  61. int (*sprintf_rdonly_dlopen)(int *, int *);
  62. int (*sprintf_writable_malloc_dlopen)(int *, int *);
  63. static int
  64. do_test (void)
  65. {
  66. set_fortify_handler (handler);
  67. {
  68. void *h = xdlopen ("tst-sprintf-fortify-rdonly-dlopen.so", RTLD_NOW);
  69. init_writable_dlopen = xdlsym (h, str(init_writable));
  70. sprintf_writable_dlopen = xdlsym (h, str(sprintf_writable));
  71. sprintf_rdonly_dlopen = xdlsym (h, str(sprintf_relro));
  72. sprintf_writable_malloc_dlopen = xdlsym (h, str(sprintf_writable_malloc));
  73. }
  74. struct rlimit rl;
  75. int max_fd = 24;
  76. if (getrlimit (RLIMIT_NOFILE, &rl) == -1)
  77. FAIL_EXIT1 ("getrlimit (RLIMIT_NOFILE): %m");
  78. max_fd = (rl.rlim_cur < max_fd ? rl.rlim_cur : max_fd);
  79. rl.rlim_cur = max_fd;
  80. if (setrlimit (RLIMIT_NOFILE, &rl) == -1)
  81. FAIL_EXIT1 ("setrlimit (RLIMIT_NOFILE): %m");
  82. /* Exhaust the file descriptor limit with temporary files. */
  83. int nfiles = 0;
  84. for (; nfiles < max_fd; nfiles++)
  85. {
  86. int fd = create_temp_file ("tst-sprintf-fortify-rdonly-.", NULL);
  87. if (fd == -1)
  88. {
  89. if (errno != EMFILE)
  90. FAIL_EXIT1 ("create_temp_file: %m");
  91. break;
  92. }
  93. }
  94. TEST_VERIFY_EXIT (nfiles != 0);
  95. strcpy (writeable_format + 2, "%n%s%n");
  96. init_writable ();
  97. init_writable_dlopen ();
  98. /* writeable_format is at a writable part of .bss segment, so libc should be
  99. able to check it without resorting to procfs. */
  100. {
  101. char buf[128];
  102. int n1;
  103. int n2;
  104. CHK_FAIL_START
  105. sprintf (buf, writeable_format, str2, &n1, str2, &n2);
  106. CHK_FAIL_END
  107. }
  108. /* Same as before, but from an library. */
  109. {
  110. int n1;
  111. int n2;
  112. CHK_FAIL_START
  113. sprintf_writable (&n1, &n2);
  114. CHK_FAIL_END
  115. }
  116. {
  117. int n1;
  118. int n2;
  119. CHK_FAIL_START
  120. sprintf_writable_dlopen (&n1, &n2);
  121. CHK_FAIL_END
  122. }
  123. /* relro_format is at a readonly part of .bss segment, so '%n' in format input
  124. should not trigger a fortify failure. */
  125. {
  126. char buf[128];
  127. int n1;
  128. int n2;
  129. if (sprintf (buf, relro_format, str2, &n1, str2, &n2) != 2
  130. || n1 != 1 || n2 != 2)
  131. FAIL_EXIT1 ("sprintf failed: %s %d %d", buf, n1, n2);
  132. }
  133. /* Same as before, but from an library. */
  134. {
  135. int n1;
  136. int n2;
  137. if (sprintf_relro (&n1, &n2) != 2 || n1 != 1 || n2 != 2)
  138. FAIL_EXIT1 ("sprintf failed: %d %d", n1, n2);
  139. }
  140. {
  141. int n1;
  142. int n2;
  143. if (sprintf_rdonly_dlopen (&n1, &n2) != 2 || n1 != 1 || n2 != 2)
  144. FAIL_EXIT1 ("sprintf failed: %d %d", n1, n2);
  145. }
  146. /* However if the format string is placed on a writable memory not covered
  147. by ELF segments, libc needs to resort to procfs. */
  148. {
  149. char buf[128];
  150. int n1;
  151. int n2;
  152. char *buf2_malloc = xstrdup (writeable_format);
  153. CHK_FAIL_START
  154. sprintf (buf, buf2_malloc, str2, &n1, str2, &n2);
  155. CHK_FAIL_END
  156. }
  157. /* Same as before, but from an library. */
  158. {
  159. int n1;
  160. int n2;
  161. CHK_FAIL_START
  162. sprintf_writable_malloc (&n1, &n2);
  163. CHK_FAIL_END
  164. }
  165. {
  166. int n1;
  167. int n2;
  168. CHK_FAIL_START
  169. sprintf_writable_malloc_dlopen (&n1, &n2);
  170. CHK_FAIL_END
  171. }
  172. return ret;
  173. }
  174. #include <support/test-driver.c>