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