1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
(* virt-customize
* Copyright (C) 2016 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*)
open Std_utils
open Tools_utils
open Common_gettext.Gettext
open Printf
module G = Guestfs
(* Simple reimplementation of Array.mem, available only with OCaml >= 4.03. *)
let array_find a l =
List.mem a (Array.to_list l)
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.
*)
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
(* If the spec file doesn't exist then fall back to using
* autorelabel (RHBZ#1828952).
*)
if not (g#is_file ~followsymlinks:true specfile) then
failwith "no spec file";
(* 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 "/"
|