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