Skip to content

Commit

Permalink
ci: Disable sandboxing by default
Browse files Browse the repository at this point in the history
The ~/Applications/DkMLNative is not a path added
to the predefined OCaml sandbox, and more importantly
the user can change the installation path to anything.

So [ocaml] and related executables can't be found in the sandbox.

+bugfix: Recursively delete the temp dir

Part of diskuv/dkml-installer-ocaml#80
  • Loading branch information
Jonah Beckford committed Nov 27, 2023
1 parent ae10b46 commit ea586be
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 35 deletions.
16 changes: 13 additions & 3 deletions src/dkml-exe/cmd_init.ml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ let enable_imprecise_c99_float_ops_t =
in
Arg.(value & flag & info [ "enable-imprecise-c99-float-ops" ] ~doc)

let disable_sandboxing_t =
let doc =
"Disables the creation of sandboxes during `opam install` commands. Poorly \
written or malicious opam packages may erase or modify files on your \
macOS and Linux machines. Ignored for Windows and all other non-macOS and \
non-Linux machines."
in
Arg.(value & flag & info [ "disable-sandboxing" ] ~doc)

let non_system_opt = "non-system-compiler"

let non_system_compiler_t =
Expand Down Expand Up @@ -106,10 +115,11 @@ let create_local_switch ~system_cfg ~scripts_dir_fp ~yes ~non_system_compiler
Ok (128 + signal)

let run f_setup localdir_fp_opt yes non_system_compiler system_only
enable_imprecise_c99_float_ops =
enable_imprecise_c99_float_ops disable_sandboxing =
let enable_imprecise_c99_float_ops =
if enable_imprecise_c99_float_ops then Some () else None
in
let disable_sandboxing = if disable_sandboxing then Some () else None in
f_setup () >>= fun () ->
OS.Dir.with_tmp "dkml-initsystem-de-%s" (* de = dkml-exe *)
(fun dir_fp () ->
Expand Down Expand Up @@ -146,8 +156,8 @@ let run f_setup localdir_fp_opt yes non_system_compiler system_only
ignore temp_dir;
Ok system_cfg
in
Dkml_runtimelib.init_system ?enable_imprecise_c99_float_ops ~f_temp_dir
~f_system_cfg ()
Dkml_runtimelib.init_system ?enable_imprecise_c99_float_ops
?disable_sandboxing ~f_temp_dir ~f_system_cfg ()
>>= fun ec ->
if ec <> 0 then exit ec;
(* Create local switch *)
Expand Down
3 changes: 2 additions & 1 deletion src/dkml-exe/dkml_exe_lib.ml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ let init_t =
const rresult_to_term_result
$ (const Cmd_init.run $ const setup $ localdir_opt_t $ yes_t
$ Cmd_init.non_system_compiler_t $ Cmd_init.system_only_t
$ Cmd_init.enable_imprecise_c99_float_ops_t))
$ Cmd_init.enable_imprecise_c99_float_ops_t
$ Cmd_init.disable_sandboxing_t))

let init_info =
Cmd.info
Expand Down
1 change: 1 addition & 0 deletions src/runtimelib/dkml_runtimelib.mli
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ val get_msys2_create_opam_switch_options : SystemConfig.msys2_t -> string list

val init_system :
?enable_imprecise_c99_float_ops:unit ->
?disable_sandboxing:unit ->
?delete_temp_dir_after_init:unit ->
f_temp_dir:(unit -> (Fpath.t, Rresult.R.msg) result) ->
f_system_cfg:
Expand Down
90 changes: 61 additions & 29 deletions src/runtimelib/init_system.ml
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,18 @@ let create_playground_switch ~system_cfg ~ocaml_home_fp ~opamroot_dir_fp =
(* Run the command *)
run_command cmd rel_fp

let create_opam_root ~opamroot_dir_fp ~ocaml_home_fp ~system_cfg =
let create_opam_root ?disable_sandboxing ?reinit ~opamroot_dir_fp ~ocaml_home_fp
~system_cfg () =
(* Assemble command line arguments *)
let open Opam_context.SystemConfig in
let* rel_fp =
Fpath.of_string "vendor/drd/src/unix/private/init-opam-root.sh"
in
let init_opam_root_fp = Fpath.(system_cfg.scripts_dir_fp // rel_fp) in
let disable_sandboxing_args =
match disable_sandboxing with Some () -> [ "-x" ] | None -> []
in
let reinit_args = match reinit with Some () -> [ "-i" ] | None -> [] in
let cmd =
Cmd.of_list
(system_cfg.env_exe_wrapper
Expand All @@ -67,7 +72,8 @@ let create_opam_root ~opamroot_dir_fp ~ocaml_home_fp ~system_cfg =
Fpath.to_string opamroot_dir_fp;
"-v";
Fpath.to_string ocaml_home_fp;
])
]
@ disable_sandboxing_args @ reinit_args)
in
(* Run the command *)
run_command cmd rel_fp
Expand Down Expand Up @@ -130,12 +136,14 @@ let critical_vsstudio_files =
type opamroot_status =
| Opamroot_missing
| Opamroot_no_repository
| Opamroot_complete
| Opamroot_complete_with_sandbox
| Opamroot_complete_without_sandbox

let get_opamroot_status () =
let* opamroot_dir_fp = Lazy.force Opam_context.get_opam_root in
let* opamroot_exists = OS.File.exists Fpath.(opamroot_dir_fp / "config") in
if opamroot_exists then
let config = Fpath.(opamroot_dir_fp / "config") in
let* config_exists = OS.File.exists config in
if config_exists then
let* dkml_version = Lazy.force Dkml_context.get_dkmlversion_or_default in
(* COMPLETE: The diskuv-<VERSION> repository must exist *)
let* diskuv_repo =
Expand All @@ -149,8 +157,23 @@ let get_opamroot_status () =
opamroot_dir_fp / "repo"
/ Printf.sprintf "diskuv-%s.tar.gz" dkml_version)
in
(* Does <opamroot>/config have:
wrap-build-commands:
["%{hooks}%/sandbox.sh" "build"] {os = "linux" | os = "macos"}
wrap-install-commands:
["%{hooks}%/sandbox.sh" "install"] {os = "linux" | os = "macos"}
wrap-remove-commands:
["%{hooks}%/sandbox.sh" "remove"] {os = "linux" | os = "macos"}
*)
let* config_contents = OS.File.read config in
let config_contains_sandbox =
Astring.String.find_sub ~sub:"%{hooks}%/sandbox.sh" config_contents
|> Option.is_some
in
let state =
if diskuv_repo || diskuv_repo_targz then Opamroot_complete
if diskuv_repo || diskuv_repo_targz then
if config_contains_sandbox then Opamroot_complete_with_sandbox
else Opamroot_complete_without_sandbox
else Opamroot_no_repository
in
Ok state
Expand Down Expand Up @@ -214,8 +237,8 @@ let verify_git ~msg_why_check_git ~what_install =
git') to install it.")
else Ok ()

let init_system_helper ?enable_imprecise_c99_float_ops ~f_system_cfg ~temp_dir
() =
let init_system_helper ?enable_imprecise_c99_float_ops ?disable_sandboxing
~f_system_cfg ~temp_dir () =
(*
DEVELOPER NOTE:
Expand Down Expand Up @@ -278,26 +301,35 @@ let init_system_helper ?enable_imprecise_c99_float_ops ~f_system_cfg ~temp_dir
let* ec =
let what_install = "\"opam root\" package cache" in
match opamroot_status with
| Opamroot_complete -> Ok 0
| Opamroot_missing ->
let msg_why =
"Detected that the \"opam root\" package cache is not present."
in
let* () = verify_git ~msg_why_check_git:msg_why ~what_install in
Logs.warn (fun l ->
l "%s Creating it now. ETA: 10 minutes." msg_why);
let* system_cfg = Lazy.force system_cfg in
create_opam_root ~opamroot_dir_fp ~ocaml_home_fp ~system_cfg
| Opamroot_no_repository ->
let msg_why =
"Detected that the \"opam root\" package cache is missing the \
DkML repository."
| Opamroot_complete_without_sandbox -> Ok 0
| Opamroot_complete_with_sandbox when disable_sandboxing = None ->
Ok 0
| Opamroot_missing | Opamroot_no_repository
| Opamroot_complete_with_sandbox ->
let msg_why, action, reinit =
match opamroot_status with
| Opamroot_no_repository ->
( "Detected that the \"opam root\" package cache is \
missing the DkML repository.",
"Creating it",
None )
| Opamroot_complete_with_sandbox ->
( "Detected that the \"opam root\" package cache is \
configured for sandboxing.",
"Disabling sandboxing",
Some () )
| _ ->
( "Detected that the \"opam root\" package cache is not \
present.",
"Creating it",
None )
in
let* () = verify_git ~msg_why_check_git:msg_why ~what_install in
Logs.warn (fun l ->
l "%s Creating it now. ETA: 10 minutes." msg_why);
l "%s %s now. ETA: 10 minutes." msg_why action);
let* system_cfg = Lazy.force system_cfg in
create_opam_root ~opamroot_dir_fp ~ocaml_home_fp ~system_cfg
create_opam_root ?disable_sandboxing ?reinit ~opamroot_dir_fp
~ocaml_home_fp ~system_cfg ()
in
if ec <> 0 then Ok ec (* short-circuit exit if signal raised *)
else
Expand All @@ -316,15 +348,15 @@ let init_system_helper ?enable_imprecise_c99_float_ops ~f_system_cfg ~temp_dir
let* system_cfg = Lazy.force system_cfg in
create_playground_switch ~opamroot_dir_fp ~ocaml_home_fp ~system_cfg)

let init_system ?enable_imprecise_c99_float_ops ?delete_temp_dir_after_init
~f_temp_dir ~f_system_cfg () =
let init_system ?enable_imprecise_c99_float_ops ?disable_sandboxing
?delete_temp_dir_after_init ~f_temp_dir ~f_system_cfg () =
let* temp_dir = f_temp_dir () in
let delayed_error = ref (Ok 0) in
let* ec =
Fun.protect
~finally:(fun () ->
if Option.is_some delete_temp_dir_after_init then
match OS.Dir.delete temp_dir with
match OS.Dir.delete ~recurse:true temp_dir with
| Ok () -> ()
| Error (`Msg msg) -> (
match !delayed_error with
Expand All @@ -340,7 +372,7 @@ let init_system ?enable_imprecise_c99_float_ops ?delete_temp_dir_after_init
Fpath.pp temp_dir msg)))
(fun () ->
let* (_created : bool) = OS.Dir.create temp_dir in
init_system_helper ?enable_imprecise_c99_float_ops ~f_system_cfg
~temp_dir ())
init_system_helper ?enable_imprecise_c99_float_ops ?disable_sandboxing
~f_system_cfg ~temp_dir ())
in
match !delayed_error with Ok _ -> Ok ec | Error e -> Error e
7 changes: 5 additions & 2 deletions src/with-dkml/with_dkml.ml
Original file line number Diff line number Diff line change
Expand Up @@ -607,8 +607,11 @@ let main_with_result () =
(* Now we finish gathering information to create switches *)
Dkml_runtimelib.SystemConfig.create ~scripts_dir_fp ()
in
Dkml_runtimelib.init_system ~delete_temp_dir_after_init:() ~f_temp_dir
~f_system_cfg ()
(* By default we disable sandboxing so that macOS/Unix actually work
out-of-the-box. If the user wants something different, they
can do [dkml init --system <options>] before. *)
Dkml_runtimelib.init_system ~disable_sandboxing:()
~delete_temp_dir_after_init:() ~f_temp_dir ~f_system_cfg ()
>>= fun ec ->
if ec <> 0 then exit ec;
(* EIGHTH, stop tracing variables from propagating. *)
Expand Down

0 comments on commit ea586be

Please sign in to comment.