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