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] [container]", 45 "", 46 " list all available monitors", 47 "", 48 " -h/--help: print this menu", 49 "", 50 " [container]: list only monitors in this container", 51 NULL, 52 }; 53 int i, print_help = 0, retval = 0; 54 char *container = NULL; 55 56 if (argc == 2) { 57 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { 58 print_help = 1; 59 retval = 0; 60 } else if (argv[1][0] == '-') { 61 /* assume invalid option */ 62 print_help = 1; 63 retval = 1; 64 } else 65 container = argv[1]; 66 } else if (argc > 2) { 67 /* more than 2 is always usage */ 68 print_help = 1; 69 retval = 1; 70 } 71 if (print_help) { 72 fprintf(stderr, "rv version %s\n", VERSION); 73 for (i = 0; usage[i]; i++) 74 fprintf(stderr, "%s\n", usage[i]); 75 exit(retval); 76 } 77 78 ikm_list_monitors(container); 79 80 exit(0); 81 } 82 83 /* 84 * rv_mon - try to run a monitor passed as argument 85 */ 86 static void rv_mon(int argc, char **argv) 87 { 88 char *monitor_name; 89 int i, run = 0; 90 91 static const char *const usage[] = { 92 "", 93 " usage: rv mon [-h] monitor [monitor options]", 94 "", 95 " run a monitor", 96 "", 97 " -h/--help: print this menu", 98 "", 99 " monitor [monitor options]: the monitor, passing", 100 " the arguments to the [monitor options]", 101 NULL, 102 }; 103 104 /* requires at least one argument */ 105 if (argc == 1) { 106 107 fprintf(stderr, "rv version %s\n", VERSION); 108 109 for (i = 0; usage[i]; i++) 110 fprintf(stderr, "%s\n", usage[i]); 111 exit(1); 112 } else if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { 113 114 fprintf(stderr, "rv version %s\n", VERSION); 115 116 for (i = 0; usage[i]; i++) 117 fprintf(stderr, "%s\n", usage[i]); 118 exit(0); 119 } 120 121 monitor_name = argv[1]; 122 /* 123 * Call all possible monitor implementations, looking 124 * for the [monitor]. 125 */ 126 run += ikm_run_monitor(monitor_name, argc-1, &argv[1]); 127 128 if (!run) 129 err_msg("rv: monitor %s does not exist\n", monitor_name); 130 exit(!run); 131 } 132 133 static void usage(int exit_val, const char *fmt, ...) 134 { 135 char message[1024]; 136 va_list ap; 137 int i; 138 139 static const char *const usage[] = { 140 "", 141 " usage: rv command [-h] [command_options]", 142 "", 143 " -h/--help: print this menu", 144 "", 145 " command: run one of the following command:", 146 " list: list all available monitors", 147 " mon: run a monitor", 148 "", 149 " [command options]: each command has its own set of options", 150 " run rv command -h for further information", 151 NULL, 152 }; 153 154 va_start(ap, fmt); 155 vsnprintf(message, sizeof(message), fmt, ap); 156 va_end(ap); 157 158 fprintf(stderr, "rv version %s: %s\n", VERSION, message); 159 160 for (i = 0; usage[i]; i++) 161 fprintf(stderr, "%s\n", usage[i]); 162 163 exit(exit_val); 164 } 165 166 /* 167 * main - select which main sending the command 168 * 169 * main itself redirects the arguments to the sub-commands 170 * to handle the options. 171 * 172 * subcommands should exit. 173 */ 174 int main(int argc, char **argv) 175 { 176 if (geteuid()) 177 usage(1, "%s needs root permission", argv[0]); 178 179 if (argc <= 1) 180 usage(1, "%s requires a command", argv[0]); 181 182 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) 183 usage(0, "help"); 184 185 if (!strcmp(argv[1], "list")) 186 rv_list(--argc, &argv[1]); 187 188 if (!strcmp(argv[1], "mon")) { 189 /* 190 * monitor's main should monitor should_stop() function. 191 * and exit. 192 */ 193 signal(SIGINT, stop_rv); 194 signal(SIGTERM, stop_rv); 195 196 rv_mon(argc - 1, &argv[1]); 197 } 198 199 /* invalid sub-command */ 200 usage(1, "%s does not know the %s command, old version?", argv[0], argv[1]); 201 } 202