mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
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).
This commit is contained in:
@@ -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 "/"
|
||||
|
||||
Reference in New Issue
Block a user