|
|
15d06e |
From 9292a4637e8f4d534f4dde70e8e5451f61ad0162 Mon Sep 17 00:00:00 2001
|
|
|
15d06e |
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
|
15d06e |
Date: Tue, 19 Jan 2021 14:22:33 +0000
|
|
|
15d06e |
Subject: [PATCH] Update common/ submodule to latest upstream.
|
|
|
15d06e |
|
|
|
15d06e |
Only for RHEL AV 8.4.0, allowing this branch to be compiled
|
|
|
15d06e |
from git with libguestfs 1.44.
|
|
|
15d06e |
---
|
|
|
15d06e |
common | 2 +-
|
|
|
15d06e |
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
15d06e |
|
|
|
15d06e |
Submodule common 9338df5e...be09523d:
|
|
|
15d06e |
diff --git a/common/mlcustomize/SELinux_relabel.ml b/common/mlcustomize/SELinux_relabel.ml
|
|
|
15d06e |
index 44995df6..5ecf7bd7 100644
|
|
|
15d06e |
--- a/common/mlcustomize/SELinux_relabel.ml
|
|
|
15d06e |
+++ b/common/mlcustomize/SELinux_relabel.ml
|
|
|
15d06e |
@@ -28,65 +28,80 @@ module G = Guestfs
|
|
|
15d06e |
let array_find a l =
|
|
|
15d06e |
List.mem a (Array.to_list l)
|
|
|
15d06e |
|
|
|
15d06e |
-let relabel (g : G.guestfs) =
|
|
|
15d06e |
- (* Is the guest using SELinux? *)
|
|
|
15d06e |
- if g#is_file ~followsymlinks:true "/usr/sbin/load_policy" &&
|
|
|
15d06e |
- g#is_file ~followsymlinks:true "/etc/selinux/config" then (
|
|
|
15d06e |
- (* Is setfiles / SELinux relabelling functionality available? *)
|
|
|
15d06e |
- if g#feature_available [| "selinuxrelabel" |] then (
|
|
|
15d06e |
- (* Use Augeas to parse /etc/selinux/config. *)
|
|
|
15d06e |
- g#aug_init "/" (16+32) (* AUG_SAVE_NOOP | AUG_NO_LOAD *);
|
|
|
15d06e |
- (* See: https://bugzilla.redhat.com/show_bug.cgi?id=975412#c0 *)
|
|
|
15d06e |
- ignore (g#aug_rm "/augeas/load/*[\"/etc/selinux/config/\" !~ regexp('^') + glob(incl) + regexp('/.*')]");
|
|
|
15d06e |
- g#aug_load ();
|
|
|
15d06e |
- debug_augeas_errors g;
|
|
|
15d06e |
-
|
|
|
15d06e |
- (* Get the SELinux policy name, eg. "targeted", "minimum".
|
|
|
15d06e |
- * Use "targeted" if not specified, just like libselinux does.
|
|
|
15d06e |
- *)
|
|
|
15d06e |
- let policy =
|
|
|
15d06e |
- let config_path = "/files/etc/selinux/config" in
|
|
|
15d06e |
- let selinuxtype_path = config_path ^ "/SELINUXTYPE" in
|
|
|
15d06e |
- let keys = g#aug_ls config_path in
|
|
|
15d06e |
- if array_find selinuxtype_path keys then
|
|
|
15d06e |
- g#aug_get selinuxtype_path
|
|
|
15d06e |
- else
|
|
|
15d06e |
- "targeted" in
|
|
|
15d06e |
-
|
|
|
15d06e |
- g#aug_close ();
|
|
|
15d06e |
-
|
|
|
15d06e |
- (* Get the spec file name. *)
|
|
|
15d06e |
- let specfile =
|
|
|
15d06e |
- sprintf "/etc/selinux/%s/contexts/files/file_contexts" policy in
|
|
|
15d06e |
-
|
|
|
15d06e |
- (* RHEL 6.2 - 6.5 had a malformed specfile that contained the
|
|
|
15d06e |
- * invalid regular expression "/var/run/spice-vdagentd.\pid"
|
|
|
15d06e |
- * (instead of "\.p"). This stops setfiles from working on
|
|
|
15d06e |
- * the guest.
|
|
|
15d06e |
- *
|
|
|
15d06e |
- * Because an SELinux relabel writes all over the filesystem,
|
|
|
15d06e |
- * it seems reasonable to fix this problem in the specfile
|
|
|
15d06e |
- * at the same time. (RHBZ#1374232)
|
|
|
15d06e |
- *)
|
|
|
15d06e |
- if g#grep ~fixed:true "vdagentd.\\pid" specfile <> [||] then (
|
|
|
15d06e |
- debug "fixing invalid regular expression in %s" specfile;
|
|
|
15d06e |
- let old_specfile = specfile ^ "~" in
|
|
|
15d06e |
- g#mv specfile old_specfile;
|
|
|
15d06e |
- let content = g#read_file old_specfile in
|
|
|
15d06e |
- let content =
|
|
|
15d06e |
- String.replace content "vdagentd.\\pid" "vdagentd\\.pid" in
|
|
|
15d06e |
- g#write specfile content;
|
|
|
15d06e |
- g#copy_attributes ~all:true old_specfile specfile
|
|
|
15d06e |
- );
|
|
|
15d06e |
-
|
|
|
15d06e |
- (* Relabel everything. *)
|
|
|
15d06e |
- g#selinux_relabel ~force:true specfile "/";
|
|
|
15d06e |
-
|
|
|
15d06e |
- (* If that worked, we don't need to autorelabel. *)
|
|
|
15d06e |
+let rec relabel (g : G.guestfs) =
|
|
|
15d06e |
+ (* Is the guest using SELinux? (Otherwise this is a no-op). *)
|
|
|
15d06e |
+ if is_selinux_guest g then (
|
|
|
15d06e |
+ try
|
|
|
15d06e |
+ use_setfiles g;
|
|
|
15d06e |
+ (* That worked, so we don't need to autorelabel. *)
|
|
|
15d06e |
g#rm_f "/.autorelabel"
|
|
|
15d06e |
- )
|
|
|
15d06e |
- else (
|
|
|
15d06e |
- (* SELinux guest, but not SELinux host. Fallback to this. *)
|
|
|
15d06e |
+ with Failure _ ->
|
|
|
15d06e |
+ (* This is the fallback in case something in the setfiles
|
|
|
15d06e |
+ * method didn't work. That includes the case where a non-SELinux
|
|
|
15d06e |
+ * host is processing an SELinux guest, and other things.
|
|
|
15d06e |
+ *)
|
|
|
15d06e |
g#touch "/.autorelabel"
|
|
|
15d06e |
- )
|
|
|
15d06e |
)
|
|
|
15d06e |
+
|
|
|
15d06e |
+and is_selinux_guest g =
|
|
|
15d06e |
+ g#is_file ~followsymlinks:true "/usr/sbin/load_policy" &&
|
|
|
15d06e |
+ g#is_file ~followsymlinks:true "/etc/selinux/config"
|
|
|
15d06e |
+
|
|
|
15d06e |
+and use_setfiles g =
|
|
|
15d06e |
+ (* Is setfiles / SELinux relabelling functionality available? *)
|
|
|
15d06e |
+ if not (g#feature_available [| "selinuxrelabel" |]) then
|
|
|
15d06e |
+ failwith "no selinux relabel feature";
|
|
|
15d06e |
+
|
|
|
15d06e |
+ (* Use Augeas to parse /etc/selinux/config. *)
|
|
|
15d06e |
+ g#aug_init "/" (16+32) (* AUG_SAVE_NOOP | AUG_NO_LOAD *);
|
|
|
15d06e |
+ (* See: https://bugzilla.redhat.com/show_bug.cgi?id=975412#c0 *)
|
|
|
15d06e |
+ ignore (g#aug_rm "/augeas/load/*[\"/etc/selinux/config/\" !~ regexp('^') + glob(incl) + regexp('/.*')]");
|
|
|
15d06e |
+ g#aug_load ();
|
|
|
15d06e |
+ debug_augeas_errors g;
|
|
|
15d06e |
+
|
|
|
15d06e |
+ (* Get the SELinux policy name, eg. "targeted", "minimum".
|
|
|
15d06e |
+ * Use "targeted" if not specified, just like libselinux does.
|
|
|
15d06e |
+ *)
|
|
|
15d06e |
+ let policy =
|
|
|
15d06e |
+ let config_path = "/files/etc/selinux/config" in
|
|
|
15d06e |
+ let selinuxtype_path = config_path ^ "/SELINUXTYPE" in
|
|
|
15d06e |
+ let keys = g#aug_ls config_path in
|
|
|
15d06e |
+ if array_find selinuxtype_path keys then
|
|
|
15d06e |
+ g#aug_get selinuxtype_path
|
|
|
15d06e |
+ else
|
|
|
15d06e |
+ "targeted" in
|
|
|
15d06e |
+
|
|
|
15d06e |
+ g#aug_close ();
|
|
|
15d06e |
+
|
|
|
15d06e |
+ (* Get the spec file name. *)
|
|
|
15d06e |
+ let specfile =
|
|
|
15d06e |
+ sprintf "/etc/selinux/%s/contexts/files/file_contexts" policy in
|
|
|
15d06e |
+
|
|
|
15d06e |
+ (* If the spec file doesn't exist then fall back to using
|
|
|
15d06e |
+ * autorelabel (RHBZ#1828952).
|
|
|
15d06e |
+ *)
|
|
|
15d06e |
+ if not (g#is_file ~followsymlinks:true specfile) then
|
|
|
15d06e |
+ failwith "no spec file";
|
|
|
15d06e |
+
|
|
|
15d06e |
+ (* RHEL 6.2 - 6.5 had a malformed specfile that contained the
|
|
|
15d06e |
+ * invalid regular expression "/var/run/spice-vdagentd.\pid"
|
|
|
15d06e |
+ * (instead of "\.p"). This stops setfiles from working on
|
|
|
15d06e |
+ * the guest.
|
|
|
15d06e |
+ *
|
|
|
15d06e |
+ * Because an SELinux relabel writes all over the filesystem,
|
|
|
15d06e |
+ * it seems reasonable to fix this problem in the specfile
|
|
|
15d06e |
+ * at the same time. (RHBZ#1374232)
|
|
|
15d06e |
+ *)
|
|
|
15d06e |
+ if g#grep ~fixed:true "vdagentd.\\pid" specfile <> [||] then (
|
|
|
15d06e |
+ debug "fixing invalid regular expression in %s" specfile;
|
|
|
15d06e |
+ let old_specfile = specfile ^ "~" in
|
|
|
15d06e |
+ g#mv specfile old_specfile;
|
|
|
15d06e |
+ let content = g#read_file old_specfile in
|
|
|
15d06e |
+ let content =
|
|
|
15d06e |
+ String.replace content "vdagentd.\\pid" "vdagentd\\.pid" in
|
|
|
15d06e |
+ g#write specfile content;
|
|
|
15d06e |
+ g#copy_attributes ~all:true old_specfile specfile
|
|
|
15d06e |
+ );
|
|
|
15d06e |
+
|
|
|
15d06e |
+ (* Relabel everything. *)
|
|
|
15d06e |
+ g#selinux_relabel ~force:true specfile "/"
|
|
|
15d06e |
diff --git a/common/mltools/Makefile.am b/common/mltools/Makefile.am
|
|
|
15d06e |
index 3b4172db..aea2dce9 100644
|
|
|
15d06e |
--- a/common/mltools/Makefile.am
|
|
|
15d06e |
+++ b/common/mltools/Makefile.am
|
|
|
15d06e |
@@ -95,6 +95,7 @@ libmltools_a_CPPFLAGS = \
|
|
|
15d06e |
-I$(shell $(OCAMLC) -where) \
|
|
|
15d06e |
-I$(top_srcdir)/common/utils \
|
|
|
15d06e |
-I$(top_srcdir)/lib \
|
|
|
15d06e |
+ $(INCLUDE_DIRECTORY) \
|
|
|
15d06e |
-I$(top_srcdir)/common/options \
|
|
|
15d06e |
-I$(top_srcdir)/common/mlgettext \
|
|
|
15d06e |
-I$(top_srcdir)/common/mlpcre \
|
|
|
15d06e |
diff --git a/common/mltools/tools_utils.ml b/common/mltools/tools_utils.ml
|
|
|
15d06e |
index 12718022..d54ec581 100644
|
|
|
15d06e |
--- a/common/mltools/tools_utils.ml
|
|
|
15d06e |
+++ b/common/mltools/tools_utils.ml
|
|
|
15d06e |
@@ -679,3 +679,53 @@ let with_timeout op timeout ?(sleep = 2) fn =
|
|
|
15d06e |
loop ()
|
|
|
15d06e |
in
|
|
|
15d06e |
loop ()
|
|
|
15d06e |
+
|
|
|
15d06e |
+let run_in_guest_command g root ?logfile ?incompatible_fn cmd =
|
|
|
15d06e |
+ (* Is the host_cpu compatible with the guest arch? ie. Can we
|
|
|
15d06e |
+ * run commands in this guest?
|
|
|
15d06e |
+ *)
|
|
|
15d06e |
+ let guest_arch = g#inspect_get_arch root in
|
|
|
15d06e |
+ let guest_arch_compatible = guest_arch_compatible guest_arch in
|
|
|
15d06e |
+ if not guest_arch_compatible then (
|
|
|
15d06e |
+ match incompatible_fn with
|
|
|
15d06e |
+ | None -> ()
|
|
|
15d06e |
+ | Some fn -> fn ()
|
|
|
15d06e |
+ )
|
|
|
15d06e |
+ else (
|
|
|
15d06e |
+ (* Add a prologue to the scripts:
|
|
|
15d06e |
+ * - Pass environment variables through from the host.
|
|
|
15d06e |
+ * - Optionally send stdout and stderr to a log file so we capture
|
|
|
15d06e |
+ * all output in error messages.
|
|
|
15d06e |
+ * - Use setarch when running x86_64 host + i686 guest.
|
|
|
15d06e |
+ *)
|
|
|
15d06e |
+ let env_vars =
|
|
|
15d06e |
+ List.filter_map (
|
|
|
15d06e |
+ fun name ->
|
|
|
15d06e |
+ try Some (sprintf "export %s=%s" name (quote (Sys.getenv name)))
|
|
|
15d06e |
+ with Not_found -> None
|
|
|
15d06e |
+ ) [ "http_proxy"; "https_proxy"; "ftp_proxy"; "no_proxy" ] in
|
|
|
15d06e |
+ let env_vars = String.concat "\n" env_vars ^ "\n" in
|
|
|
15d06e |
+
|
|
|
15d06e |
+ let cmd =
|
|
|
15d06e |
+ match Guestfs_config.host_cpu, guest_arch with
|
|
|
15d06e |
+ | "x86_64", ("i386"|"i486"|"i586"|"i686") ->
|
|
|
15d06e |
+ sprintf "setarch i686 <<\"__EOCMD\"
|
|
|
15d06e |
+%s
|
|
|
15d06e |
+__EOCMD
|
|
|
15d06e |
+" cmd
|
|
|
15d06e |
+ | _ -> cmd in
|
|
|
15d06e |
+
|
|
|
15d06e |
+ let logfile_redirect =
|
|
|
15d06e |
+ match logfile with
|
|
|
15d06e |
+ | None -> ""
|
|
|
15d06e |
+ | Some logfile -> sprintf "exec >>%s 2>&1" (quote logfile) in
|
|
|
15d06e |
+
|
|
|
15d06e |
+ let cmd = sprintf "\
|
|
|
15d06e |
+%s
|
|
|
15d06e |
+%s
|
|
|
15d06e |
+%s
|
|
|
15d06e |
+" (logfile_redirect) env_vars cmd in
|
|
|
15d06e |
+
|
|
|
15d06e |
+ debug "running command:\n%s" cmd;
|
|
|
15d06e |
+ ignore (g#sh cmd)
|
|
|
15d06e |
+ )
|
|
|
15d06e |
diff --git a/common/mltools/tools_utils.mli b/common/mltools/tools_utils.mli
|
|
|
15d06e |
index ab70f583..1d1ac8a8 100644
|
|
|
15d06e |
--- a/common/mltools/tools_utils.mli
|
|
|
15d06e |
+++ b/common/mltools/tools_utils.mli
|
|
|
15d06e |
@@ -195,9 +195,8 @@ val is_btrfs_subvolume : Guestfs.guestfs -> string -> bool
|
|
|
15d06e |
(** Checks if a filesystem is a btrfs subvolume. *)
|
|
|
15d06e |
|
|
|
15d06e |
val inspect_decrypt : Guestfs.guestfs -> key_store -> unit
|
|
|
15d06e |
-(** Simple implementation of decryption: look for any [crypto_LUKS]
|
|
|
15d06e |
- partitions and decrypt them, then rescan for VGs. This only works
|
|
|
15d06e |
- for Fedora whole-disk encryption. *)
|
|
|
15d06e |
+(** Simple implementation of decryption: look for any encrypted
|
|
|
15d06e |
+ partitions and decrypt them, then rescan for VGs. *)
|
|
|
15d06e |
|
|
|
15d06e |
val with_timeout : string -> int -> ?sleep:int -> (unit -> 'a option) -> 'a
|
|
|
15d06e |
(** [with_timeout op timeout ?sleep fn] implements a timeout loop.
|
|
|
15d06e |
@@ -212,3 +211,13 @@ val with_timeout : string -> int -> ?sleep:int -> (unit -> 'a option) -> 'a
|
|
|
15d06e |
calls {!error} and the program exits. The error message will
|
|
|
15d06e |
contain the diagnostic string [op] to identify the operation
|
|
|
15d06e |
which timed out. *)
|
|
|
15d06e |
+
|
|
|
15d06e |
+val run_in_guest_command : Guestfs.guestfs -> string -> ?logfile:string -> ?incompatible_fn:(unit -> unit) -> string -> unit
|
|
|
15d06e |
+(** [run_in_guest_command g root ?incompatible_archs_fn cmd]
|
|
|
15d06e |
+ runs a command in the guest, which is already mounted for the
|
|
|
15d06e |
+ specified [root]. The command is run directly in case the
|
|
|
15d06e |
+ architecture of the host and the guest are compatible, optionally
|
|
|
15d06e |
+ calling [?incompatible_fn] in case they are not.
|
|
|
15d06e |
+
|
|
|
15d06e |
+ [?logfile] is an optional file in the guest to where redirect
|
|
|
15d06e |
+ stdout and stderr of the command. *)
|
|
|
15d06e |
diff --git a/common/mlutils/unix_utils-c.c b/common/mlutils/unix_utils-c.c
|
|
|
15d06e |
index 33099611..8acf0395 100644
|
|
|
15d06e |
--- a/common/mlutils/unix_utils-c.c
|
|
|
15d06e |
+++ b/common/mlutils/unix_utils-c.c
|
|
|
15d06e |
@@ -77,6 +77,7 @@ extern value guestfs_int_mllib_mkdtemp (value val_pattern);
|
|
|
15d06e |
extern value guestfs_int_mllib_realpath (value pathv);
|
|
|
15d06e |
extern value guestfs_int_mllib_statvfs_statvfs (value pathv);
|
|
|
15d06e |
extern value guestfs_int_mllib_statvfs_is_network_filesystem (value pathv);
|
|
|
15d06e |
+extern value guestfs_int_mllib_sysconf_nr_processors_online (value unitv);
|
|
|
15d06e |
|
|
|
15d06e |
/* NB: This is a "noalloc" call. */
|
|
|
15d06e |
value
|
|
|
15d06e |
@@ -368,3 +369,17 @@ guestfs_int_mllib_statvfs_is_network_filesystem (value pathv)
|
|
|
15d06e |
return Val_bool (0);
|
|
|
15d06e |
#endif
|
|
|
15d06e |
}
|
|
|
15d06e |
+
|
|
|
15d06e |
+/* NB: This is a "noalloc" call. */
|
|
|
15d06e |
+value
|
|
|
15d06e |
+guestfs_int_mllib_sysconf_nr_processors_online (value unitv)
|
|
|
15d06e |
+{
|
|
|
15d06e |
+#ifdef _SC_NPROCESSORS_ONLN
|
|
|
15d06e |
+ long n;
|
|
|
15d06e |
+
|
|
|
15d06e |
+ n = sysconf (_SC_NPROCESSORS_ONLN);
|
|
|
15d06e |
+ if (n > 0) return Val_int (n);
|
|
|
15d06e |
+#endif
|
|
|
15d06e |
+ /* Return a safe value so that callers don't need to deal with errors. */
|
|
|
15d06e |
+ return Val_int (1);
|
|
|
15d06e |
+}
|
|
|
15d06e |
diff --git a/common/mlutils/unix_utils.ml b/common/mlutils/unix_utils.ml
|
|
|
15d06e |
index 52eb824d..2bdda12a 100644
|
|
|
15d06e |
--- a/common/mlutils/unix_utils.ml
|
|
|
15d06e |
+++ b/common/mlutils/unix_utils.ml
|
|
|
15d06e |
@@ -84,3 +84,8 @@ module StatVFS = struct
|
|
|
15d06e |
external is_network_filesystem : string -> bool =
|
|
|
15d06e |
"guestfs_int_mllib_statvfs_is_network_filesystem" "noalloc"
|
|
|
15d06e |
end
|
|
|
15d06e |
+
|
|
|
15d06e |
+module Sysconf = struct
|
|
|
15d06e |
+ external nr_processors_online : unit -> int =
|
|
|
15d06e |
+ "guestfs_int_mllib_sysconf_nr_processors_online" "noalloc"
|
|
|
15d06e |
+end
|
|
|
15d06e |
diff --git a/common/mlutils/unix_utils.mli b/common/mlutils/unix_utils.mli
|
|
|
15d06e |
index 4fcea4a3..aead4df2 100644
|
|
|
15d06e |
--- a/common/mlutils/unix_utils.mli
|
|
|
15d06e |
+++ b/common/mlutils/unix_utils.mli
|
|
|
15d06e |
@@ -121,3 +121,12 @@ module StatVFS : sig
|
|
|
15d06e |
(** [is_network_filesystem path] returns true if [path] is located on
|
|
|
15d06e |
a network filesystem such as NFS or CIFS. *)
|
|
|
15d06e |
end
|
|
|
15d06e |
+
|
|
|
15d06e |
+module Sysconf : sig
|
|
|
15d06e |
+ val nr_processors_online : unit -> int
|
|
|
15d06e |
+ (** [nr_processors_online ()] returns the number of processors
|
|
|
15d06e |
+ currently online, from [sysconf (_SC_NPROCESSORS_ONLN)].
|
|
|
15d06e |
+
|
|
|
15d06e |
+ Note this never fails. In case we cannot get the number of
|
|
|
15d06e |
+ cores it returns 1. *)
|
|
|
15d06e |
+end
|
|
|
15d06e |
diff --git a/common/options/Makefile.am b/common/options/Makefile.am
|
|
|
15d06e |
index f7ea7493..162d143b 100644
|
|
|
15d06e |
--- a/common/options/Makefile.am
|
|
|
15d06e |
+++ b/common/options/Makefile.am
|
|
|
15d06e |
@@ -41,8 +41,9 @@ liboptions_la_SOURCES = \
|
|
|
15d06e |
liboptions_la_CPPFLAGS = \
|
|
|
15d06e |
-DGUESTFS_NO_DEPRECATED=1 \
|
|
|
15d06e |
-I$(top_srcdir)/common/utils -I$(top_builddir)/common/utils \
|
|
|
15d06e |
+ -I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \
|
|
|
15d06e |
-I$(top_srcdir)/lib -I$(top_builddir)/lib \
|
|
|
15d06e |
- -I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib
|
|
|
15d06e |
+ $(INCLUDE_DIRECTORY)
|
|
|
15d06e |
liboptions_la_CFLAGS = \
|
|
|
15d06e |
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
|
|
|
15d06e |
$(LIBCONFIG_CFLAGS) \
|
|
|
15d06e |
diff --git a/common/options/decrypt.c b/common/options/decrypt.c
|
|
|
15d06e |
index 683cf5ed..434b7d58 100644
|
|
|
15d06e |
--- a/common/options/decrypt.c
|
|
|
15d06e |
+++ b/common/options/decrypt.c
|
|
|
15d06e |
@@ -25,6 +25,7 @@
|
|
|
15d06e |
|
|
|
15d06e |
#include <stdio.h>
|
|
|
15d06e |
#include <stdlib.h>
|
|
|
15d06e |
+#include <stdbool.h>
|
|
|
15d06e |
#include <string.h>
|
|
|
15d06e |
#include <libintl.h>
|
|
|
15d06e |
#include <error.h>
|
|
|
15d06e |
@@ -38,18 +39,18 @@
|
|
|
15d06e |
|
|
|
15d06e |
/**
|
|
|
15d06e |
* Make a LUKS map name from the partition name,
|
|
|
15d06e |
- * eg. C<"/dev/vda2" =E<gt> "luksvda2">
|
|
|
15d06e |
+ * eg. C<"/dev/vda2" =E<gt> "cryptvda2">
|
|
|
15d06e |
*/
|
|
|
15d06e |
static void
|
|
|
15d06e |
make_mapname (const char *device, char *mapname, size_t len)
|
|
|
15d06e |
{
|
|
|
15d06e |
size_t i = 0;
|
|
|
15d06e |
|
|
|
15d06e |
- if (len < 5)
|
|
|
15d06e |
+ if (len < 6)
|
|
|
15d06e |
abort ();
|
|
|
15d06e |
- strcpy (mapname, "luks");
|
|
|
15d06e |
- mapname += 4;
|
|
|
15d06e |
- len -= 4;
|
|
|
15d06e |
+ strcpy (mapname, "crypt");
|
|
|
15d06e |
+ mapname += 5;
|
|
|
15d06e |
+ len -= 5;
|
|
|
15d06e |
|
|
|
15d06e |
if (STRPREFIX (device, "/dev/"))
|
|
|
15d06e |
i = 5;
|
|
|
15d06e |
@@ -65,10 +66,8 @@ make_mapname (const char *device, char *mapname, size_t len)
|
|
|
15d06e |
}
|
|
|
15d06e |
|
|
|
15d06e |
/**
|
|
|
15d06e |
- * Simple implementation of decryption: look for any C<crypto_LUKS>
|
|
|
15d06e |
- * partitions and decrypt them, then rescan for VGs. This only works
|
|
|
15d06e |
- * for Fedora whole-disk encryption. WIP to make this work for other
|
|
|
15d06e |
- * encryption schemes.
|
|
|
15d06e |
+ * Simple implementation of decryption: look for any encrypted
|
|
|
15d06e |
+ * partitions and decrypt them, then rescan for VGs.
|
|
|
15d06e |
*/
|
|
|
15d06e |
void
|
|
|
15d06e |
inspect_do_decrypt (guestfs_h *g, struct key_store *ks)
|
|
|
15d06e |
@@ -82,12 +81,21 @@ inspect_do_decrypt (guestfs_h *g, struct key_store *ks)
|
|
|
15d06e |
|
|
|
15d06e |
for (i = 0; partitions[i] != NULL; ++i) {
|
|
|
15d06e |
CLEANUP_FREE char *type = guestfs_vfs_type (g, partitions[i]);
|
|
|
15d06e |
- if (type && STREQ (type, "crypto_LUKS")) {
|
|
|
15d06e |
+ if (type &&
|
|
|
15d06e |
+ (STREQ (type, "crypto_LUKS") || STREQ (type, "BitLocker"))) {
|
|
|
15d06e |
+ bool is_bitlocker = STREQ (type, "BitLocker");
|
|
|
15d06e |
char mapname[32];
|
|
|
15d06e |
make_mapname (partitions[i], mapname, sizeof mapname);
|
|
|
15d06e |
|
|
|
15d06e |
#ifdef GUESTFS_HAVE_LUKS_UUID
|
|
|
15d06e |
- CLEANUP_FREE char *uuid = guestfs_luks_uuid (g, partitions[i]);
|
|
|
15d06e |
+ CLEANUP_FREE char *uuid = NULL;
|
|
|
15d06e |
+
|
|
|
15d06e |
+ /* This fails for Windows BitLocker disks because cryptsetup
|
|
|
15d06e |
+ * luksUUID cannot read a UUID (unclear if this is a limitation
|
|
|
15d06e |
+ * of the format or cryptsetup).
|
|
|
15d06e |
+ */
|
|
|
15d06e |
+ if (!is_bitlocker)
|
|
|
15d06e |
+ uuid = guestfs_luks_uuid (g, partitions[i]);
|
|
|
15d06e |
#else
|
|
|
15d06e |
const char *uuid = NULL;
|
|
|
15d06e |
#endif
|
|
|
15d06e |
@@ -97,11 +105,15 @@ inspect_do_decrypt (guestfs_h *g, struct key_store *ks)
|
|
|
15d06e |
|
|
|
15d06e |
/* Try each key in turn. */
|
|
|
15d06e |
for (j = 0; keys[j] != NULL; ++j) {
|
|
|
15d06e |
- /* XXX Should we call guestfs_luks_open_ro if readonly flag
|
|
|
15d06e |
+ /* XXX Should we set GUESTFS_CRYPTSETUP_OPEN_READONLY if readonly
|
|
|
15d06e |
* is set? This might break 'mount_ro'.
|
|
|
15d06e |
*/
|
|
|
15d06e |
guestfs_push_error_handler (g, NULL, NULL);
|
|
|
15d06e |
+#ifdef GUESTFS_HAVE_CRYPTSETUP_OPEN
|
|
|
15d06e |
+ r = guestfs_cryptsetup_open (g, partitions[i], keys[j], mapname, -1);
|
|
|
15d06e |
+#else
|
|
|
15d06e |
r = guestfs_luks_open (g, partitions[i], keys[j], mapname);
|
|
|
15d06e |
+#endif
|
|
|
15d06e |
guestfs_pop_error_handler (g);
|
|
|
15d06e |
if (r == 0)
|
|
|
15d06e |
goto opened;
|
|
|
15d06e |
diff --git a/common/options/uri.c b/common/options/uri.c
|
|
|
15d06e |
index ac36bccb..6b696fc2 100644
|
|
|
15d06e |
--- a/common/options/uri.c
|
|
|
15d06e |
+++ b/common/options/uri.c
|
|
|
15d06e |
@@ -194,6 +194,7 @@ parse (const char *arg, char **path_ret, char **protocol_ret,
|
|
|
15d06e |
if (path && path[0] == '/' &&
|
|
|
15d06e |
(STREQ (uri->scheme, "gluster") ||
|
|
|
15d06e |
STREQ (uri->scheme, "iscsi") ||
|
|
|
15d06e |
+ STREQ (uri->scheme, "nbd") ||
|
|
|
15d06e |
STREQ (uri->scheme, "rbd") ||
|
|
|
15d06e |
STREQ (uri->scheme, "sheepdog")))
|
|
|
15d06e |
path++;
|
|
|
15d06e |
diff --git a/common/utils/guestfs-stringlists-utils.h b/common/utils/guestfs-stringlists-utils.h
|
|
|
15d06e |
index 0bac1587..ade3b6f3 100644
|
|
|
15d06e |
--- a/common/utils/guestfs-stringlists-utils.h
|
|
|
15d06e |
+++ b/common/utils/guestfs-stringlists-utils.h
|
|
|
15d06e |
@@ -21,7 +21,8 @@
|
|
|
15d06e |
|
|
|
15d06e |
/* stringlists-utils.c */
|
|
|
15d06e |
extern void guestfs_int_free_string_list (char **);
|
|
|
15d06e |
-extern size_t guestfs_int_count_strings (char *const *);
|
|
|
15d06e |
+extern size_t guestfs_int_count_strings (char *const *)
|
|
|
15d06e |
+ __attribute__((__nonnull__ (1)));
|
|
|
15d06e |
extern char *guestfs_int_concat_strings (char *const *);
|
|
|
15d06e |
extern char **guestfs_int_copy_string_list (char *const *);
|
|
|
15d06e |
extern char *guestfs_int_join_strings (const char *sep, char *const *);
|