builder: Add --selinux-relabel option to perform SELinux relabelling.

This adds the --selinux-relabel option which enables selinux in the
appliance and runs:

  if load_policy && fixfiles restore; then
    rm -f /.autorelabel
  else
    touch /.autorelabel
  fi

at the end of installation.

When possible this fixes SELinux labels in the guest and makes the
autorelabel step unnecessary.

Notes:

 - The previous commit is required so that load_policy works.

 - During the build, SELinux is enabled but no policy is loaded.  This
   works because SELinux is in permissive mode.

 - This flag does not work if the appliance kernel and the guest have
   greatly differing versions, eg. a RHEL 6 guest with a Fedora 20
   appliance.  This is because SELinux changes the policy format and
   breaks backwards compatibility.  You would see errors like this:

   libsepol.policydb_write: policy version 15 cannot support MLS
   libsepol.policydb_to_image: could not compute policy length
   libsepol.policydb_to_image: could not create policy image
   SELinux:  Could not downgrade policy file /etc/selinux/targeted/policy/policy.24, searching for an older version.
   SELinux:  Could not open policy file <= /etc/selinux/targeted/policy/policy.24:  No such file or directory

   These errors are ignored (they go to the log file) and relabelling
   is done at boot instead.

 - It's not clear if loading guest policy is safe.  You should trust
   the virt-builder templates and to use libguestfs confinement for
   additional protection.
This commit is contained in:
Richard W.M. Jones
2014-01-24 19:38:26 +00:00
parent ab33653ef3
commit 90e23b4e56
3 changed files with 65 additions and 25 deletions

View File

@@ -40,8 +40,8 @@ let main () =
edit, firstboot, run, format, gpg, hostname, install, list_format, links,
memsize, mkdirs,
network, output, password_crypto, quiet, root_password, scrub,
scrub_logfile, size, smp, sources, sync, timezone, update, upload,
writes =
scrub_logfile, selinux_relabel, size, smp, sources, sync, timezone,
update, upload, writes =
parse_cmdline () in
(* Timestamped messages in ordinary, non-debug non-quiet mode. *)
@@ -578,6 +578,8 @@ let main () =
(match smp with None -> () | Some smp -> g#set_smp smp);
g#set_network network;
g#set_selinux selinux_relabel;
(* The output disk is being created, so use cache=unsafe here. *)
g#add_drive_opts ~format:output_format ~cachemode:"unsafe" output_filename;
@@ -890,6 +892,19 @@ exec >>%s 2>&1
do_run ~display:cmd cmd
) run;
if selinux_relabel then (
msg (f_"SELinux relabelling");
let cmd = sprintf "
if load_policy && fixfiles restore; then
rm -f /.autorelabel
else
touch /.autorelabel
echo '%s: SELinux relabelling failed, will relabel at boot instead.'
fi
" prog in
do_run ~display:"load_policy && fixfiles restore" cmd
);
(* Clean up the log file:
*
* If debugging, dump out the log file.

View File

@@ -180,6 +180,7 @@ let parse_cmdline () =
let add_scrub s = scrub := s :: !scrub in
let scrub_logfile = ref false in
let selinux_relabel = ref false in
let size = ref None in
let set_size arg = size := Some (parse_size ~prog arg) in
@@ -287,6 +288,8 @@ let parse_cmdline () =
"--run", Arg.String add_run, "script" ^ " " ^ s_"Run script in disk image";
"--run-command", Arg.String add_run_cmd, "cmd+args" ^ " " ^ s_"Run command in disk image";
"--scrub", Arg.String add_scrub, "name" ^ " " ^ s_"Scrub a file";
"--selinux-relabel", Arg.Set selinux_relabel,
" " ^ s_"Relabel files with correct SELinux labels";
"--size", Arg.String set_size, "size" ^ " " ^ s_"Set output disk size";
"--smp", Arg.Int set_smp, "vcpus" ^ " " ^ s_"Set number of vCPUs";
"--source", Arg.String add_source, "URL" ^ " " ^ s_"Set source URL";
@@ -351,6 +354,7 @@ read the man page virt-builder(1).
let root_password = !root_password in
let scrub = List.rev !scrub in
let scrub_logfile = !scrub_logfile in
let selinux_relabel = !selinux_relabel in
let size = !size in
let smp = !smp in
let sources = List.rev !sources in
@@ -457,5 +461,5 @@ read the man page virt-builder(1).
edit, firstboot, run, format, gpg, hostname, install, list_format, links,
memsize, mkdirs,
network, output, password_crypto, quiet, root_password, scrub,
scrub_logfile, size, smp, sources, sync, timezone, update, upload,
writes
scrub_logfile, selinux_relabel, size, smp, sources, sync, timezone,
update, upload, writes

View File

@@ -27,6 +27,7 @@ virt-builder - Build virtual machine images quickly
[--link TARGET:LINK[:LINK]]
[--edit FILE:EXPR]
[--delete FILE] [--scrub FILE]
[--selinux-relabel]
[--run SCRIPT] [--run-command 'CMD ARGS ...']
[--firstboot SCRIPT] [--firstboot-command 'CMD ARGS ...']
[--firstboot-install PKG,[PKG...]]
@@ -136,6 +137,16 @@ To install packages from the ordinary (guest) software repository
(In Fedora, C<@> is used to install groups of packages. On Debian
you would install a meta-package instead.)
To update the core packages to the latest version:
virt-builder debian-7 --update
For guests which use SELinux, like Fedora and Red Hat Enterprise
Linux, you may need to do SELinux relabelling after installing or
updating packages (see L</SELINUX> below):
virt-builder fedora-20 --update --selinux-relabel
=head2 Customizing the installation
There are many options that let you customize the installation. These
@@ -593,6 +604,12 @@ It cannot delete directories, only regular files.
=back
=item B<--selinux-relabel>
Relabel files in the guest so that they have the correct SELinux label.
You should only use this option for guests which support SELinux.
=item B<--size> SIZE
Select the size of the output disk, where the size can be specified
@@ -1029,6 +1046,10 @@ Scripts are run (I<--run>, I<--run-command>).
Scripts run in the order they appear on the command line.
=item *
SELinux relabelling is done (I<--selinux-relabel>).
=back
=head2 IMPORTING THE DISK IMAGE
@@ -1714,30 +1735,29 @@ raw-format guests.
Guests which use SELinux (such as Fedora and Red Hat Enterprise Linux)
require that each file has a correct SELinux label.
Since virt-builder does not know how to give new files a correct
label, the guest templates have an empty file C</.autorelabel> and
this causes the guest to relabel itself at first boot.
Virt-builder does not know how to give new files a label, so there are
two possible strategies it can use to ensure correct labelling:
This usually means that these guests will reboot themselves once the
first time you use them. B<This is normal, and harmless.> However if
you want to perform the relabelling at build time instead of delaying
it to the first boot, you can boot the guest with the qemu
I<-no-reboot> option (which means it will shut down after the relabel
is complete without booting "for real"). Only do this if you are sure
it is an SELinux guest:
=over 4
qemu-system-x86_64 \
-no-reboot \
-nographic \
-machine accel=kvm:tcg \
-cpu host \
-m 2048 \
-drive file=disk.img,format=raw,if=virtio \
-serial stdio \
-monitor none
=item Using I<--selinux-relabel>
(For further information on the topic of SELinux labelling, see:
L<https://www.redhat.com/archives/libguestfs/2014-January/msg00183.html>)
This runs L<fixfiles(8)> just before finalizing the guest, which sets
SELinux labels correctly in the disk image.
Sometimes fixfiles is not possible during installation, in which case
this option falls back on:
=item Touching C</.autorelabel>
Guest templates may already contain a file called C</.autorelabel>, or
it is touched if I<--selinux-relabel> cannot run fixfiles.
For guests that use SELinux, this causes fixfiles to run at first
boot. Guests will reboot themselves once the first time you use them,
which is normal and harmless.
=back
=head1 ENVIRONMENT VARIABLES
@@ -1795,6 +1815,7 @@ L<gpg(1)>,
L<curl(1)>,
L<virt-make-fs(1)>,
L<genisoimage(1)>,
L<fixfiles(8)>,
L<http://libguestfs.org/>.
=head1 AUTHOR