[Libguestfs] [common PATCH 1/3] mlcustomize: Refactor SELinux_relabel code.

Pino Toscano
2020-09-23T15:57:48Z

From: "Richard W.M. Jones" <rjones@redhat.com>

This shouldn't change the effect of this code.
---
 mlcustomize/SELinux_relabel.ml | 121 ++++++++++++++++++---------------
 1 file changed, 65 insertions(+), 56 deletions(-)

diff --git a/mlcustomize/SELinux_relabel.ml b/mlcustomize/SELinux_relabel.ml
index 44995df..5df1f08 100644
--- a/mlcustomize/SELinux_relabel.ml
+++ b/mlcustomize/SELinux_relabel.ml
@@ -28,65 +28,74 @@ module G = Guestfs
 let array_find a l    List.mem a (Array.to_list l)

-let relabel (g : G.guestfs) -  (* Is the guest using SELinux? *)
-  if g#is_file ~followsymlinks:true "/usr/sbin/load_policy"
&&
-     g#is_file ~followsymlinks:true "/etc/selinux/config" then (
-    (* Is setfiles / SELinux relabelling functionality available? *)
-    if g#feature_available [| "selinuxrelabel" |] then (
-      (* Use Augeas to parse /etc/selinux/config. *)
-      g#aug_init "/" (16+32) (* AUG_SAVE_NOOP | AUG_NO_LOAD *);
-      (* See: https://bugzilla.redhat.com/show_bug.cgi?id=975412#c0 *)
-      ignore (g#aug_rm "/augeas/load/*[\"/etc/selinux/config/\"
!~ regexp('^') + glob(incl) + regexp('/.*')]");
-      g#aug_load ();
-      debug_augeas_errors g;
-
-      (* Get the SELinux policy name, eg. "targeted",
"minimum".
-       * Use "targeted" if not specified, just like libselinux does.
+let rec relabel (g : G.guestfs) +  (* Is the guest using SELinux?  (Otherwise
this is a no-op). *)
+  if is_selinux_guest g then (
+    try
+      use_setfiles g;
+      (* That worked, so we don't need to autorelabel. *)
+      g#rm_f "/.autorelabel"
+    with Failure _ ->
+      (* This is the fallback in case something in the setfiles
+       * method didn't work.  That includes the case where a non-SELinux
+       * host is processing an SELinux guest, and other things.
        *)
-      let policy -        let config_path =
"/files/etc/selinux/config" in
-        let selinuxtype_path = config_path ^ "/SELINUXTYPE" in
-        let keys = g#aug_ls config_path in
-        if array_find selinuxtype_path keys then
-          g#aug_get selinuxtype_path
-        else
-          "targeted" in
+      g#touch "/.autorelabel"
+  )

-      g#aug_close ();
+and is_selinux_guest g +  g#is_file ~followsymlinks:true
"/usr/sbin/load_policy" &&
+  g#is_file ~followsymlinks:true "/etc/selinux/config"

-      (* Get the spec file name. *)
-      let specfile -        sprintf
"/etc/selinux/%s/contexts/files/file_contexts" policy in
+and use_setfiles g +  (* Is setfiles / SELinux relabelling functionality
available? *)
+  if not (g#feature_available [| "selinuxrelabel" |]) then
+    failwith "no selinux relabel feature";

-      (* RHEL 6.2 - 6.5 had a malformed specfile that contained the
-       * invalid regular expression "/var/run/spice-vdagentd.\pid"
-       * (instead of "\.p").  This stops setfiles from working on
-       * the guest.
-       *
-       * Because an SELinux relabel writes all over the filesystem,
-       * it seems reasonable to fix this problem in the specfile
-       * at the same time.  (RHBZ#1374232)
-       *)
-      if g#grep ~fixed:true "vdagentd.\\pid" specfile <> [||]
then (
-        debug "fixing invalid regular expression in %s" specfile;
-        let old_specfile = specfile ^ "~" in
-        g#mv specfile old_specfile;
-        let content = g#read_file old_specfile in
-        let content -          String.replace content
"vdagentd.\\pid" "vdagentd\\.pid" in
-        g#write specfile content;
-        g#copy_attributes ~all:true old_specfile specfile
-      );
+  (* Use Augeas to parse /etc/selinux/config. *)
+  g#aug_init "/" (16+32) (* AUG_SAVE_NOOP | AUG_NO_LOAD *);
+  (* See: https://bugzilla.redhat.com/show_bug.cgi?id=975412#c0 *)
+  ignore (g#aug_rm "/augeas/load/*[\"/etc/selinux/config/\" !~
regexp('^') + glob(incl) + regexp('/.*')]");
+  g#aug_load ();
+  debug_augeas_errors g;

-      (* Relabel everything. *)
-      g#selinux_relabel ~force:true specfile "/";
+  (* Get the SELinux policy name, eg. "targeted",
"minimum".
+   * Use "targeted" if not specified, just like libselinux does.
+   *)
+  let policy +    let config_path = "/files/etc/selinux/config" in
+    let selinuxtype_path = config_path ^ "/SELINUXTYPE" in
+    let keys = g#aug_ls config_path in
+    if array_find selinuxtype_path keys then
+      g#aug_get selinuxtype_path
+    else
+      "targeted" in

-      (* If that worked, we don't need to autorelabel. *)
-      g#rm_f "/.autorelabel"
-    )
-    else (
-      (* SELinux guest, but not SELinux host.  Fallback to this. *)
-      g#touch "/.autorelabel"
-    )
-  )
+  g#aug_close ();
+
+  (* Get the spec file name. *)
+  let specfile +    sprintf
"/etc/selinux/%s/contexts/files/file_contexts" policy in
+
+  (* RHEL 6.2 - 6.5 had a malformed specfile that contained the
+   * invalid regular expression "/var/run/spice-vdagentd.\pid"
+   * (instead of "\.p").  This stops setfiles from working on
+   * the guest.
+   *
+   * Because an SELinux relabel writes all over the filesystem,
+   * it seems reasonable to fix this problem in the specfile
+   * at the same time.  (RHBZ#1374232)
+   *)
+  if g#grep ~fixed:true "vdagentd.\\pid" specfile <> [||] then
(
+    debug "fixing invalid regular expression in %s" specfile;
+    let old_specfile = specfile ^ "~" in
+    g#mv specfile old_specfile;
+    let content = g#read_file old_specfile in
+    let content +      String.replace content "vdagentd.\\pid"
"vdagentd\\.pid" in
+    g#write specfile content;
+    g#copy_attributes ~all:true old_specfile specfile
+  );
+
+  (* Relabel everything. *)
+  g#selinux_relabel ~force:true specfile "/"
--
2.26.2