Skip to content

Commit 1d0aae5

Browse files
authored
Merge pull request #5874 from psafont/private/paus/minions
2 parents 1c92485 + 5dc2900 commit 1d0aae5

File tree

1 file changed

+52
-57
lines changed

1 file changed

+52
-57
lines changed

ocaml/xapi/xapi_xenops.ml

Lines changed: 52 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -337,19 +337,40 @@ let rtc_timeoffset_of_vm ~__context (vm, vm_t) vbds =
337337
)
338338
)
339339

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
353374

354375
let builder_of_vm ~__context (vmref, vm) timeoffset pci_passthrough vgpu =
355376
let open Vm in
@@ -372,19 +393,12 @@ let builder_of_vm ~__context (vmref, vm) timeoffset pci_passthrough vgpu =
372393
Cirrus
373394
in
374395
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
379397
match s with
380398
| None ->
381399
[]
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
388402
in
389403
let make_hvmloader_boot_record () =
390404
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 =
427441
; acpi= bool vm.API.vM_platform true "acpi"
428442
; serial=
429443
((* The platform value should override the other_config value. If
430-
* neither are set, use pty. *)
444+
neither are set, use pty. *)
431445
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
439448
match (other_config_value, platform_value) with
440449
| None, None ->
441450
Some "pty"
@@ -444,10 +453,7 @@ let builder_of_vm ~__context (vmref, vm) timeoffset pci_passthrough vgpu =
444453
| Some value, None ->
445454
Some value
446455
)
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
451457
; vnc_ip= None (*None PR-1255*)
452458
; pci_emulations
453459
; pci_passthrough
@@ -464,30 +470,19 @@ let builder_of_vm ~__context (vmref, vm) timeoffset pci_passthrough vgpu =
464470
; tpm= tpm_of_vm ()
465471
}
466472
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]))
488481
in
482+
let kernel = resolve "kernel" ~path:kernel in
483+
let ramdisk = Option.map (fun k -> resolve "ramdisk" ~path:k) ramdisk in
489484
{
490-
boot= Direct {kernel= k; cmdline= ka; ramdisk= initrd}
485+
boot= Direct {kernel; cmdline= ka; ramdisk}
491486
; framebuffer= bool vm.API.vM_platform false "pvfb"
492487
; framebuffer_ip= None (* None PR-1255 *)
493488
; vncterm= not (List.mem_assoc "disable_pv_vnc" vm.API.vM_other_config)

0 commit comments

Comments
 (0)