debuggers.hg

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