1 /*
2 * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
3 */
4
5 #include <fcntl.h>
6 #include <libgen.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/mman.h>
11 #include <sys/stat.h>
12 #include <time.h>
13 #include <unistd.h>
14 #include <xenctrl.h>
15 #include <xenstore.h>
16
17 #include <xen/errno.h>
18 #include <xen-tools/libs.h>
19
20 static xc_interface *xch;
21
show_help(void)22 void show_help(void)
23 {
24 fprintf(stderr,
25 "xen-livepatch: live patching tool\n"
26 "Usage: xen-livepatch <command> [args] [command-flags]\n"
27 " <name> An unique name of payload. Up to %d characters.\n"
28 "Commands:\n"
29 " help display this help\n"
30 " upload <name> <file> upload file <file> with <name> name\n"
31 " list list payloads uploaded.\n"
32 " apply <name> [flags] apply <name> patch.\n"
33 " Supported flags:\n"
34 " --nodeps Disable inter-module buildid dependency check.\n"
35 " Check only against hypervisor buildid.\n"
36 " revert <name> revert name <name> patch.\n"
37 " replace <name> apply <name> patch and revert all others.\n"
38 " unload <name> unload name <name> patch.\n"
39 " load <file> [flags] upload and apply <file> with name as the <file> name\n"
40 " Supported flags:\n"
41 " --nodeps Disable inter-module buildid dependency check.\n"
42 " Check only against hypervisor buildid.\n",
43 XEN_LIVEPATCH_NAME_SIZE);
44 }
45
46 /* wrapper function */
help_func(int argc,char * argv[])47 static int help_func(int argc, char *argv[])
48 {
49 show_help();
50 return 0;
51 }
52
state2str(unsigned int state)53 static const char *state2str(unsigned int state)
54 {
55 #define STATE(x) [LIVEPATCH_STATE_##x] = #x
56 static const char *const names[] = {
57 STATE(CHECKED),
58 STATE(APPLIED),
59 };
60 #undef STATE
61 if (state >= ARRAY_SIZE(names) || !names[state])
62 return "unknown";
63
64 return names[state];
65 }
66
list_func(int argc,char * argv[])67 static int list_func(int argc, char *argv[])
68 {
69 unsigned int nr, done, left, i;
70 xen_livepatch_status_t *info = NULL;
71 char *name = NULL;
72 char *metadata = NULL;
73 uint32_t *len = NULL;
74 uint32_t *metadata_len = NULL;
75 uint32_t name_total_size, metadata_total_size, name_off, metadata_off;
76 int rc = ENOMEM;
77
78 if ( argc )
79 {
80 show_help();
81 return -1;
82 }
83 done = left = 0;
84
85 rc = xc_livepatch_list_get_sizes(xch, &nr, &name_total_size, &metadata_total_size);
86 if ( rc )
87 {
88 rc = errno;
89 fprintf(stderr, "Failed to get list sizes.\n"
90 "Error %d: %s\n",
91 rc, strerror(rc));
92 return rc;
93 }
94
95 if ( nr == 0 )
96 {
97 fprintf(stdout, "Nothing to list\n");
98 return 0;
99 }
100
101 info = malloc(nr * sizeof(*info));
102 if ( !info )
103 return rc;
104
105 name = malloc(name_total_size * sizeof(*name));
106 if ( !name )
107 goto error_name;
108
109 len = malloc(nr * sizeof(*len));
110 if ( !len )
111 goto error_len;
112
113 metadata = malloc(metadata_total_size * sizeof(*metadata) + 1);
114 if ( !metadata )
115 goto error_metadata;
116
117 metadata_len = malloc(nr * sizeof(*metadata_len));
118 if ( !metadata_len )
119 goto error_metadata_len;
120
121 memset(info, 'A', nr * sizeof(*info));
122 memset(name, 'B', name_total_size * sizeof(*name));
123 memset(len, 'C', nr * sizeof(*len));
124 memset(metadata, 'D', metadata_total_size * sizeof(*metadata) + 1);
125 memset(metadata_len, 'E', nr * sizeof(*metadata_len));
126 name_off = metadata_off = 0;
127
128 rc = xc_livepatch_list(xch, nr, 0, info, name, len, name_total_size,
129 metadata, metadata_len, metadata_total_size, &done, &left);
130 if ( rc || done != nr || left > 0)
131 {
132 rc = errno;
133 fprintf(stderr, "Failed to list %d/%d.\n"
134 "Error %d: %s\n",
135 left, nr, rc, strerror(rc));
136 goto error;
137 }
138
139 fprintf(stdout," ID | status | metadata\n"
140 "----------------------------------------+------------+---------------\n");
141
142 for ( i = 0; i < done; i++ )
143 {
144 unsigned int j;
145 char *name_str = name + name_off;
146 char *metadata_str = metadata + metadata_off;
147
148 printf("%-40.*s| %s", len[i], name_str, state2str(info[i].state));
149 if ( info[i].rc )
150 printf(" (%d, %s) | ", -info[i].rc, strerror(-info[i].rc));
151 else
152 printf(" | ");
153
154 /* Replace all '\0' with semi-colons. */
155 for ( j = 0; metadata_len[i] && j < metadata_len[i] - 1; j++ )
156 metadata_str[j] = (metadata_str[j] ?: ';');
157 printf("%.*s\n", metadata_len[i], metadata_str);
158
159 name_off += len[i];
160 metadata_off += metadata_len[i];
161 }
162
163 error:
164 free(metadata_len);
165 error_metadata_len:
166 free(metadata);
167 error_metadata:
168 free(len);
169 error_len:
170 free(name);
171 error_name:
172 free(info);
173 return rc;
174 }
175 #undef MAX_LEN
176
get_name(int argc,char * argv[],char * name)177 static int get_name(int argc, char *argv[], char *name)
178 {
179 ssize_t len = strlen(argv[0]);
180 if ( len > XEN_LIVEPATCH_NAME_SIZE )
181 {
182 fprintf(stderr, "ID must be no more than %d characters.\n",
183 XEN_LIVEPATCH_NAME_SIZE);
184 errno = EINVAL;
185 return errno;
186 }
187 /* Don't want any funny strings from the stack. */
188 memset(name, 0, XEN_LIVEPATCH_NAME_SIZE);
189 strncpy(name, argv[0], len);
190 return 0;
191 }
192
upload_func(int argc,char * argv[])193 static int upload_func(int argc, char *argv[])
194 {
195 char *filename;
196 char name[XEN_LIVEPATCH_NAME_SIZE];
197 int fd = 0, rc;
198 struct stat buf;
199 unsigned char *fbuf;
200 ssize_t len;
201
202 if ( argc != 2 )
203 {
204 show_help();
205 return -1;
206 }
207
208 if ( get_name(argc, argv, name) )
209 return EINVAL;
210
211 filename = argv[1];
212 fd = open(filename, O_RDONLY);
213 if ( fd < 0 )
214 {
215 int saved_errno = errno;
216 fprintf(stderr, "Could not open %s.\n"
217 "Error %d: %s\n",
218 filename, saved_errno, strerror(saved_errno));
219 return saved_errno;
220 }
221 if ( stat(filename, &buf) != 0 )
222 {
223 int saved_errno = errno;
224 fprintf(stderr, "Could not get size of %s.\n"
225 "Error %d: %s\n",
226 filename, saved_errno, strerror(saved_errno));
227 close(fd);
228 return saved_errno;
229 }
230
231 len = buf.st_size;
232 fbuf = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
233 if ( fbuf == MAP_FAILED )
234 {
235 int saved_errno = errno;
236 fprintf(stderr, "Could not map %s.\n"
237 "Error %d: %s\n",
238 filename, saved_errno, strerror(saved_errno));
239 close (fd);
240 return saved_errno;
241 }
242 printf("Uploading %s... ", filename);
243 rc = xc_livepatch_upload(xch, name, fbuf, len);
244 if ( rc )
245 {
246 rc = errno;
247 printf("failed\n");
248 fprintf(stderr, "Error %d: %s\n", rc, strerror(rc));
249 }
250 else
251 printf("completed\n");
252
253
254 if ( munmap( fbuf, len) )
255 {
256 fprintf(stderr, "Could not unmap %s.\n"
257 "Error %d: %s\n",
258 filename, errno, strerror(errno));
259 }
260 close(fd);
261
262 return rc;
263 }
264
265 /* These MUST match to the 'action_options[]' and 'flag_options[]' array slots. */
266 enum {
267 ACTION_APPLY = 0,
268 ACTION_REVERT = 1,
269 ACTION_UNLOAD = 2,
270 ACTION_REPLACE = 3,
271 ACTION_NUM
272 };
273
274 struct {
275 int allow; /* State it must be in to call function. */
276 int expected; /* The state to be in after the function. */
277 const char *name;
278 const char *verb;
279 int (*function)(xc_interface *xch, char *name, uint32_t timeout, uint32_t flags);
280 } action_options[] = {
281 { .allow = LIVEPATCH_STATE_CHECKED,
282 .expected = LIVEPATCH_STATE_APPLIED,
283 .name = "apply",
284 .verb = "Applying",
285 .function = xc_livepatch_apply,
286 },
287 { .allow = LIVEPATCH_STATE_APPLIED,
288 .expected = LIVEPATCH_STATE_CHECKED,
289 .name = "revert",
290 .verb = "Reverting",
291 .function = xc_livepatch_revert,
292 },
293 { .allow = LIVEPATCH_STATE_CHECKED,
294 .expected = -XEN_ENOENT,
295 .name = "unload",
296 .verb = "Unloading",
297 .function = xc_livepatch_unload,
298 },
299 { .allow = LIVEPATCH_STATE_CHECKED,
300 .expected = LIVEPATCH_STATE_APPLIED,
301 .name = "replace",
302 .verb = "Replacing all live patches with",
303 .function = xc_livepatch_replace,
304 },
305 };
306
307 /*
308 * This structure defines supported flag options for actions.
309 * It defines entries for each action and supports up to 32
310 * flags per action.
311 */
312 struct {
313 const char *name;
314 const uint32_t flag;
315 } flag_options[ACTION_NUM][8 * sizeof(uint32_t)] = {
316 { /* ACTION_APPLY */
317 { .name = "--nodeps",
318 .flag = LIVEPATCH_ACTION_APPLY_NODEPS,
319 },
320 },
321 { /* ACTION_REVERT */
322 },
323 { /* ACTION_UNLOAD */
324 },
325 { /* ACTION_REPLACE */
326 }
327 };
328
329 /*
330 * Parse user provided action flags.
331 * This function expects to only receive an array of input parameters being flags.
332 * Expected action is specified via idx paramater (index of flag_options[]).
333 */
get_flags(int argc,char * argv[],unsigned int idx,uint32_t * flags)334 static int get_flags(int argc, char *argv[], unsigned int idx, uint32_t *flags)
335 {
336 int i, j;
337
338 if ( !flags || idx >= ARRAY_SIZE(flag_options) )
339 return -1;
340
341 *flags = 0;
342 for ( i = 0; i < argc; i++ )
343 {
344 for ( j = 0; j < ARRAY_SIZE(flag_options[idx]); j++ )
345 {
346 if ( !flag_options[idx][j].name )
347 goto error;
348
349 if ( !strcmp(flag_options[idx][j].name, argv[i]) )
350 {
351 *flags |= flag_options[idx][j].flag;
352 break;
353 }
354 }
355
356 if ( j == ARRAY_SIZE(flag_options[idx]) )
357 goto error;
358 }
359
360 return 0;
361 error:
362 fprintf(stderr, "Unsupported flag: %s.\n", argv[i]);
363 errno = EINVAL;
364 return errno;
365 }
366
367 /* The hypervisor timeout for the live patching operation is 30 msec,
368 * but it could take some time for the operation to start, so wait twice
369 * that period. */
370 #define HYPERVISOR_TIMEOUT_NS 30000000
371 #define DELAY (2 * HYPERVISOR_TIMEOUT_NS)
372
nanosleep_retry(long ns)373 static void nanosleep_retry(long ns)
374 {
375 struct timespec req, rem;
376 int rc;
377
378 rem.tv_sec = 0;
379 rem.tv_nsec = ns;
380
381 do {
382 req = rem;
383 rc = nanosleep(&req, &rem);
384 } while ( rc == -1 && errno == EINTR );
385 }
386
action_func(int argc,char * argv[],unsigned int idx)387 int action_func(int argc, char *argv[], unsigned int idx)
388 {
389 char name[XEN_LIVEPATCH_NAME_SIZE];
390 int rc;
391 xen_livepatch_status_t status;
392 uint32_t flags;
393
394 if ( argc < 1 )
395 {
396 show_help();
397 return -1;
398 }
399
400 if ( idx >= ARRAY_SIZE(action_options) )
401 return -1;
402
403 if ( get_name(argc--, argv++, name) )
404 return EINVAL;
405
406 if ( get_flags(argc, argv, idx, &flags) )
407 return EINVAL;
408
409 /* Check initial status. */
410 rc = xc_livepatch_get(xch, name, &status);
411 if ( rc )
412 {
413 int saved_errno = errno;
414 fprintf(stderr, "Failed to get status of %s.\n"
415 "Error %d: %s\n",
416 name, saved_errno, strerror(saved_errno));
417 return saved_errno;
418 }
419 if ( status.rc == -XEN_EAGAIN )
420 {
421 fprintf(stderr,
422 "Cannot execute %s.\n"
423 "Operation already in progress.\n", action_options[idx].name);
424 return EAGAIN;
425 }
426
427 if ( status.state == action_options[idx].expected )
428 {
429 printf("No action needed.\n");
430 return 0;
431 }
432
433 /* Perform action. */
434 if ( action_options[idx].allow & status.state )
435 {
436 printf("%s %s... ", action_options[idx].verb, name);
437 rc = action_options[idx].function(xch, name, HYPERVISOR_TIMEOUT_NS, flags);
438 if ( rc )
439 {
440 int saved_errno = errno;
441 printf("failed\n");
442 fprintf(stderr, "Error %d: %s\n",
443 saved_errno, strerror(saved_errno));
444 return saved_errno;
445 }
446 }
447 else
448 {
449 fprintf(stderr, "%s is in the wrong state.\n"
450 "Current state: %s\n"
451 "Expected state: %s\n",
452 name, state2str(status.state),
453 state2str(action_options[idx].allow));
454 return -1;
455 }
456
457 nanosleep_retry(DELAY);
458 rc = xc_livepatch_get(xch, name, &status);
459
460 if ( rc )
461 rc = -errno;
462 else if ( status.rc )
463 rc = status.rc;
464
465 if ( rc == -XEN_EAGAIN )
466 {
467 printf("failed\n");
468 fprintf(stderr, "Operation didn't complete.\n");
469 return EAGAIN;
470 }
471
472 if ( rc == 0 )
473 rc = status.state;
474
475 if ( action_options[idx].expected == rc )
476 printf("completed\n");
477 else if ( rc < 0 )
478 {
479 printf("failed\n");
480 fprintf(stderr, "Error %d: %s\n", -rc, strerror(-rc));
481 return -rc;
482 }
483 else
484 {
485 printf("failed\n");
486 fprintf(stderr, "%s is in the wrong state.\n"
487 "Current state: %s\n"
488 "Expected state: %s\n",
489 name, state2str(rc),
490 state2str(action_options[idx].expected));
491 return -1;
492 }
493
494 return 0;
495 }
496
load_func(int argc,char * argv[])497 static int load_func(int argc, char *argv[])
498 {
499 int i, rc = ENOMEM;
500 char *upload_argv[2];
501 char **apply_argv, *path, *name, *lastdot;
502
503 if ( argc < 1 )
504 {
505 show_help();
506 return -1;
507 }
508
509 /* apply action has <id> [flags] input requirement, which must be constructed */
510 apply_argv = (char **) malloc(argc * sizeof(*apply_argv));
511 if ( !apply_argv )
512 return rc;
513
514 /* <file> */
515 upload_argv[1] = argv[0];
516
517 /* Synthesize the <id> */
518 path = strdup(argv[0]);
519
520 name = basename(path);
521 lastdot = strrchr(name, '.');
522 if ( lastdot != NULL )
523 *lastdot = '\0';
524 upload_argv[0] = name;
525 apply_argv[0] = name;
526
527 /* Fill in all user provided flags */
528 for ( i = 1; i < argc; i++ )
529 apply_argv[i] = argv[i];
530
531 rc = upload_func(2 /* <id> <file> */, upload_argv);
532 if ( rc )
533 goto error;
534
535 rc = action_func(argc, apply_argv, ACTION_APPLY);
536 if ( rc )
537 action_func(1 /* only <id> */, upload_argv, ACTION_UNLOAD);
538
539 error:
540 free(apply_argv);
541 free(path);
542 return rc;
543 }
544
545 /*
546 * These are also functions in action_options that are called in case
547 * none of the ones in main_options match.
548 */
549 struct {
550 const char *name;
551 int (*function)(int argc, char *argv[]);
552 } main_options[] = {
553 { "help", help_func },
554 { "list", list_func },
555 { "upload", upload_func },
556 { "load", load_func },
557 };
558
main(int argc,char * argv[])559 int main(int argc, char *argv[])
560 {
561 int i, j = 0, ret;
562
563 /*
564 * Set stdout to be unbuffered to avoid having to fflush when
565 * printing without a newline.
566 */
567 setvbuf(stdout, NULL, _IONBF, 0);
568
569 if ( argc <= 1 )
570 {
571 show_help();
572 return 0;
573 }
574 for ( i = 0; i < ARRAY_SIZE(main_options); i++ )
575 if (!strncmp(main_options[i].name, argv[1], strlen(argv[1])))
576 break;
577
578 if ( i == ARRAY_SIZE(main_options) )
579 {
580 for ( j = 0; j < ARRAY_SIZE(action_options); j++ )
581 if (!strncmp(action_options[j].name, argv[1], strlen(argv[1])))
582 break;
583
584 if ( j == ARRAY_SIZE(action_options) )
585 {
586 fprintf(stderr, "Unrecognised command '%s' -- try "
587 "'xen-livepatch help'\n", argv[1]);
588 return 1;
589 }
590 }
591
592 xch = xc_interface_open(0,0,0);
593 if ( !xch )
594 {
595 fprintf(stderr, "failed to get the handler\n");
596 return 0;
597 }
598
599 if ( i == ARRAY_SIZE(main_options) )
600 ret = action_func(argc -2, argv + 2, j);
601 else
602 ret = main_options[i].function(argc -2, argv + 2);
603
604 xc_interface_close(xch);
605
606 /*
607 * Exitcode 0 for success.
608 * Exitcode 1 for an error.
609 * Exitcode 2 if the operation should be retried for any reason (e.g. a
610 * timeout or because another operation was in progress).
611 */
612 #define EXIT_TIMEOUT (EXIT_FAILURE + 1)
613
614 BUILD_BUG_ON(EXIT_SUCCESS != 0);
615 BUILD_BUG_ON(EXIT_FAILURE != 1);
616 BUILD_BUG_ON(EXIT_TIMEOUT != 2);
617
618 switch ( ret )
619 {
620 case 0:
621 return EXIT_SUCCESS;
622 case EAGAIN:
623 case EBUSY:
624 return EXIT_TIMEOUT;
625 default:
626 return EXIT_FAILURE;
627 }
628 }
629
630 /*
631 * Local variables:
632 * mode: C
633 * c-file-style: "BSD"
634 * c-basic-offset: 4
635 * tab-width: 4
636 * indent-tabs-mode: nil
637 * End:
638 */
639