chdexcr.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. #include <errno.h>
  3. #include <stddef.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <sys/prctl.h>
  8. #include "dexcr.h"
  9. #include "utils.h"
  10. static void die(const char *msg)
  11. {
  12. printf("%s\n", msg);
  13. exit(1);
  14. }
  15. static void help(void)
  16. {
  17. printf("Invoke a provided program with a custom DEXCR on-exec reset value\n"
  18. "\n"
  19. "usage: chdexcr [CHDEXCR OPTIONS] -- PROGRAM [ARGS...]\n"
  20. "\n"
  21. "Each configurable DEXCR aspect is exposed as an option.\n"
  22. "\n"
  23. "The normal option sets the aspect in the DEXCR. The --no- variant\n"
  24. "clears that aspect. For example, --ibrtpd sets the IBRTPD aspect bit,\n"
  25. "so indirect branch prediction will be disabled in the provided program.\n"
  26. "Conversely, --no-ibrtpd clears the aspect bit, so indirect branch\n"
  27. "prediction may occur.\n"
  28. "\n"
  29. "CHDEXCR OPTIONS:\n");
  30. for (int i = 0; i < ARRAY_SIZE(aspects); i++) {
  31. const struct dexcr_aspect *aspect = &aspects[i];
  32. if (aspect->prctl == -1)
  33. continue;
  34. printf(" --%-6s / --no-%-6s : %s\n", aspect->opt, aspect->opt, aspect->desc);
  35. }
  36. }
  37. static const struct dexcr_aspect *opt_to_aspect(const char *opt)
  38. {
  39. for (int i = 0; i < ARRAY_SIZE(aspects); i++)
  40. if (aspects[i].prctl != -1 && !strcmp(aspects[i].opt, opt))
  41. return &aspects[i];
  42. return NULL;
  43. }
  44. static int apply_option(const char *option)
  45. {
  46. const struct dexcr_aspect *aspect;
  47. const char *opt = NULL;
  48. const char *set_prefix = "--";
  49. const char *clear_prefix = "--no-";
  50. unsigned long ctrl = 0;
  51. int err;
  52. if (!strcmp(option, "-h") || !strcmp(option, "--help")) {
  53. help();
  54. exit(0);
  55. }
  56. /* Strip out --(no-) prefix and determine ctrl value */
  57. if (!strncmp(option, clear_prefix, strlen(clear_prefix))) {
  58. opt = &option[strlen(clear_prefix)];
  59. ctrl |= PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC;
  60. } else if (!strncmp(option, set_prefix, strlen(set_prefix))) {
  61. opt = &option[strlen(set_prefix)];
  62. ctrl |= PR_PPC_DEXCR_CTRL_SET_ONEXEC;
  63. }
  64. if (!opt || !*opt)
  65. return 1;
  66. aspect = opt_to_aspect(opt);
  67. if (!aspect)
  68. die("unknown aspect");
  69. err = pr_set_dexcr(aspect->prctl, ctrl);
  70. if (err)
  71. die("failed to apply option");
  72. return 0;
  73. }
  74. int main(int argc, char *const argv[])
  75. {
  76. int i;
  77. if (!dexcr_exists())
  78. die("DEXCR not detected on this hardware");
  79. for (i = 1; i < argc; i++)
  80. if (apply_option(argv[i]))
  81. break;
  82. if (i < argc && !strcmp(argv[i], "--"))
  83. i++;
  84. if (i >= argc)
  85. die("missing command");
  86. execvp(argv[i], &argv[i]);
  87. perror("execve");
  88. return errno;
  89. }