1 /******************************************************************************
2  * kernel.c
3  *
4  * Copyright (c) 2002-2005 K A Fraser
5  */
6 
7 #include <xen/init.h>
8 #include <xen/lib.h>
9 #include <xen/errno.h>
10 #include <xen/param.h>
11 #include <xen/version.h>
12 #include <xen/sched.h>
13 #include <xen/paging.h>
14 #include <xen/guest_access.h>
15 #include <xen/hypercall.h>
16 #include <xen/hypfs.h>
17 #include <xsm/xsm.h>
18 #include <asm/current.h>
19 #include <public/version.h>
20 
21 #ifdef CONFIG_COMPAT
22 #include <compat/version.h>
23 
24 CHECK_build_id;
25 CHECK_compile_info;
26 CHECK_feature_info;
27 #endif
28 
29 enum system_state system_state = SYS_STATE_early_boot;
30 
31 #ifdef CONFIG_HAS_DIT
32 bool __ro_after_init opt_dit = IS_ENABLED(CONFIG_DIT_DEFAULT);
33 boolean_param("dit", opt_dit);
34 #endif
35 
36 static xen_commandline_t saved_cmdline;
37 static const char __initconst opt_builtin_cmdline[] = CONFIG_CMDLINE;
38 
assign_integer_param(const struct kernel_param * param,uint64_t val)39 static int assign_integer_param(const struct kernel_param *param, uint64_t val)
40 {
41     switch ( param->len )
42     {
43     case sizeof(uint8_t):
44         if ( val > UINT8_MAX && val < (uint64_t)INT8_MIN )
45             return -EOVERFLOW;
46         *(uint8_t *)param->par.var = val;
47         break;
48     case sizeof(uint16_t):
49         if ( val > UINT16_MAX && val < (uint64_t)INT16_MIN )
50             return -EOVERFLOW;
51         *(uint16_t *)param->par.var = val;
52         break;
53     case sizeof(uint32_t):
54         if ( val > UINT32_MAX && val < (uint64_t)INT32_MIN )
55             return -EOVERFLOW;
56         *(uint32_t *)param->par.var = val;
57         break;
58     case sizeof(uint64_t):
59         *(uint64_t *)param->par.var = val;
60         break;
61     default:
62         BUG();
63     }
64 
65     return 0;
66 }
67 
parse_params(const char * cmdline,const struct kernel_param * start,const struct kernel_param * end)68 static int parse_params(const char *cmdline, const struct kernel_param *start,
69                         const struct kernel_param *end)
70 {
71     char opt[MAX_PARAM_SIZE], *optval, *optkey, *q;
72     const char *p = cmdline, *key;
73     const struct kernel_param *param;
74     int rc, final_rc = 0;
75     bool bool_assert, found;
76 
77     for ( ; ; )
78     {
79         /* Skip whitespace. */
80         while ( *p == ' ' )
81             p++;
82         if ( *p == '\0' )
83             break;
84 
85         /* Grab the next whitespace-delimited option. */
86         q = optkey = opt;
87         while ( (*p != ' ') && (*p != '\0') )
88         {
89             if ( (q-opt) < (sizeof(opt)-1) ) /* avoid overflow */
90                 *q++ = *p;
91             p++;
92         }
93         *q = '\0';
94 
95         /* Search for value part of a key=value option. */
96         optval = strchr(opt, '=');
97         if ( optval != NULL )
98         {
99             *optval++ = '\0'; /* nul-terminate the option value */
100             q = strpbrk(opt, "([{<");
101         }
102         else
103         {
104             optval = q;       /* default option value is empty string */
105             q = NULL;
106         }
107 
108         /* Boolean parameters can be inverted with 'no-' prefix. */
109         key = optkey;
110         bool_assert = !!strncmp("no-", optkey, 3);
111         if ( !bool_assert )
112             optkey += 3;
113 
114         rc = 0;
115         found = false;
116         for ( param = start; param < end; param++ )
117         {
118             int rctmp;
119             const char *s;
120 
121             if ( strcmp(param->name, optkey) )
122             {
123                 if ( param->type == OPT_CUSTOM && q &&
124                      strlen(param->name) == q + 1 - opt &&
125                      !strncmp(param->name, opt, q + 1 - opt) )
126                 {
127                     found = true;
128                     optval[-1] = '=';
129                     rctmp = param->par.func(q);
130                     optval[-1] = '\0';
131                     if ( !rc )
132                         rc = rctmp;
133                 }
134                 continue;
135             }
136 
137             rctmp = 0;
138             found = true;
139             switch ( param->type )
140             {
141             case OPT_STR:
142                 strlcpy(param->par.var, optval, param->len);
143                 break;
144             case OPT_UINT:
145                 rctmp = assign_integer_param(
146                     param,
147                     simple_strtoll(optval, &s, 0));
148                 if ( *s )
149                     rctmp = -EINVAL;
150                 break;
151             case OPT_BOOL:
152                 rctmp = *optval ? parse_bool(optval, NULL) : 1;
153                 if ( rctmp < 0 )
154                     break;
155                 if ( !rctmp )
156                     bool_assert = !bool_assert;
157                 rctmp = 0;
158                 assign_integer_param(param, bool_assert);
159                 break;
160             case OPT_SIZE:
161                 rctmp = assign_integer_param(
162                     param,
163                     parse_size_and_unit(optval, &s));
164                 if ( *s )
165                     rctmp = -EINVAL;
166                 break;
167             case OPT_CUSTOM:
168                 rctmp = -EINVAL;
169                 if ( !bool_assert )
170                 {
171                     if ( *optval )
172                         break;
173                     safe_strcpy(opt, "no");
174                     optval = opt;
175                 }
176                 rctmp = param->par.func(optval);
177                 break;
178             case OPT_IGNORE:
179                 break;
180             default:
181                 BUG();
182                 break;
183             }
184 
185             if ( !rc )
186                 rc = rctmp;
187         }
188 
189         if ( rc )
190         {
191             printk("parameter \"%s\" has invalid value \"%s\", rc=%d!\n",
192                     key, optval, rc);
193             final_rc = rc;
194         }
195         if ( !found )
196         {
197             printk("parameter \"%s\" unknown!\n", key);
198             final_rc = -EINVAL;
199         }
200     }
201 
202     return final_rc;
203 }
204 
_cmdline_parse(const char * cmdline)205 static void __init _cmdline_parse(const char *cmdline)
206 {
207     parse_params(cmdline, __setup_start, __setup_end);
208 }
209 
210 /**
211  *    cmdline_parse -- parses the xen command line.
212  * If CONFIG_CMDLINE is set, it would be parsed prior to @cmdline.
213  * But if CONFIG_CMDLINE_OVERRIDE is set to y, @cmdline will be ignored.
214  */
cmdline_parse(const char * cmdline)215 void __init cmdline_parse(const char *cmdline)
216 {
217     if ( opt_builtin_cmdline[0] )
218     {
219         printk("Built-in command line: %s\n", opt_builtin_cmdline);
220         _cmdline_parse(opt_builtin_cmdline);
221     }
222 
223 #ifndef CONFIG_CMDLINE_OVERRIDE
224     if ( cmdline == NULL )
225         return;
226 
227     safe_strcpy(saved_cmdline, cmdline);
228     _cmdline_parse(cmdline);
229 #endif
230 }
231 
parse_bool(const char * s,const char * e)232 int parse_bool(const char *s, const char *e)
233 {
234     size_t len = e ? ({ ASSERT(e >= s); e - s; }) : strlen(s);
235 
236     switch ( len )
237     {
238     case 1:
239         if ( *s == '1' )
240             return 1;
241         if ( *s == '0' )
242             return 0;
243         break;
244 
245     case 2:
246         if ( !strncmp("on", s, 2) )
247             return 1;
248         if ( !strncmp("no", s, 2) )
249             return 0;
250         break;
251 
252     case 3:
253         if ( !strncmp("yes", s, 3) )
254             return 1;
255         if ( !strncmp("off", s, 3) )
256             return 0;
257         break;
258 
259     case 4:
260         if ( !strncmp("true", s, 4) )
261             return 1;
262         break;
263 
264     case 5:
265         if ( !strncmp("false", s, 5) )
266             return 0;
267         break;
268 
269     case 6:
270         if ( !strncmp("enable", s, 6) )
271             return 1;
272         break;
273 
274     case 7:
275         if ( !strncmp("disable", s, 7) )
276             return 0;
277         break;
278     }
279 
280     return -1;
281 }
282 
parse_boolean(const char * name,const char * s,const char * e)283 int parse_boolean(const char *name, const char *s, const char *e)
284 {
285     size_t slen, nlen;
286     bool has_neg_prefix = !strncmp(s, "no-", 3);
287 
288     if ( has_neg_prefix )
289         s += 3;
290 
291     slen = e ? ({ ASSERT(e >= s); e - s; }) : strlen(s);
292     nlen = strlen(name);
293 
294     /* Does s now start with name? */
295     if ( slen < nlen || strncmp(s, name, nlen) )
296         return -1;
297 
298     /* Exact, unadorned name?  Result depends on the 'no-' prefix. */
299     if ( slen == nlen )
300         return !has_neg_prefix;
301 
302     /* Inexact match with a 'no-' prefix?  Not valid. */
303     if ( has_neg_prefix )
304         return -1;
305 
306     /* =$SOMETHING?  Defer to the regular boolean parsing. */
307     if ( s[nlen] == '=' )
308     {
309         int b = parse_bool(&s[nlen + 1], e);
310 
311         if ( b >= 0 )
312             return b;
313 
314         /* Not a boolean, but the name matched.  Signal specially. */
315         return -2;
316     }
317 
318     /* Unrecognised.  Give up. */
319     return -1;
320 }
321 
parse_signed_integer(const char * name,const char * s,const char * e,long long * val)322 int __init parse_signed_integer(const char *name, const char *s, const char *e,
323                                 long long *val)
324 {
325     size_t slen, nlen;
326     const char *str;
327     long long pval;
328 
329     slen = e ? ({ ASSERT(e >= s); e - s; }) : strlen(s);
330     nlen = strlen(name);
331 
332     if ( !e )
333         e = s + slen;
334 
335     /* Check that this is the name we're looking for and a value was provided */
336     if ( slen <= nlen || strncmp(s, name, nlen) || s[nlen] != '=' )
337         return -1;
338 
339     pval = simple_strtoll(&s[nlen + 1], &str, 10);
340 
341     /* Number not recognised */
342     if ( str != e )
343         return -2;
344 
345     *val = pval;
346 
347     return 0;
348 }
349 
cmdline_strcmp(const char * frag,const char * name)350 int cmdline_strcmp(const char *frag, const char *name)
351 {
352     for ( ; ; frag++, name++ )
353     {
354         unsigned char f = *frag, n = *name;
355         int res = f - n;
356 
357         if ( res || n == '\0' )
358         {
359             /*
360              * NUL in 'name' matching a comma, colon, semicolon or equals in
361              * 'frag' implies success.
362              */
363             if ( n == '\0' && (f == ',' || f == ':' || f == ';' || f == '=') )
364                 res = 0;
365 
366             return res;
367         }
368     }
369 }
370 
371 unsigned int tainted;
372 
373 /**
374  *      print_tainted - return a string to represent the kernel taint state.
375  *
376  *  'C' - Console output is synchronous.
377  *  'E' - An error (e.g. a machine check exceptions) has been injected.
378  *  'H' - HVM forced emulation prefix is permitted.
379  *  'I' - Platform is insecure (usually due to an errata on the platform).
380  *  'M' - Machine had a machine check experience.
381  *  'S' - Out of spec CPU (Incompatible features on one or more cores).
382  *
383  *      The string is overwritten by the next call to print_taint().
384  */
print_tainted(char * str)385 char *print_tainted(char *str)
386 {
387     if ( tainted )
388     {
389         snprintf(str, TAINT_STRING_MAX_LEN, "Tainted: %c%c%c%c%c%c",
390                  tainted & TAINT_MACHINE_INSECURE ? 'I' : ' ',
391                  tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
392                  tainted & TAINT_SYNC_CONSOLE ? 'C' : ' ',
393                  tainted & TAINT_ERROR_INJECT ? 'E' : ' ',
394                  tainted & TAINT_HVM_FEP ? 'H' : ' ',
395                  tainted & TAINT_CPU_OUT_OF_SPEC ? 'S' : ' ');
396     }
397     else
398     {
399         snprintf(str, TAINT_STRING_MAX_LEN, "Not tainted");
400     }
401 
402     return str;
403 }
404 
add_taint(unsigned int taint)405 void add_taint(unsigned int taint)
406 {
407     tainted |= taint;
408 }
409 
410 extern const initcall_t __initcall_start[], __presmp_initcall_end[],
411     __initcall_end[];
412 
do_presmp_initcalls(void)413 void __init do_presmp_initcalls(void)
414 {
415     const initcall_t *call;
416     for ( call = __initcall_start; call < __presmp_initcall_end; call++ )
417         (*call)();
418 }
419 
do_initcalls(void)420 void __init do_initcalls(void)
421 {
422     const initcall_t *call;
423     for ( call = __presmp_initcall_end; call < __initcall_end; call++ )
424         (*call)();
425 }
426 
427 #ifdef CONFIG_HYPFS
428 static unsigned int __read_mostly major_version;
429 static unsigned int __read_mostly minor_version;
430 
431 static HYPFS_DIR_INIT(buildinfo, "buildinfo");
432 static HYPFS_DIR_INIT(compileinfo, "compileinfo");
433 static HYPFS_DIR_INIT(version, "version");
434 static HYPFS_UINT_INIT(major, "major", major_version);
435 static HYPFS_UINT_INIT(minor, "minor", minor_version);
436 static HYPFS_STRING_INIT(changeset, "changeset");
437 static HYPFS_STRING_INIT(compiler, "compiler");
438 static HYPFS_STRING_INIT(compile_by, "compile_by");
439 static HYPFS_STRING_INIT(compile_date, "compile_date");
440 static HYPFS_STRING_INIT(compile_domain, "compile_domain");
441 static HYPFS_STRING_INIT(extra, "extra");
442 
443 #ifdef CONFIG_HYPFS_CONFIG
444 static HYPFS_STRING_INIT(config, "config");
445 #endif
446 
buildinfo_init(void)447 static int __init cf_check buildinfo_init(void)
448 {
449     hypfs_add_dir(&hypfs_root, &buildinfo, true);
450 
451     hypfs_string_set_reference(&changeset, xen_changeset());
452     hypfs_add_leaf(&buildinfo, &changeset, true);
453 
454     hypfs_add_dir(&buildinfo, &compileinfo, true);
455     hypfs_string_set_reference(&compiler, xen_compiler());
456     hypfs_string_set_reference(&compile_by, xen_compile_by());
457     hypfs_string_set_reference(&compile_date, xen_compile_date());
458     hypfs_string_set_reference(&compile_domain, xen_compile_domain());
459     hypfs_add_leaf(&compileinfo, &compiler, true);
460     hypfs_add_leaf(&compileinfo, &compile_by, true);
461     hypfs_add_leaf(&compileinfo, &compile_date, true);
462     hypfs_add_leaf(&compileinfo, &compile_domain, true);
463 
464     major_version = xen_major_version();
465     minor_version = xen_minor_version();
466     hypfs_add_dir(&buildinfo, &version, true);
467     hypfs_string_set_reference(&extra, xen_extra_version());
468     hypfs_add_leaf(&version, &extra, true);
469     hypfs_add_leaf(&version, &major, true);
470     hypfs_add_leaf(&version, &minor, true);
471 
472 #ifdef CONFIG_HYPFS_CONFIG
473     config.e.encoding = XEN_HYPFS_ENC_GZIP;
474     config.e.size = xen_config_data_size;
475     config.u.content = xen_config_data;
476     hypfs_add_leaf(&buildinfo, &config, true);
477 #endif
478 
479     return 0;
480 }
481 __initcall(buildinfo_init);
482 
483 static HYPFS_DIR_INIT(params, "params");
484 
param_init(void)485 static int __init cf_check param_init(void)
486 {
487     struct param_hypfs *param;
488 
489     hypfs_add_dir(&hypfs_root, &params, true);
490 
491     for ( param = __paramhypfs_start; param < __paramhypfs_end; param++ )
492     {
493         if ( param->init_leaf )
494             param->init_leaf(param);
495         else if ( param->hypfs.e.type == XEN_HYPFS_TYPE_STRING )
496             param->hypfs.e.size = strlen(param->hypfs.u.content) + 1;
497         hypfs_add_leaf(&params, &param->hypfs, true);
498     }
499 
500     return 0;
501 }
502 __initcall(param_init);
503 #endif
504 
do_xen_version(int cmd,XEN_GUEST_HANDLE_PARAM (void)arg)505 long do_xen_version(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
506 {
507     bool deny = xsm_xen_version(XSM_OTHER, cmd);
508 
509     switch ( cmd )
510     {
511     case XENVER_version:
512         return (xen_major_version() << 16) | xen_minor_version();
513 
514     case XENVER_extraversion:
515     {
516         xen_extraversion_t extraversion;
517 
518         memset(extraversion, 0, sizeof(extraversion));
519         safe_strcpy(extraversion, deny ? xen_deny() : xen_extra_version());
520         if ( copy_to_guest(arg, extraversion, ARRAY_SIZE(extraversion)) )
521             return -EFAULT;
522         return 0;
523     }
524 
525     case XENVER_compile_info:
526     {
527         xen_compile_info_t info;
528 
529         memset(&info, 0, sizeof(info));
530         safe_strcpy(info.compiler,       deny ? xen_deny() : xen_compiler());
531         safe_strcpy(info.compile_by,     deny ? xen_deny() : xen_compile_by());
532         safe_strcpy(info.compile_domain, deny ? xen_deny() : xen_compile_domain());
533         safe_strcpy(info.compile_date,   deny ? xen_deny() : xen_compile_date());
534         if ( copy_to_guest(arg, &info, 1) )
535             return -EFAULT;
536         return 0;
537     }
538 
539     case XENVER_capabilities:
540     {
541         xen_capabilities_info_t info;
542 
543         memset(info, 0, sizeof(info));
544         if ( !deny )
545             arch_get_xen_caps(&info);
546 
547         if ( copy_to_guest(arg, info, ARRAY_SIZE(info)) )
548             return -EFAULT;
549         return 0;
550     }
551 
552     case XENVER_platform_parameters:
553     {
554         const struct vcpu *curr = current;
555 
556 #ifdef CONFIG_COMPAT
557         if ( curr->hcall_compat )
558         {
559             compat_platform_parameters_t params = {
560                 .virt_start = is_pv_vcpu(curr)
561                             ? HYPERVISOR_COMPAT_VIRT_START(curr->domain)
562                             : 0,
563             };
564 
565             if ( copy_to_guest(arg, &params, 1) )
566                 return -EFAULT;
567         }
568         else
569 #endif
570         {
571             xen_platform_parameters_t params = {
572                 /*
573                  * Out of an abundance of caution, retain the useless return
574                  * value for 64bit PV guests, but in release builds only.
575                  *
576                  * This is not expected to cause any problems, but if it does,
577                  * the developer impacted will be the one best suited to fix
578                  * the caller not to issue this hypercall.
579                  */
580                 .virt_start = !IS_ENABLED(CONFIG_DEBUG) && is_pv_vcpu(curr)
581                               ? HYPERVISOR_VIRT_START
582                               : 0,
583             };
584 
585             if ( copy_to_guest(arg, &params, 1) )
586                 return -EFAULT;
587         }
588 
589         return 0;
590 
591     }
592 
593     case XENVER_changeset:
594     {
595         xen_changeset_info_t chgset;
596 
597         memset(chgset, 0, sizeof(chgset));
598         safe_strcpy(chgset, deny ? xen_deny() : xen_changeset());
599         if ( copy_to_guest(arg, chgset, ARRAY_SIZE(chgset)) )
600             return -EFAULT;
601         return 0;
602     }
603 
604     case XENVER_get_features:
605     {
606         xen_feature_info_t fi;
607         struct domain *d = current->domain;
608 
609         if ( copy_from_guest(&fi, arg, 1) )
610             return -EFAULT;
611 
612         switch ( fi.submap_idx )
613         {
614         case 0:
615             fi.submap = (1U << XENFEAT_memory_op_vnode_supported) |
616 #ifdef CONFIG_X86
617                         (1U << XENFEAT_vcpu_time_phys_area) |
618 #endif
619                         (1U << XENFEAT_runstate_phys_area);
620             if ( VM_ASSIST(d, pae_extended_cr3) )
621                 fi.submap |= (1U << XENFEAT_pae_pgdir_above_4gb);
622             if ( paging_mode_translate(d) )
623                 fi.submap |=
624                     (1U << XENFEAT_writable_page_tables) |
625                     (1U << XENFEAT_auto_translated_physmap);
626             if ( is_hardware_domain(d) )
627                 fi.submap |= 1U << XENFEAT_dom0;
628 #ifdef CONFIG_ARM
629             fi.submap |= (1U << XENFEAT_ARM_SMCCC_supported);
630 #endif
631 #ifdef CONFIG_X86
632             if ( is_pv_domain(d) )
633                 fi.submap |= (1U << XENFEAT_mmu_pt_update_preserve_ad) |
634                              (1U << XENFEAT_highmem_assist) |
635                              (1U << XENFEAT_gnttab_map_avail_bits);
636             else
637                 fi.submap |= (1U << XENFEAT_hvm_safe_pvclock) |
638                              (1U << XENFEAT_hvm_callback_vector) |
639                              (has_pirq(d) ? (1U << XENFEAT_hvm_pirqs) : 0);
640             fi.submap |= (1U << XENFEAT_dm_msix_all_writes);
641 #endif
642             if ( !paging_mode_translate(d) || is_domain_direct_mapped(d) )
643                 fi.submap |= (1U << XENFEAT_direct_mapped);
644             else
645                 fi.submap |= (1U << XENFEAT_not_direct_mapped);
646             break;
647         default:
648             return -EINVAL;
649         }
650 
651         if ( __copy_to_guest(arg, &fi, 1) )
652             return -EFAULT;
653         return 0;
654     }
655 
656     case XENVER_pagesize:
657         if ( deny )
658             return 0;
659         return (!guest_handle_is_null(arg) ? -EINVAL : PAGE_SIZE);
660 
661     case XENVER_guest_handle:
662     {
663         xen_domain_handle_t hdl;
664 
665         if ( deny )
666             memset(&hdl, 0, ARRAY_SIZE(hdl));
667 
668         BUILD_BUG_ON(ARRAY_SIZE(current->domain->handle) != ARRAY_SIZE(hdl));
669 
670         if ( copy_to_guest(arg, deny ? hdl : current->domain->handle,
671                            ARRAY_SIZE(hdl) ) )
672             return -EFAULT;
673         return 0;
674     }
675 
676     case XENVER_commandline:
677     {
678         size_t len = ARRAY_SIZE(saved_cmdline);
679 
680         if ( deny )
681             len = strlen(xen_deny()) + 1;
682 
683         if ( copy_to_guest(arg, deny ? xen_deny() : saved_cmdline, len) )
684             return -EFAULT;
685         return 0;
686     }
687 
688     case XENVER_build_id:
689     {
690         xen_build_id_t build_id;
691         unsigned int sz;
692         int rc;
693         const void *p;
694 
695         if ( deny )
696             return -EPERM;
697 
698         /* Only return size. */
699         if ( !guest_handle_is_null(arg) )
700         {
701             if ( copy_from_guest(&build_id, arg, 1) )
702                 return -EFAULT;
703 
704             if ( build_id.len == 0 )
705                 return -EINVAL;
706         }
707 
708         rc = xen_build_id(&p, &sz);
709         if ( rc )
710             return rc;
711 
712         if ( guest_handle_is_null(arg) )
713             return sz;
714 
715         if ( sz > build_id.len )
716             return -ENOBUFS;
717 
718         if ( copy_to_guest_offset(arg, offsetof(xen_build_id_t, buf), p, sz) )
719             return -EFAULT;
720 
721         return sz;
722     }
723     }
724 
725     return -ENOSYS;
726 }
727 
728 /*
729  * Local variables:
730  * mode: C
731  * c-file-style: "BSD"
732  * c-basic-offset: 4
733  * tab-width: 4
734  * indent-tabs-mode: nil
735  * End:
736  */
737