dexcr_test.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <sys/prctl.h>
  7. #include <unistd.h>
  8. #include "dexcr.h"
  9. #include "utils.h"
  10. /*
  11. * Helper function for testing the behaviour of a newly exec-ed process
  12. */
  13. static int dexcr_prctl_onexec_test_child(unsigned long which, const char *status)
  14. {
  15. unsigned long dexcr = mfspr(SPRN_DEXCR_RO);
  16. unsigned long aspect = pr_which_to_aspect(which);
  17. int ctrl = pr_get_dexcr(which);
  18. if (!strcmp(status, "set")) {
  19. FAIL_IF_EXIT_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_SET),
  20. "setting aspect across exec not applied");
  21. FAIL_IF_EXIT_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_SET_ONEXEC),
  22. "setting aspect across exec not inherited");
  23. FAIL_IF_EXIT_MSG(!(aspect & dexcr), "setting aspect across exec did not take effect");
  24. } else if (!strcmp(status, "clear")) {
  25. FAIL_IF_EXIT_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR),
  26. "clearing aspect across exec not applied");
  27. FAIL_IF_EXIT_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC),
  28. "clearing aspect across exec not inherited");
  29. FAIL_IF_EXIT_MSG(aspect & dexcr, "clearing aspect across exec did not take effect");
  30. } else {
  31. FAIL_IF_EXIT_MSG(true, "unknown expected status");
  32. }
  33. return 0;
  34. }
  35. /*
  36. * Test that the given prctl value can be manipulated freely
  37. */
  38. static int dexcr_prctl_aspect_test(unsigned long which)
  39. {
  40. unsigned long aspect = pr_which_to_aspect(which);
  41. pid_t pid;
  42. int ctrl;
  43. int err;
  44. int errno_save;
  45. SKIP_IF_MSG(!dexcr_exists(), "DEXCR not supported");
  46. SKIP_IF_MSG(!pr_dexcr_aspect_supported(which), "DEXCR aspect not supported");
  47. SKIP_IF_MSG(!pr_dexcr_aspect_editable(which), "DEXCR aspect not editable with prctl");
  48. /* We reject invalid combinations of arguments */
  49. err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_SET | PR_PPC_DEXCR_CTRL_CLEAR);
  50. errno_save = errno;
  51. FAIL_IF_MSG(err != -1, "simultaneous set and clear should be rejected");
  52. FAIL_IF_MSG(errno_save != EINVAL, "simultaneous set and clear should be rejected with EINVAL");
  53. err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_SET_ONEXEC | PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC);
  54. errno_save = errno;
  55. FAIL_IF_MSG(err != -1, "simultaneous set and clear on exec should be rejected");
  56. FAIL_IF_MSG(errno_save != EINVAL, "simultaneous set and clear on exec should be rejected with EINVAL");
  57. /* We set the aspect */
  58. err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_SET);
  59. FAIL_IF_MSG(err, "PR_PPC_DEXCR_CTRL_SET failed");
  60. ctrl = pr_get_dexcr(which);
  61. FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_SET), "config value not PR_PPC_DEXCR_CTRL_SET");
  62. FAIL_IF_MSG(ctrl & PR_PPC_DEXCR_CTRL_CLEAR, "config value unexpected clear flag");
  63. FAIL_IF_MSG(!(aspect & mfspr(SPRN_DEXCR_RO)), "setting aspect did not take effect");
  64. /* We clear the aspect */
  65. err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_CLEAR);
  66. FAIL_IF_MSG(err, "PR_PPC_DEXCR_CTRL_CLEAR failed");
  67. ctrl = pr_get_dexcr(which);
  68. FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR), "config value not PR_PPC_DEXCR_CTRL_CLEAR");
  69. FAIL_IF_MSG(ctrl & PR_PPC_DEXCR_CTRL_SET, "config value unexpected set flag");
  70. FAIL_IF_MSG(aspect & mfspr(SPRN_DEXCR_RO), "clearing aspect did not take effect");
  71. /* We make it set on exec (doesn't change our current value) */
  72. err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_SET_ONEXEC);
  73. FAIL_IF_MSG(err, "PR_PPC_DEXCR_CTRL_SET_ONEXEC failed");
  74. ctrl = pr_get_dexcr(which);
  75. FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR), "process aspect should still be cleared");
  76. FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_SET_ONEXEC), "config value not PR_PPC_DEXCR_CTRL_SET_ONEXEC");
  77. FAIL_IF_MSG(ctrl & PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC, "config value unexpected clear on exec flag");
  78. FAIL_IF_MSG(aspect & mfspr(SPRN_DEXCR_RO), "scheduling aspect to set on exec should not change it now");
  79. /* We make it clear on exec (doesn't change our current value) */
  80. err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC);
  81. FAIL_IF_MSG(err, "PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC failed");
  82. ctrl = pr_get_dexcr(which);
  83. FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR), "process aspect config should still be cleared");
  84. FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC), "config value not PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC");
  85. FAIL_IF_MSG(ctrl & PR_PPC_DEXCR_CTRL_SET_ONEXEC, "config value unexpected set on exec flag");
  86. FAIL_IF_MSG(aspect & mfspr(SPRN_DEXCR_RO), "process aspect should still be cleared");
  87. /* We allow setting the current and on-exec value in a single call */
  88. err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_SET | PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC);
  89. FAIL_IF_MSG(err, "PR_PPC_DEXCR_CTRL_SET | PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC failed");
  90. ctrl = pr_get_dexcr(which);
  91. FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_SET), "config value not PR_PPC_DEXCR_CTRL_SET");
  92. FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC), "config value not PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC");
  93. FAIL_IF_MSG(!(aspect & mfspr(SPRN_DEXCR_RO)), "process aspect should be set");
  94. err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_CLEAR | PR_PPC_DEXCR_CTRL_SET_ONEXEC);
  95. FAIL_IF_MSG(err, "PR_PPC_DEXCR_CTRL_CLEAR | PR_PPC_DEXCR_CTRL_SET_ONEXEC failed");
  96. ctrl = pr_get_dexcr(which);
  97. FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR), "config value not PR_PPC_DEXCR_CTRL_CLEAR");
  98. FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_SET_ONEXEC), "config value not PR_PPC_DEXCR_CTRL_SET_ONEXEC");
  99. FAIL_IF_MSG(aspect & mfspr(SPRN_DEXCR_RO), "process aspect should be clear");
  100. /* Verify the onexec value is applied across exec */
  101. pid = fork();
  102. if (!pid) {
  103. char which_str[32] = {};
  104. char *args[] = { "dexcr_prctl_onexec_test_child", which_str, "set", NULL };
  105. unsigned int ctrl = pr_get_dexcr(which);
  106. sprintf(which_str, "%lu", which);
  107. FAIL_IF_EXIT_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_SET_ONEXEC),
  108. "setting aspect on exec not copied across fork");
  109. FAIL_IF_EXIT_MSG(mfspr(SPRN_DEXCR_RO) & aspect,
  110. "setting aspect on exec wrongly applied to fork");
  111. execve("/proc/self/exe", args, NULL);
  112. _exit(errno);
  113. }
  114. await_child_success(pid);
  115. err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_SET | PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC);
  116. FAIL_IF_MSG(err, "PR_PPC_DEXCR_CTRL_SET | PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC failed");
  117. pid = fork();
  118. if (!pid) {
  119. char which_str[32] = {};
  120. char *args[] = { "dexcr_prctl_onexec_test_child", which_str, "clear", NULL };
  121. unsigned int ctrl = pr_get_dexcr(which);
  122. sprintf(which_str, "%lu", which);
  123. FAIL_IF_EXIT_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC),
  124. "clearing aspect on exec not copied across fork");
  125. FAIL_IF_EXIT_MSG(!(mfspr(SPRN_DEXCR_RO) & aspect),
  126. "clearing aspect on exec wrongly applied to fork");
  127. execve("/proc/self/exe", args, NULL);
  128. _exit(errno);
  129. }
  130. await_child_success(pid);
  131. return 0;
  132. }
  133. static int dexcr_prctl_ibrtpd_test(void)
  134. {
  135. return dexcr_prctl_aspect_test(PR_PPC_DEXCR_IBRTPD);
  136. }
  137. static int dexcr_prctl_srapd_test(void)
  138. {
  139. return dexcr_prctl_aspect_test(PR_PPC_DEXCR_SRAPD);
  140. }
  141. static int dexcr_prctl_nphie_test(void)
  142. {
  143. return dexcr_prctl_aspect_test(PR_PPC_DEXCR_NPHIE);
  144. }
  145. int main(int argc, char *argv[])
  146. {
  147. int err = 0;
  148. /*
  149. * Some tests require checking what happens across exec, so we may be
  150. * invoked as the child of a particular test
  151. */
  152. if (argc > 1) {
  153. if (argc == 3 && !strcmp(argv[0], "dexcr_prctl_onexec_test_child")) {
  154. unsigned long which;
  155. err = parse_ulong(argv[1], strlen(argv[1]), &which, 10);
  156. FAIL_IF_MSG(err, "failed to parse which value for child");
  157. return dexcr_prctl_onexec_test_child(which, argv[2]);
  158. }
  159. FAIL_IF_MSG(true, "unknown test case");
  160. }
  161. /*
  162. * Otherwise we are the main test invocation and run the full suite
  163. */
  164. err |= test_harness(dexcr_prctl_ibrtpd_test, "dexcr_prctl_ibrtpd");
  165. err |= test_harness(dexcr_prctl_srapd_test, "dexcr_prctl_srapd");
  166. err |= test_harness(dexcr_prctl_nphie_test, "dexcr_prctl_nphie");
  167. return err;
  168. }