tst-safe-linking.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /* Test reporting of Safe-Linking caught errors.
  2. Copyright (C) 2020-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 <signal.h>
  16. #include <stdint.h>
  17. #include <stdlib.h>
  18. #include <memory.h>
  19. #include <string.h>
  20. #include <time.h>
  21. #include <stdbool.h>
  22. #include <support/capture_subprocess.h>
  23. #include <support/check.h>
  24. #include "tst-malloc-aux.h"
  25. /* Run CALLBACK and check that the data on standard error equals
  26. EXPECTED. */
  27. static void
  28. check (const char *test, void (*callback) (void *),
  29. const char *expected)
  30. {
  31. int i, rand_mask;
  32. int success = 0; /* 0 == fail, 1 == other check 2 == safe linking */
  33. /* There is a chance of 1/16 that a corrupted pointer will be aligned.
  34. Try multiple times so that statistical failure will be improbable. */
  35. for (i = 0; i < 16; ++i)
  36. {
  37. rand_mask = rand () & 0xFF;
  38. struct support_capture_subprocess result
  39. = support_capture_subprocess (callback, &rand_mask);
  40. printf ("%s\n", result.out.buffer);
  41. /* Did not crash, could happen. Try again. */
  42. if (strlen (result.err.buffer) == 0)
  43. continue;
  44. /* Crashed, it may either be safe linking or some other check. If it's
  45. not safe linking then try again. */
  46. if (strcmp (result.err.buffer, expected) != 0)
  47. {
  48. printf ("test %s failed with a different error\n"
  49. " expected: %s\n"
  50. " actual: %s\n",
  51. test, expected, result.err.buffer);
  52. success = 1;
  53. continue;
  54. }
  55. TEST_VERIFY (WIFSIGNALED (result.status));
  56. if (WIFSIGNALED (result.status))
  57. TEST_VERIFY (WTERMSIG (result.status) == SIGABRT);
  58. support_capture_subprocess_free (&result);
  59. success = 2;
  60. break;
  61. }
  62. /* The test fails only if the corruption was not caught by any of the malloc
  63. mechanisms in all those iterations. This has a lower than 1 in 2^64
  64. chance of a false positive. */
  65. TEST_VERIFY (success);
  66. }
  67. /* Implementation details must be kept in sync with malloc. */
  68. #define TCACHE_FILL_COUNT 7
  69. #define TCACHE_ALLOC_SIZE 0x20
  70. /* Try corrupting the tcache list. */
  71. static void
  72. test_tcache (void *closure)
  73. {
  74. int mask = ((int *)closure)[0];
  75. size_t size = TCACHE_ALLOC_SIZE;
  76. printf ("++ tcache ++\n");
  77. /* Populate the tcache list. */
  78. void * volatile a = malloc (size);
  79. void * volatile b = malloc (size);
  80. void * volatile c = malloc (size);
  81. printf ("a=%p, b=%p, c=%p\n", a, b, c);
  82. free (a);
  83. free (b);
  84. free (c);
  85. /* Corrupt the pointer with a random value, and avoid optimizations. */
  86. printf ("Before: c=%p, c[0]=%p\n", c, ((void **)c)[0]);
  87. memset (c, mask & 0xFF, size);
  88. printf ("After: c=%p, c[0]=%p\n", c, ((void **)c)[0]);
  89. c = malloc (size);
  90. printf ("Allocated: c=%p\n", c);
  91. /* This line will trigger the Safe-Linking check. */
  92. b = malloc (size);
  93. printf ("b=%p\n", b);
  94. }
  95. static int
  96. do_test (void)
  97. {
  98. /* Seed the random for the test. */
  99. srand (time (NULL));
  100. check ("test_tcache", test_tcache,
  101. "malloc(): unaligned tcache chunk detected\n");
  102. return 0;
  103. }
  104. #include <support/test-driver.c>