@@ -337,19 +337,40 @@ let rtc_timeoffset_of_vm ~__context (vm, vm_t) vbds =
337
337
)
338
338
)
339
339
340
- (* /boot/ contains potentially sensitive files like xen-initrd, so we will only*)
341
- (* allow directly booting guests from the subfolder /boot/guest/ *)
342
- let allowed_dom0_directories_for_boot_files =
343
- [" /boot/guest/" ; " /var/lib/xcp/guest" ]
344
-
345
- let is_boot_file_whitelisted filename =
346
- let safe_str str = not (String. has_substr str " .." ) in
347
- (* make sure the script prefix is the allowed dom0 directory *)
348
- List. exists
349
- (fun allowed -> String. starts_with ~prefix: allowed filename)
350
- allowed_dom0_directories_for_boot_files
351
- (* avoid ..-style attacks and other weird things *)
352
- && safe_str filename
340
+ let allowed_dom0_directories_for_boot_files = [" /var/lib/xcp/guest/" ]
341
+
342
+ let kernel_path filename =
343
+ let ( let * ) = Result. bind in
344
+ let * real_path =
345
+ try Ok (Unix. realpath filename) with
346
+ | Unix. (Unix_error (ENOENT, _ , _ )) ->
347
+ let reason = " File does not exist" in
348
+ Error (filename, reason)
349
+ | exn ->
350
+ let reason = Printexc. to_string exn in
351
+ Error (filename, reason)
352
+ in
353
+ let * () =
354
+ match Unix. stat real_path with
355
+ | {st_kind = Unix. S_REG ; _} ->
356
+ Ok ()
357
+ | _ ->
358
+ let reason = " Is not a regular file" in
359
+ Error (filename, reason)
360
+ in
361
+ let allowed =
362
+ List. exists
363
+ (fun allowed -> String. starts_with ~prefix: allowed real_path)
364
+ allowed_dom0_directories_for_boot_files
365
+ in
366
+ if not allowed then
367
+ let reason =
368
+ Printf. sprintf " Is not in any of the allowed kernel directories: [%s]"
369
+ (String. concat " ; " allowed_dom0_directories_for_boot_files)
370
+ in
371
+ Error (filename, reason)
372
+ else
373
+ Ok real_path
353
374
354
375
let builder_of_vm ~__context (vmref , vm ) timeoffset pci_passthrough vgpu =
355
376
let open Vm in
@@ -372,19 +393,12 @@ let builder_of_vm ~__context (vmref, vm) timeoffset pci_passthrough vgpu =
372
393
Cirrus
373
394
in
374
395
let pci_emulations =
375
- let s =
376
- try Some (List. assoc " mtc_pci_emulations" vm.API. vM_other_config)
377
- with _ -> None
378
- in
396
+ let s = List. assoc_opt " mtc_pci_emulations" vm.API. vM_other_config in
379
397
match s with
380
398
| None ->
381
399
[]
382
- | Some x -> (
383
- try
384
- let l = String. split ',' x in
385
- List. map (String. strip String. isspace) l
386
- with _ -> []
387
- )
400
+ | Some x ->
401
+ String. split_on_char ',' x |> List. map String. trim
388
402
in
389
403
let make_hvmloader_boot_record () =
390
404
if bool vm.API. vM_platform false " qemu_stubdom" then
@@ -427,15 +441,10 @@ let builder_of_vm ~__context (vmref, vm) timeoffset pci_passthrough vgpu =
427
441
; acpi= bool vm.API. vM_platform true " acpi"
428
442
; serial=
429
443
((* The platform value should override the other_config value. If
430
- * neither are set, use pty. *)
444
+ neither are set, use pty. *)
431
445
let key = " hvm_serial" in
432
- let other_config_value =
433
- try Some (List. assoc key vm.API. vM_other_config)
434
- with Not_found -> None
435
- in
436
- let platform_value =
437
- try Some (List. assoc key vm.API. vM_platform) with Not_found -> None
438
- in
446
+ let other_config_value = List. assoc_opt key vm.API. vM_other_config in
447
+ let platform_value = List. assoc_opt key vm.API. vM_platform in
439
448
match (other_config_value, platform_value) with
440
449
| None , None ->
441
450
Some " pty"
@@ -444,10 +453,7 @@ let builder_of_vm ~__context (vmref, vm) timeoffset pci_passthrough vgpu =
444
453
| Some value , None ->
445
454
Some value
446
455
)
447
- ; keymap=
448
- ( try Some (List. assoc " keymap" vm.API. vM_platform)
449
- with Not_found -> None
450
- )
456
+ ; keymap= List. assoc_opt " keymap" vm.API. vM_platform
451
457
; vnc_ip= None (* None PR-1255*)
452
458
; pci_emulations
453
459
; pci_passthrough
@@ -464,30 +470,19 @@ let builder_of_vm ~__context (vmref, vm) timeoffset pci_passthrough vgpu =
464
470
; tpm= tpm_of_vm ()
465
471
}
466
472
in
467
- let make_direct_boot_record
468
- {Helpers. kernel = k ; kernel_args = ka ; ramdisk = initrd } =
469
- let k =
470
- if is_boot_file_whitelisted k then
471
- k
472
- else (
473
- debug " kernel %s is not in the whitelist: ignoring" k ;
474
- " "
475
- )
476
- in
477
- let initrd =
478
- Option. map
479
- (fun x ->
480
- if is_boot_file_whitelisted x then
481
- x
482
- else (
483
- debug " initrd %s is not in the whitelist: ignoring" k ;
484
- " "
485
- )
486
- )
487
- initrd
473
+ let make_direct_boot_record {Helpers. kernel; kernel_args = ka ; ramdisk} =
474
+ let resolve name ~path =
475
+ match kernel_path path with
476
+ | Ok k ->
477
+ k
478
+ | Error (file , msg ) ->
479
+ info {|% s : refusing to load % s "%s" : % s|} __FUNCTION__ name file msg ;
480
+ raise Api_errors. (Server_error (invalid_value, [name; file; msg]))
488
481
in
482
+ let kernel = resolve " kernel" ~path: kernel in
483
+ let ramdisk = Option. map (fun k -> resolve " ramdisk" ~path: k) ramdisk in
489
484
{
490
- boot= Direct {kernel= k ; cmdline= ka; ramdisk= initrd }
485
+ boot= Direct {kernel; cmdline= ka; ramdisk}
491
486
; framebuffer= bool vm.API. vM_platform false " pvfb"
492
487
; framebuffer_ip= None (* None PR-1255 *)
493
488
; vncterm= not (List. mem_assoc " disable_pv_vnc" vm.API. vM_other_config)
0 commit comments