mrc0mmand / rpms / libguestfs

Forked from rpms/libguestfs 3 years ago
Clone
Blob Blame History Raw
From 3bceb391d14aeebb21dd9742108fa98945a32c5c Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 5 May 2020 16:44:14 +0100
Subject: [PATCH] mlcustomize: Refactor SELinux_relabel code.

This shouldn't change the effect of this code.

Cherry picked from libguestfs-common
commit 3493d9fcaab6de1c09528e55a01bc24f0fb6c03c and backported
to libguestfs 1.40 branch (which predates the common submodule).
---
 customize/SELinux_relabel.ml | 127 +++++++++++++++++++----------------
 1 file changed, 68 insertions(+), 59 deletions(-)

diff --git a/customize/SELinux_relabel.ml b/customize/SELinux_relabel.ml
index 44995df6b..5df1f0895 100644
--- a/customize/SELinux_relabel.ml
+++ b/customize/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 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#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 "/";
-
-      (* If that worked, we don't need to autorelabel. *)
+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"
-    )
-    else (
-      (* SELinux guest, but not SELinux host.  Fallback to this. *)
+    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.
+       *)
       g#touch "/.autorelabel"
-    )
   )
+
+and is_selinux_guest g =
+  g#is_file ~followsymlinks:true "/usr/sbin/load_policy" &&
+  g#is_file ~followsymlinks:true "/etc/selinux/config"
+
+and use_setfiles g =
+  (* Is setfiles / SELinux relabelling functionality available? *)
+  if not (g#feature_available [| "selinuxrelabel" |]) then
+    failwith "no selinux relabel feature";
+
+  (* 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 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#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.18.4