1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * rv tool, the interface for the Linux kernel RV subsystem and home of 4 * user-space controlled monitors. 5 * 6 * Copyright (C) 2022 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org> 7 */ 8 9 #include <stdlib.h> 10 #include <signal.h> 11 #include <unistd.h> 12 13 #include <trace.h> 14 #include <utils.h> 15 #include <in_kernel.h> 16 17 static int stop_session; 18 19 /* 20 * stop_rv - tell monitors to stop 21 */ 22 static void stop_rv(int sig) 23 { 24 stop_session = 1; 25 } 26 27 /** 28 * should_stop - check if the monitor should stop. 29 * 30 * Returns 1 if the monitor should stop, 0 otherwise. 31 */ 32 int should_stop(void) 33 { 34 return stop_session; 35 } 36 37 /* 38 * rv_list - list all available monitors 39 */ 40 static void rv_list(int argc, char **argv) 41 { 42 static const char *const usage[] = { 43 "", 44 " usage: rv list [-h]", 45 "", 46 " list all available monitors", 47 "", 48 " -h/--help: print this menu", 49 NULL, 50 }; 51 int i; 52 53 if (argc > 1) { 54 fprintf(stderr, "rv version %s\n", VERSION); 55 56 /* more than 1 is always usage */ 57 for (i = 0; usage[i]; i++) 58 fprintf(stderr, "%s\n", usage[i]); 59 60 /* but only -h is valid */ 61 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) 62 exit(0); 63 else 64 exit(1); 65 } 66 67 ikm_list_monitors(); 68 exit(0); 69 } 70 71 /* 72 * rv_mon - try to run a monitor passed as argument 73 */ 74 static void rv_mon(int argc, char **argv) 75 { 76 char *monitor_name; 77 int i, run = 0; 78 79 static const char *const usage[] = { 80 "", 81 " usage: rv mon [-h] monitor [monitor options]", 82 "", 83 " run a monitor", 84 "", 85 " -h/--help: print this menu", 86 "", 87 " monitor [monitor options]: the monitor, passing", 88 " the arguments to the [monitor options]", 89 NULL, 90 }; 91 92 /* requires at least one argument */ 93 if (argc == 1) { 94 95 fprintf(stderr, "rv version %s\n", VERSION); 96 97 for (i = 0; usage[i]; i++) 98 fprintf(stderr, "%s\n", usage[i]); 99 exit(1); 100 } else if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { 101 102 fprintf(stderr, "rv version %s\n", VERSION); 103 104 for (i = 0; usage[i]; i++) 105 fprintf(stderr, "%s\n", usage[i]); 106 exit(0); 107 } 108 109 monitor_name = argv[1]; 110 /* 111 * Call all possible monitor implementations, looking 112 * for the [monitor]. 113 */ 114 run += ikm_run_monitor(monitor_name, argc-1, &argv[1]); 115 116 if (!run) 117 err_msg("rv: monitor %s does not exist\n", monitor_name); 118 exit(!run); 119 } 120 121 static void usage(int exit_val, const char *fmt, ...) 122 { 123 char message[1024]; 124 va_list ap; 125 int i; 126 127 static const char *const usage[] = { 128 "", 129 " usage: rv command [-h] [command_options]", 130 "", 131 " -h/--help: print this menu", 132 "", 133 " command: run one of the following command:", 134 " list: list all available monitors", 135 " mon: run a monitor", 136 "", 137 " [command options]: each command has its own set of options", 138 " run rv command -h for further information", 139 NULL, 140 }; 141 142 va_start(ap, fmt); 143 vsnprintf(message, sizeof(message), fmt, ap); 144 va_end(ap); 145 146 fprintf(stderr, "rv version %s: %s\n", VERSION, message); 147 148 for (i = 0; usage[i]; i++) 149 fprintf(stderr, "%s\n", usage[i]); 150 151 exit(exit_val); 152 } 153 154 /* 155 * main - select which main sending the command 156 * 157 * main itself redirects the arguments to the sub-commands 158 * to handle the options. 159 * 160 * subcommands should exit. 161 */ 162 int main(int argc, char **argv) 163 { 164 if (geteuid()) 165 usage(1, "%s needs root permission", argv[0]); 166 167 if (argc <= 1) 168 usage(1, "%s requires a command", argv[0]); 169 170 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) 171 usage(0, "help"); 172 173 if (!strcmp(argv[1], "list")) 174 rv_list(--argc, &argv[1]); 175 176 if (!strcmp(argv[1], "mon")) { 177 /* 178 * monitor's main should monitor should_stop() function. 179 * and exit. 180 */ 181 signal(SIGINT, stop_rv); 182 183 rv_mon(argc - 1, &argv[1]); 184 } 185 186 /* invalid sub-command */ 187 usage(1, "%s does not know the %s command, old version?", argv[0], argv[1]); 188 } 189