debuggers.hg

annotate xen/common/kernel.c @ 22855:1d1eec7e1fb4

xl: Perform minimal validation of virtual disk file while parsing config file

This patch performs some very basic validation on the virtual disk
file passed through the config file. This validation ensures that we
don't go too far with the initialization like spawn qemu and more
while there could be some potentially fundamental issues.

[ Patch fixed up to work with PHYSTYPE_EMPTY 22808:6ec61438713a -iwj ]

Signed-off-by: Kamala Narasimhan <kamala.narasimhan@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Kamala Narasimhan <kamala.narasimhan@gmail.com>
date Tue Jan 25 18:09:49 2011 +0000 (2011-01-25)
parents e8acb9753ff1
children
rev   line source
kaf24@718 1 /******************************************************************************
kaf24@718 2 * kernel.c
kaf24@718 3 *
kaf24@5548 4 * Copyright (c) 2002-2005 K A Fraser
kaf24@718 5 */
kaf24@718 6
kaf24@1248 7 #include <xen/config.h>
kaf24@3372 8 #include <xen/init.h>
kaf24@1248 9 #include <xen/lib.h>
kaf24@1248 10 #include <xen/errno.h>
kfraser@10919 11 #include <xen/version.h>
kaf24@1248 12 #include <xen/sched.h>
Tim@15666 13 #include <xen/paging.h>
ack@13292 14 #include <xen/nmi.h>
kaf24@9197 15 #include <xen/guest_access.h>
cl349@5325 16 #include <asm/current.h>
Ian@8589 17 #include <public/nmi.h>
kaf24@5548 18 #include <public/version.h>
ack@13294 19 #ifdef CONFIG_X86
ack@13294 20 #include <asm/shared.h>
ack@13294 21 #endif
kaf24@3372 22
ack@13292 23 #ifndef COMPAT
ack@13292 24
kaf24@8869 25 int tainted;
kaf24@8869 26
keir@19830 27 xen_commandline_t saved_cmdline;
keir@19830 28
keir@22676 29 static void __init assign_integer_param(
keir@22676 30 struct kernel_param *param, uint64_t val)
keir@22676 31 {
keir@22676 32 switch ( param->len )
keir@22676 33 {
keir@22676 34 case sizeof(uint8_t):
keir@22676 35 *(uint8_t *)param->var = val;
keir@22676 36 break;
keir@22676 37 case sizeof(uint16_t):
keir@22676 38 *(uint16_t *)param->var = val;
keir@22676 39 break;
keir@22676 40 case sizeof(uint32_t):
keir@22676 41 *(uint32_t *)param->var = val;
keir@22676 42 break;
keir@22676 43 case sizeof(uint64_t):
keir@22676 44 *(uint64_t *)param->var = val;
keir@22676 45 break;
keir@22676 46 default:
keir@22676 47 BUG();
keir@22676 48 }
keir@22676 49 }
keir@22676 50
keir@22453 51 void __init cmdline_parse(char *cmdline)
iap10@274 52 {
kfraser@15547 53 char opt[100], *optval, *optkey, *q;
kfraser@13158 54 const char *p = cmdline;
kaf24@3376 55 struct kernel_param *param;
kfraser@15548 56 int bool_assert;
kfraser@15547 57
keir@19830 58 safe_strcpy(saved_cmdline, cmdline);
keir@19830 59
kaf24@5195 60 if ( p == NULL )
kaf24@5195 61 return;
kaf24@5195 62
kaf24@5195 63 for ( ; ; )
iap10@274 64 {
kaf24@5195 65 /* Skip whitespace. */
kaf24@5195 66 while ( *p == ' ' )
kaf24@5195 67 p++;
kaf24@5195 68 if ( *p == '\0' )
kaf24@3376 69 break;
kaf24@5195 70
kaf24@5195 71 /* Grab the next whitespace-delimited option. */
kfraser@15547 72 q = optkey = opt;
kaf24@5195 73 while ( (*p != ' ') && (*p != '\0') )
kaf24@9756 74 {
kaf24@9756 75 if ( (q-opt) < (sizeof(opt)-1) ) /* avoid overflow */
kaf24@9756 76 *q++ = *p;
kaf24@9756 77 p++;
kaf24@9756 78 }
kaf24@5195 79 *q = '\0';
kaf24@5195 80
kaf24@5195 81 /* Search for value part of a key=value option. */
kaf24@5195 82 optval = strchr(opt, '=');
kaf24@5195 83 if ( optval != NULL )
kaf24@9756 84 *optval++ = '\0'; /* nul-terminate the option value */
kaf24@9756 85 else
kaf24@9756 86 optval = q; /* default option value is empty string */
kaf24@5195 87
kfraser@15547 88 /* Boolean parameters can be inverted with 'no-' prefix. */
kfraser@15548 89 bool_assert = !!strncmp("no-", optkey, 3);
kfraser@15548 90 if ( !bool_assert )
kfraser@15547 91 optkey += 3;
kfraser@15547 92
adsharma@6569 93 for ( param = &__setup_start; param <= &__setup_end; param++ )
iap10@274 94 {
kfraser@15547 95 if ( strcmp(param->name, optkey) )
kaf24@3376 96 continue;
kaf24@5195 97
kaf24@3376 98 switch ( param->type )
iap10@274 99 {
kaf24@3376 100 case OPT_STR:
kfraser@13697 101 strlcpy(param->var, optval, param->len);
kaf24@3376 102 break;
kaf24@3376 103 case OPT_UINT:
keir@22676 104 assign_integer_param(
keir@22676 105 param,
keir@22676 106 simple_strtoll(optval, NULL, 0));
kaf24@3376 107 break;
kaf24@3376 108 case OPT_BOOL:
kfraser@15547 109 case OPT_INVBOOL:
keir@22453 110 if ( !parse_bool(optval) )
kfraser@15548 111 bool_assert = !bool_assert;
keir@22676 112 assign_integer_param(
keir@22676 113 param,
keir@22676 114 (param->type == OPT_BOOL) == bool_assert);
kaf24@3376 115 break;
keir@22676 116 case OPT_SIZE:
keir@22676 117 assign_integer_param(
keir@22676 118 param,
keir@22676 119 parse_size_and_unit(optval, NULL));
keir@20171 120 break;
kaf24@4888 121 case OPT_CUSTOM:
kfraser@13158 122 ((void (*)(const char *))param->var)(optval);
kaf24@4888 123 break;
keir@22676 124 default:
keir@22676 125 BUG();
keir@22676 126 break;
iap10@274 127 }
iap10@274 128 }
kaf24@1660 129 }
kaf24@718 130 }
iap10@274 131
keir@22453 132 int __init parse_bool(const char *s)
keir@22453 133 {
keir@22453 134 if ( !strcmp("no", s) ||
keir@22453 135 !strcmp("off", s) ||
keir@22453 136 !strcmp("false", s) ||
keir@22453 137 !strcmp("disable", s) ||
keir@22453 138 !strcmp("0", s) )
keir@22453 139 return 0;
keir@22453 140
keir@22453 141 if ( !strcmp("yes", s) ||
keir@22453 142 !strcmp("on", s) ||
keir@22453 143 !strcmp("true", s) ||
keir@22453 144 !strcmp("enable", s) ||
keir@22453 145 !strcmp("1", s) )
keir@22453 146 return 1;
keir@22453 147
keir@22453 148 return -1;
keir@22453 149 }
keir@22453 150
kaf24@8869 151 /**
kaf24@8869 152 * print_tainted - return a string to represent the kernel taint state.
kaf24@8869 153 *
kaf24@8869 154 * 'S' - SMP with CPUs not designed for SMP.
kaf24@8869 155 * 'M' - Machine had a machine check experience.
kaf24@8869 156 * 'B' - System has hit bad_page.
kaf24@8869 157 *
kaf24@8869 158 * The string is overwritten by the next call to print_taint().
kaf24@8869 159 */
kaf24@8869 160 char *print_tainted(char *str)
kaf24@8869 161 {
kaf24@8869 162 if ( tainted )
kaf24@8869 163 {
kaf24@10506 164 snprintf(str, TAINT_STRING_MAX_LEN, "Tainted: %c%c%c%c",
kaf24@8869 165 tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
kaf24@8869 166 tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
kaf24@10506 167 tainted & TAINT_BAD_PAGE ? 'B' : ' ',
kaf24@10506 168 tainted & TAINT_SYNC_CONSOLE ? 'C' : ' ');
kaf24@8869 169 }
kaf24@8869 170 else
kaf24@8869 171 {
kaf24@8869 172 snprintf(str, TAINT_STRING_MAX_LEN, "Not tainted");
kaf24@8869 173 }
kaf24@8869 174
kaf24@8869 175 return str;
kaf24@8869 176 }
kaf24@8869 177
kaf24@8869 178 void add_taint(unsigned flag)
kaf24@8869 179 {
kaf24@8869 180 tainted |= flag;
kaf24@8869 181 }
kaf24@8869 182
keir@21429 183 extern initcall_t __initcall_start, __presmp_initcall_end, __initcall_end;
keir@21429 184
keir@21429 185 void __init do_presmp_initcalls(void)
keir@21429 186 {
keir@21429 187 initcall_t *call;
keir@21429 188 for ( call = &__initcall_start; call < &__presmp_initcall_end; call++ )
keir@21429 189 (*call)();
keir@21429 190 }
keir@21429 191
keir@21429 192 void __init do_initcalls(void)
keir@21429 193 {
keir@21429 194 initcall_t *call;
keir@21429 195 for ( call = &__presmp_initcall_end; call < &__initcall_end; call++ )
keir@21429 196 (*call)();
keir@21429 197 }
keir@21429 198
ack@13292 199 # define DO(fn) long do_##fn
ack@13292 200
ack@13292 201 #endif
ack@13292 202
kaf24@1188 203 /*
kaf24@1594 204 * Simple hypercalls.
kaf24@1147 205 */
kaf24@1147 206
ack@13292 207 DO(xen_version)(int cmd, XEN_GUEST_HANDLE(void) arg)
kaf24@1147 208 {
kaf24@5548 209 switch ( cmd )
kaf24@5548 210 {
kaf24@5548 211 case XENVER_version:
kaf24@5548 212 {
kfraser@10919 213 return (xen_major_version() << 16) | xen_minor_version();
kaf24@5548 214 }
kaf24@5548 215
kaf24@5548 216 case XENVER_extraversion:
kaf24@5548 217 {
kaf24@5688 218 xen_extraversion_t extraversion;
kfraser@10919 219 safe_strcpy(extraversion, xen_extra_version());
kfraser@15437 220 if ( copy_to_guest(arg, extraversion, ARRAY_SIZE(extraversion)) )
kaf24@5548 221 return -EFAULT;
kaf24@5548 222 return 0;
kaf24@5548 223 }
kaf24@5548 224
kaf24@5548 225 case XENVER_compile_info:
kaf24@5548 226 {
kaf24@5548 227 struct xen_compile_info info;
kfraser@10919 228 safe_strcpy(info.compiler, xen_compiler());
kfraser@10919 229 safe_strcpy(info.compile_by, xen_compile_by());
kfraser@10919 230 safe_strcpy(info.compile_domain, xen_compile_domain());
kfraser@10919 231 safe_strcpy(info.compile_date, xen_compile_date());
kaf24@9197 232 if ( copy_to_guest(arg, &info, 1) )
kaf24@5548 233 return -EFAULT;
kaf24@5548 234 return 0;
kaf24@5548 235 }
vh249@6587 236
vh249@6587 237 case XENVER_capabilities:
vh249@6587 238 {
iap10@6741 239 xen_capabilities_info_t info;
ian@13775 240 extern void arch_get_xen_caps(xen_capabilities_info_t *info);
iap10@6741 241
kaf24@6743 242 memset(info, 0, sizeof(info));
ian@13775 243 arch_get_xen_caps(&info);
kaf24@6743 244
kfraser@15437 245 if ( copy_to_guest(arg, info, ARRAY_SIZE(info)) )
vh249@6587 246 return -EFAULT;
vh249@6587 247 return 0;
vh249@6587 248 }
vh249@6587 249
kaf24@7878 250 case XENVER_platform_parameters:
iap10@6741 251 {
kaf24@7878 252 xen_platform_parameters_t params = {
kaf24@7878 253 .virt_start = HYPERVISOR_VIRT_START
kaf24@7878 254 };
kaf24@9197 255 if ( copy_to_guest(arg, &params, 1) )
iap10@6741 256 return -EFAULT;
iap10@6741 257 return 0;
iap10@6741 258
iap10@6741 259 }
iap10@6741 260
vh249@6587 261 case XENVER_changeset:
vh249@6587 262 {
vh249@6587 263 xen_changeset_info_t chgset;
kfraser@10919 264 safe_strcpy(chgset, xen_changeset());
kfraser@15437 265 if ( copy_to_guest(arg, chgset, ARRAY_SIZE(chgset)) )
vh249@6587 266 return -EFAULT;
vh249@6587 267 return 0;
vh249@6587 268 }
Ian@8713 269
Ian@8713 270 case XENVER_get_features:
Ian@8713 271 {
Ian@8713 272 xen_feature_info_t fi;
kaf24@10304 273 struct domain *d = current->domain;
Ian@8713 274
kaf24@9197 275 if ( copy_from_guest(&fi, arg, 1) )
Ian@8713 276 return -EFAULT;
Ian@8713 277
Ian@8713 278 switch ( fi.submap_idx )
Ian@8713 279 {
Ian@8713 280 case 0:
kaf24@10304 281 fi.submap = 0;
kaf24@10304 282 if ( VM_ASSIST(d, VMASST_TYPE_pae_extended_cr3) )
kaf24@10304 283 fi.submap |= (1U << XENFEAT_pae_pgdir_above_4gb);
Tim@15666 284 if ( paging_mode_translate(current->domain) )
kaf24@8879 285 fi.submap |=
kaf24@8879 286 (1U << XENFEAT_writable_page_tables) |
kaf24@10211 287 (1U << XENFEAT_auto_translated_physmap);
kaf24@9029 288 if ( supervisor_mode_kernel )
kaf24@9029 289 fi.submap |= 1U << XENFEAT_supervisor_mode_kernel;
keir@16763 290 #ifdef CONFIG_X86
keir@16763 291 if ( !is_hvm_vcpu(current) )
keir@18762 292 fi.submap |= (1U << XENFEAT_mmu_pt_update_preserve_ad) |
keir@18788 293 (1U << XENFEAT_highmem_assist) |
keir@18788 294 (1U << XENFEAT_gnttab_map_avail_bits);
keir@21491 295 else
keir@21495 296 fi.submap |= (1U << XENFEAT_hvm_safe_pvclock) |
keir@22455 297 (1U << XENFEAT_hvm_callback_vector) |
keir@22455 298 (1U << XENFEAT_hvm_pirqs);
keir@16763 299 #endif
Ian@8713 300 break;
Ian@8713 301 default:
Ian@8713 302 return -EINVAL;
Ian@8713 303 }
Ian@8713 304
kaf24@9197 305 if ( copy_to_guest(arg, &fi, 1) )
Ian@8713 306 return -EFAULT;
Ian@8713 307 return 0;
Ian@8713 308 }
Ian@8713 309
kaf24@10527 310 case XENVER_pagesize:
kaf24@10527 311 {
kfraser@10536 312 return (!guest_handle_is_null(arg) ? -EINVAL : PAGE_SIZE);
kaf24@10527 313 }
kaf24@10527 314
kfraser@10986 315 case XENVER_guest_handle:
kfraser@10986 316 {
kfraser@15437 317 if ( copy_to_guest(arg, current->domain->handle,
kfraser@15437 318 ARRAY_SIZE(current->domain->handle)) )
kfraser@10986 319 return -EFAULT;
kfraser@10986 320 return 0;
keir@19830 321 }
keir@19830 322
keir@19830 323 case XENVER_commandline:
keir@19830 324 {
keir@19830 325 if ( copy_to_guest(arg, saved_cmdline, ARRAY_SIZE(saved_cmdline)) )
keir@19830 326 return -EFAULT;
keir@19830 327 return 0;
keir@19830 328 }
kaf24@5548 329 }
kaf24@5548 330
kaf24@5548 331 return -ENOSYS;
kaf24@1147 332 }
kaf24@1147 333
ack@13292 334 DO(nmi_op)(unsigned int cmd, XEN_GUEST_HANDLE(void) arg)
Ian@9747 335 {
kaf24@9197 336 struct xennmi_callback cb;
Ian@8589 337 long rc = 0;
Ian@8589 338
Ian@8589 339 switch ( cmd )
Ian@8589 340 {
Ian@8589 341 case XENNMI_register_callback:
kaf24@9197 342 rc = -EFAULT;
kaf24@9197 343 if ( copy_from_guest(&cb, arg, 1) )
kaf24@9197 344 break;
Ian@9747 345 rc = register_guest_nmi_callback(cb.handler_address);
Ian@8589 346 break;
Ian@8589 347 case XENNMI_unregister_callback:
Ian@9747 348 rc = unregister_guest_nmi_callback();
Ian@8589 349 break;
Ian@8589 350 default:
Ian@8589 351 rc = -ENOSYS;
Ian@8589 352 break;
Ian@8589 353 }
Ian@8589 354
Ian@8589 355 return rc;
Ian@8589 356 }
Ian@8589 357
ack@13292 358 DO(vm_assist)(unsigned int cmd, unsigned int type)
kaf24@2111 359 {
cl349@2957 360 return vm_assist(current->domain, cmd, type);
kaf24@2111 361 }
kaf24@2111 362
ack@13292 363 DO(ni_hypercall)(void)
kaf24@1147 364 {
kaf24@1594 365 /* No-op hypercall. */
kaf24@1147 366 return -ENOSYS;
kaf24@1147 367 }
kaf24@3952 368
kaf24@3952 369 /*
kaf24@3952 370 * Local variables:
kaf24@3952 371 * mode: C
kaf24@3952 372 * c-set-style: "BSD"
kaf24@3952 373 * c-basic-offset: 4
kaf24@3952 374 * tab-width: 4
kaf24@3952 375 * indent-tabs-mode: nil
kaf24@4026 376 * End:
kaf24@3952 377 */