v1 -> v2: - Add simple test of the setfiles API. - Use SELinux_relabel module in virt-v2v (instead of touch /.autorelabel). - Small fixes. Rich.
Richard W.M. Jones
2016-Jul-14 08:49 UTC
[Libguestfs] [PATCH v2 1/7] v2v: Move augeas_debug_errors (renamed debug_augeas_errors) to common code.
Since the function uses the StringMap module, I also had to move this to mllib. The function is renamed and the 'if verbose ()' part is moved into the function, but apart from that, it's all just code motion. --- builder/Makefile.am | 1 + customize/Makefile.am | 1 + dib/Makefile.am | 1 + get-kernel/Makefile.am | 1 + mllib/Makefile.am | 3 +++ mllib/common_utils.ml | 63 +++++++++++++++++++++++++++++++++++++++++++ mllib/common_utils.mli | 14 ++++++++++ mllib/stringMap.ml | 21 +++++++++++++++ mllib/stringMap.mli | 54 +++++++++++++++++++++++++++++++++++++ resize/Makefile.am | 1 + sparsify/Makefile.am | 1 + sysprep/Makefile.am | 1 + v2v/Makefile.am | 6 ++--- v2v/linux.ml | 64 ++------------------------------------------ v2v/stringMap.ml | 21 --------------- v2v/stringMap.mli | 54 ------------------------------------- v2v/test-harness/Makefile.am | 1 + 17 files changed, 168 insertions(+), 140 deletions(-) create mode 100644 mllib/stringMap.ml create mode 100644 mllib/stringMap.mli delete mode 100644 v2v/stringMap.ml delete mode 100644 v2v/stringMap.mli diff --git a/builder/Makefile.am b/builder/Makefile.am index 5c41cfa..cc9e51d 100644 --- a/builder/Makefile.am +++ b/builder/Makefile.am @@ -137,6 +137,7 @@ BOBJECTS = \ $(top_builddir)/mllib/guestfs_config.cmo \ $(top_builddir)/mllib/common_gettext.cmo \ $(top_builddir)/mllib/dev_t.cmo \ + $(top_builddir)/mllib/stringMap.cmo \ $(top_builddir)/mllib/common_utils.cmo \ $(top_builddir)/mllib/fsync.cmo \ $(top_builddir)/mllib/planner.cmo \ diff --git a/customize/Makefile.am b/customize/Makefile.am index de3d7e0..fbd584d 100644 --- a/customize/Makefile.am +++ b/customize/Makefile.am @@ -96,6 +96,7 @@ BOBJECTS = \ $(top_builddir)/mllib/guestfs_config.cmo \ $(top_builddir)/mllib/common_gettext.cmo \ $(top_builddir)/mllib/dev_t.cmo \ + $(top_builddir)/mllib/stringMap.cmo \ $(top_builddir)/mllib/common_utils.cmo \ $(top_builddir)/mllib/regedit.cmo \ $(top_builddir)/mllib/URI.cmo \ diff --git a/dib/Makefile.am b/dib/Makefile.am index ae6e878..3bb992a 100644 --- a/dib/Makefile.am +++ b/dib/Makefile.am @@ -60,6 +60,7 @@ BOBJECTS = \ $(top_builddir)/mllib/guestfs_config.cmo \ $(top_builddir)/mllib/common_gettext.cmo \ $(top_builddir)/mllib/dev_t.cmo \ + $(top_builddir)/mllib/stringMap.cmo \ $(top_builddir)/mllib/common_utils.cmo \ $(top_builddir)/mllib/mkdtemp.cmo \ $(SOURCES_ML:.ml=.cmo) diff --git a/get-kernel/Makefile.am b/get-kernel/Makefile.am index 6892fbb..875075f 100644 --- a/get-kernel/Makefile.am +++ b/get-kernel/Makefile.am @@ -59,6 +59,7 @@ BOBJECTS = \ $(top_builddir)/mllib/guestfs_config.cmo \ $(top_builddir)/mllib/common_gettext.cmo \ $(top_builddir)/mllib/dev_t.cmo \ + $(top_builddir)/mllib/stringMap.cmo \ $(top_builddir)/mllib/common_utils.cmo \ $(top_builddir)/mllib/URI.cmo \ $(SOURCES_ML:.ml=.cmo) diff --git a/mllib/Makefile.am b/mllib/Makefile.am index e728d54..f533749 100644 --- a/mllib/Makefile.am +++ b/mllib/Makefile.am @@ -37,12 +37,14 @@ SOURCES_MLI = \ progress.mli \ regedit.mli \ StatVFS.mli \ + stringMap.mli \ URI.mli SOURCES_ML = \ guestfs_config.ml \ $(OCAML_BYTES_COMPAT_ML) \ libdir.ml \ + stringMap.ml \ common_gettext.ml \ dev_t.ml \ common_utils.ml \ @@ -151,6 +153,7 @@ common_utils_tests_BOBJECTS = \ guestfs_config.cmo \ common_gettext.cmo \ dev_t.cmo \ + stringMap.cmo \ common_utils.cmo \ common_utils_tests.cmo common_utils_tests_XOBJECTS = $(common_utils_tests_BOBJECTS:.cmo=.cmx) diff --git a/mllib/common_utils.ml b/mllib/common_utils.ml index 69118da..041f88b 100644 --- a/mllib/common_utils.ml +++ b/mllib/common_utils.ml @@ -812,6 +812,69 @@ let truncate_recursive (g : Guestfs.guestfs) dir let files = List.filter g#is_file files in List.iter g#truncate files +let debug_augeas_errors g + if verbose () then ( + try + let errors = g#aug_match "/augeas/files//error" in + let errors = Array.to_list errors in + let map + List.fold_left ( + fun map error -> + let detail_paths = g#aug_match (error ^ "//*") in + let detail_paths = Array.to_list detail_paths in + List.fold_left ( + fun map path -> + (* path is "/augeas/files/<filename>/error/<field>". Put + * <filename>, <field> and the value of this Augeas field + * into a map. + *) + let i = String.find path "/error/" in + assert (i >= 0); + let filename = String.sub path 13 (i-13) in + let field + String.sub path (i+7) (String.length path - (i+7)) in + + let detail = g#aug_get path in + + let fmap : string StringMap.t + try StringMap.find filename map + with Not_found -> StringMap.empty in + let fmap = StringMap.add field detail fmap in + StringMap.add filename fmap map + ) map detail_paths + ) StringMap.empty errors in + + let filenames = StringMap.keys map in + let filenames = List.sort compare filenames in + + List.iter ( + fun filename -> + eprintf "augeas failed to parse %s:\n" filename; + let fmap = StringMap.find filename map in + (try + let msg = StringMap.find "message" fmap in + eprintf " error \"%s\"" msg + with Not_found -> () + ); + (try + let line = StringMap.find "line" fmap + and char = StringMap.find "char" fmap in + eprintf " at line %s char %s" line char + with Not_found -> () + ); + (try + let lens = StringMap.find "lens" fmap in + eprintf " in lens %s" lens + with Not_found -> () + ); + eprintf "\n" + ) filenames; + + flush stderr + with + Guestfs.Error msg -> eprintf "%s: augeas: %s (ignored)\n" prog msg + ) + (* Detect type of a file. *) let detect_file_type filename let chan = open_in filename in diff --git a/mllib/common_utils.mli b/mllib/common_utils.mli index 9b1086c..572719b 100644 --- a/mllib/common_utils.mli +++ b/mllib/common_utils.mli @@ -318,6 +318,20 @@ val truncate_recursive : Guestfs.guestfs -> string -> unit (** Using the libguestfs API, recurse into the given directory and truncate all files found to zero size. *) +val debug_augeas_errors : Guestfs.guestfs -> unit +(** In verbose mode, any Augeas errors which happened most recently + on the handle and printed on standard error. You should usually + call this just after either [g#aug_init] or [g#aug_load]. + + Note this doesn't call {!error} if there were any errors on the + handle. It is just for debugging. It is expected that a + subsequent Augeas command will fail, eg. when trying to match + an Augeas path which is expected to exist but does not exist + because of a parsing error. In that case turning on debugging + will reveal the parse error. + + If not in verbose mode, this does nothing. *) + val detect_file_type : string -> [`GZip | `Tar | `XZ | `Zip | `Unknown] (** Detect type of a file (for a very limited range of file types). *) diff --git a/mllib/stringMap.ml b/mllib/stringMap.ml new file mode 100644 index 0000000..ea47a6e --- /dev/null +++ b/mllib/stringMap.ml @@ -0,0 +1,21 @@ +(* virt-v2v + * Copyright (C) 2009-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. + *) + +include Map.Make (String) + +let keys map = fold (fun k _ ks -> k :: ks) map [] diff --git a/mllib/stringMap.mli b/mllib/stringMap.mli new file mode 100644 index 0000000..b668538 --- /dev/null +++ b/mllib/stringMap.mli @@ -0,0 +1,54 @@ +(* virt-v2v + * Copyright (C) 2009-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. + *) + +type key = String.t +type 'a t = 'a Map.Make(String).t + +val empty : 'a t +val is_empty : 'a t -> bool +val mem : key -> 'a t -> bool +val add : key -> 'a -> 'a t -> 'a t +(* +val singleton : key -> 'a -> 'a t +*) +val remove : key -> 'a t -> 'a t +(* +val merge : (key -> 'a option -> 'b option -> 'c option) -> 'a t -> 'b t -> 'c t +*) +val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int +val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool +val iter : (key -> 'a -> unit) -> 'a t -> unit +val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b +(* +val for_all : (key -> 'a -> bool) -> 'a t -> bool +val exists : (key -> 'a -> bool) -> 'a t -> bool +val filter : (key -> 'a -> bool) -> 'a t -> 'a t +val partition : (key -> 'a -> bool) -> 'a t -> 'a t * 'a t +val cardinal : 'a t -> int +val bindings : 'a t -> (key * 'a) list +val min_binding : 'a t -> key * 'a +val max_binding : 'a t -> key * 'a +val choose : 'a t -> key * 'a +val split : key -> 'a t -> 'a t * 'a option * 'a t +*) +val find : key -> 'a t -> 'a +val map : ('a -> 'b) -> 'a t -> 'b t +(* +val mapi : (key -> 'a -> 'b) -> 'a t -> 'b t +*) +val keys : 'a t -> key list diff --git a/resize/Makefile.am b/resize/Makefile.am index da5d42d..ac9ccc3 100644 --- a/resize/Makefile.am +++ b/resize/Makefile.am @@ -61,6 +61,7 @@ BOBJECTS = \ $(top_builddir)/mllib/guestfs_config.cmo \ $(top_builddir)/mllib/common_gettext.cmo \ $(top_builddir)/mllib/dev_t.cmo \ + $(top_builddir)/mllib/stringMap.cmo \ $(top_builddir)/mllib/common_utils.cmo \ $(SOURCES_ML:.ml=.cmo) XOBJECTS = $(BOBJECTS:.cmo=.cmx) diff --git a/sparsify/Makefile.am b/sparsify/Makefile.am index f9f0f8e..133042f 100644 --- a/sparsify/Makefile.am +++ b/sparsify/Makefile.am @@ -60,6 +60,7 @@ BOBJECTS = \ $(top_builddir)/mllib/guestfs_config.cmo \ $(top_builddir)/mllib/common_gettext.cmo \ $(top_builddir)/mllib/dev_t.cmo \ + $(top_builddir)/mllib/stringMap.cmo \ $(top_builddir)/mllib/common_utils.cmo \ $(top_builddir)/mllib/progress.cmo \ $(top_builddir)/mllib/StatVFS.cmo \ diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am index d4f1173..90f6b04 100644 --- a/sysprep/Makefile.am +++ b/sysprep/Makefile.am @@ -109,6 +109,7 @@ BOBJECTS = \ $(top_builddir)/mllib/guestfs_config.cmo \ $(top_builddir)/mllib/common_gettext.cmo \ $(top_builddir)/mllib/dev_t.cmo \ + $(top_builddir)/mllib/stringMap.cmo \ $(top_builddir)/mllib/common_utils.cmo \ $(top_builddir)/mllib/URI.cmo \ $(top_builddir)/mllib/mkdtemp.cmo \ diff --git a/v2v/Makefile.am b/v2v/Makefile.am index fedc84d..fc83600 100644 --- a/v2v/Makefile.am +++ b/v2v/Makefile.am @@ -51,7 +51,6 @@ SOURCES_MLI = \ output_rhev.mli \ output_vdsm.mli \ OVF.mli \ - stringMap.mli \ target_bus_assignment.mli \ types.mli \ utils.mli \ @@ -61,7 +60,6 @@ SOURCES_MLI = \ xml.mli SOURCES_ML = \ - stringMap.ml \ types.ml \ xml.ml \ utils.ml \ @@ -124,6 +122,7 @@ BOBJECTS = \ $(top_builddir)/mllib/guestfs_config.cmo \ $(top_builddir)/mllib/common_gettext.cmo \ $(top_builddir)/mllib/dev_t.cmo \ + $(top_builddir)/mllib/stringMap.cmo \ $(top_builddir)/mllib/common_utils.cmo \ $(top_builddir)/mllib/regedit.cmo \ $(top_builddir)/mllib/mkdtemp.cmo \ @@ -195,6 +194,7 @@ COPY_TO_LOCAL_BOBJECTS = \ $(top_builddir)/mllib/guestfs_config.cmo \ $(top_builddir)/mllib/common_gettext.cmo \ $(top_builddir)/mllib/dev_t.cmo \ + $(top_builddir)/mllib/stringMap.cmo \ $(top_builddir)/mllib/common_utils.cmo \ $(top_builddir)/mllib/JSON.cmo \ $(top_builddir)/mllib/StatVFS.cmo \ @@ -409,9 +409,9 @@ v2v_unit_tests_BOBJECTS = \ $(top_builddir)/mllib/guestfs_config.cmo \ $(top_builddir)/mllib/common_gettext.cmo \ $(top_builddir)/mllib/dev_t.cmo \ + $(top_builddir)/mllib/stringMap.cmo \ $(top_builddir)/mllib/common_utils.cmo \ $(top_builddir)/mllib/regedit.cmo \ - stringMap.cmo \ types.cmo \ xml.cmo \ utils.cmo \ diff --git a/v2v/linux.ml b/v2v/linux.ml index e1451a4..d20194b 100644 --- a/v2v/linux.ml +++ b/v2v/linux.ml @@ -31,71 +31,11 @@ module G = Guestfs *) let rec augeas_init g g#aug_init "/" 1; - if verbose () then augeas_debug_errors g + debug_augeas_errors g and augeas_reload g g#aug_load (); - if verbose () then augeas_debug_errors g - -and augeas_debug_errors g - try - let errors = g#aug_match "/augeas/files//error" in - let errors = Array.to_list errors in - let map - List.fold_left ( - fun map error -> - let detail_paths = g#aug_match (error ^ "//*") in - let detail_paths = Array.to_list detail_paths in - List.fold_left ( - fun map path -> - (* path is "/augeas/files/<filename>/error/<field>". Put - * <filename>, <field> and the value of this Augeas field - * into a map. - *) - let i = String.find path "/error/" in - assert (i >= 0); - let filename = String.sub path 13 (i-13) in - let field = String.sub path (i+7) (String.length path - (i+7)) in - - let detail = g#aug_get path in - - let fmap : string StringMap.t - try StringMap.find filename map - with Not_found -> StringMap.empty in - let fmap = StringMap.add field detail fmap in - StringMap.add filename fmap map - ) map detail_paths - ) StringMap.empty errors in - - let filenames = StringMap.keys map in - let filenames = List.sort compare filenames in - - List.iter ( - fun filename -> - eprintf "augeas failed to parse %s:\n" filename; - let fmap = StringMap.find filename map in - (try - let msg = StringMap.find "message" fmap in - eprintf " error \"%s\"" msg - with Not_found -> () - ); - (try - let line = StringMap.find "line" fmap - and char = StringMap.find "char" fmap in - eprintf " at line %s char %s" line char - with Not_found -> () - ); - (try - let lens = StringMap.find "lens" fmap in - eprintf " in lens %s" lens - with Not_found -> () - ); - eprintf "\n" - ) filenames; - - flush stderr - with - Guestfs.Error msg -> eprintf "%s: augeas: %s (ignored)\n" prog msg + debug_augeas_errors g let remove g inspect packages if packages <> [] then ( diff --git a/v2v/stringMap.ml b/v2v/stringMap.ml deleted file mode 100644 index ea47a6e..0000000 --- a/v2v/stringMap.ml +++ /dev/null @@ -1,21 +0,0 @@ -(* virt-v2v - * Copyright (C) 2009-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. - *) - -include Map.Make (String) - -let keys map = fold (fun k _ ks -> k :: ks) map [] diff --git a/v2v/stringMap.mli b/v2v/stringMap.mli deleted file mode 100644 index b668538..0000000 --- a/v2v/stringMap.mli +++ /dev/null @@ -1,54 +0,0 @@ -(* virt-v2v - * Copyright (C) 2009-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. - *) - -type key = String.t -type 'a t = 'a Map.Make(String).t - -val empty : 'a t -val is_empty : 'a t -> bool -val mem : key -> 'a t -> bool -val add : key -> 'a -> 'a t -> 'a t -(* -val singleton : key -> 'a -> 'a t -*) -val remove : key -> 'a t -> 'a t -(* -val merge : (key -> 'a option -> 'b option -> 'c option) -> 'a t -> 'b t -> 'c t -*) -val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int -val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool -val iter : (key -> 'a -> unit) -> 'a t -> unit -val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b -(* -val for_all : (key -> 'a -> bool) -> 'a t -> bool -val exists : (key -> 'a -> bool) -> 'a t -> bool -val filter : (key -> 'a -> bool) -> 'a t -> 'a t -val partition : (key -> 'a -> bool) -> 'a t -> 'a t * 'a t -val cardinal : 'a t -> int -val bindings : 'a t -> (key * 'a) list -val min_binding : 'a t -> key * 'a -val max_binding : 'a t -> key * 'a -val choose : 'a t -> key * 'a -val split : key -> 'a t -> 'a t * 'a option * 'a t -*) -val find : key -> 'a t -> 'a -val map : ('a -> 'b) -> 'a t -> 'b t -(* -val mapi : (key -> 'a -> 'b) -> 'a t -> 'b t -*) -val keys : 'a t -> key list diff --git a/v2v/test-harness/Makefile.am b/v2v/test-harness/Makefile.am index 97d62f0..dcbe884 100644 --- a/v2v/test-harness/Makefile.am +++ b/v2v/test-harness/Makefile.am @@ -62,6 +62,7 @@ BOBJECTS = \ $(top_builddir)/mllib/guestfs_config.cmo \ $(top_builddir)/mllib/common_gettext.cmo \ $(top_builddir)/mllib/dev_t.cmo \ + $(top_builddir)/mllib/stringMap.cmo \ $(top_builddir)/mllib/common_utils.cmo \ $(top_builddir)/v2v/xml.cmo \ $(SOURCES_ML:.ml=.cmo) \ -- 2.7.4
Richard W.M. Jones
2016-Jul-14 08:49 UTC
[Libguestfs] [PATCH v2 2/7] New API: setfiles - SELinux relabel parts of the filesystem.
--- appliance/packagelist.in | 1 + daemon/Makefile.am | 1 + daemon/setfiles.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++ generator/actions.ml | 22 ++++++++++++ gobject/Makefile.inc | 2 ++ src/MAX_PROC_NR | 2 +- 6 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 daemon/setfiles.c diff --git a/appliance/packagelist.in b/appliance/packagelist.in index 5f04c1c..3a4790b 100644 --- a/appliance/packagelist.in +++ b/appliance/packagelist.in @@ -43,6 +43,7 @@ ifelse(REDHAT,1, ntfs-3g openssh-clients pcre + policycoreutils reiserfs-utils libselinux syslinux-extlinux diff --git a/daemon/Makefile.am b/daemon/Makefile.am index b77d1e7..9bd495f 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -168,6 +168,7 @@ guestfsd_SOURCES = \ rsync.c \ scrub.c \ selinux.c \ + setfiles.c \ sfdisk.c \ sh.c \ sleep.c \ diff --git a/daemon/setfiles.c b/daemon/setfiles.c new file mode 100644 index 0000000..3f249c3 --- /dev/null +++ b/daemon/setfiles.c @@ -0,0 +1,93 @@ +/* libguestfs - the guestfsd daemon + * 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. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "guestfs_protocol.h" +#include "daemon.h" +#include "actions.h" + +GUESTFSD_EXT_CMD(str_setfiles, setfiles); + +#define MAX_ARGS 64 + +/* Takes optional arguments, consult optargs_bitmask. */ +int +do_setfiles (const char *specfile, const char *path, + int force) +{ + const char *argv[MAX_ARGS]; + CLEANUP_FREE char *s_dev = NULL, *s_proc = NULL, *s_selinux = NULL, + *s_sys = NULL, *s_specfile = NULL, *s_path = NULL; + CLEANUP_FREE char *err = NULL; + size_t i = 0; + + s_dev = sysroot_path ("/dev"); + if (!s_dev) { + malloc_error: + reply_with_perror ("malloc"); + return -1; + } + s_proc = sysroot_path ("/proc"); if (!s_proc) goto malloc_error; + s_selinux = sysroot_path ("/selinux"); if (!s_selinux) goto malloc_error; + s_sys = sysroot_path ("/sys"); if (!s_sys) goto malloc_error; + s_specfile = sysroot_path (specfile); if (!s_specfile) goto malloc_error; + s_path = sysroot_path (path); if (!s_path) goto malloc_error; + + /* Default settings if not selected. */ + if (!(optargs_bitmask & GUESTFS_SETFILES_FORCE_BITMASK)) + force = 0; + + ADD_ARG (argv, i, str_setfiles); + if (force) + ADD_ARG (argv, i, "-F"); + + /* Exclude some directories that should never be relabelled in + * ordinary Linux guests. These won't be mounted anyway. We have + * to prefix all these with the sysroot path. + */ + ADD_ARG (argv, i, "-e"); ADD_ARG (argv, i, s_dev); + ADD_ARG (argv, i, "-e"); ADD_ARG (argv, i, s_proc); + ADD_ARG (argv, i, "-e"); ADD_ARG (argv, i, s_selinux); + ADD_ARG (argv, i, "-e"); ADD_ARG (argv, i, s_sys); + + /* Relabelling in a chroot. */ + if (STRNEQ (sysroot, "/")) { + ADD_ARG (argv, i, "-r"); + ADD_ARG (argv, i, sysroot); + } + + /* Suppress non-error output. */ + ADD_ARG (argv, i, "-q"); + + /* Add parameters. */ + ADD_ARG (argv, i, s_specfile); + ADD_ARG (argv, i, s_path); + ADD_ARG (argv, i, NULL); + + if (commandv (NULL, &err, argv) == -1) { + reply_with_perror ("%s", err); + return -1; + } + + return 0; +} diff --git a/generator/actions.ml b/generator/actions.ml index 25108a2..49c360c 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -13149,6 +13149,28 @@ fails and the C<errno> is set to C<ENODEV>." }; shortdesc = "walk through the filesystem content"; longdesc = "Internal function for filesystem_walk." }; + { defaults with + name = "setfiles"; added = (1, 33, 43); + style = RErr, [String "specfile"; Pathname "path"], [OBool "force"]; + proc_nr = Some 467; + test_excuse = "tests are in the tests/relabel directory"; + shortdesc = "relabel parts of the filesystem"; + longdesc = "\ +SELinux relabel parts of the filesystem. + +The C<specfile> parameter controls the policy spec file used. +You have to parse C</etc/selinux/config> to find the correct +SELinux policy and then pass the spec file, usually: +C</etc/selinux/> + I<selinuxtype> + C</contexts/files/file_contexts>. + +The required C<path> parameter is the top level directory where +relabelling starts. Normally you should pass C<path> as C</> +to relabel the whole guest filesystem. + +The optional C<force> boolean controls whether the context +is reset for customizable files, and also whether the +user, role and range parts of the file context is changed." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc index 77f1614..0284add 100644 --- a/gobject/Makefile.inc +++ b/gobject/Makefile.inc @@ -99,6 +99,7 @@ guestfs_gobject_headers= \ include/guestfs-gobject/optargs-rsync_in.h \ include/guestfs-gobject/optargs-rsync_out.h \ include/guestfs-gobject/optargs-set_e2attrs.h \ + include/guestfs-gobject/optargs-setfiles.h \ include/guestfs-gobject/optargs-syslinux.h \ include/guestfs-gobject/optargs-tar_in.h \ include/guestfs-gobject/optargs-tar_out.h \ @@ -187,6 +188,7 @@ guestfs_gobject_sources= \ src/optargs-rsync_in.c \ src/optargs-rsync_out.c \ src/optargs-set_e2attrs.c \ + src/optargs-setfiles.c \ src/optargs-syslinux.c \ src/optargs-tar_in.c \ src/optargs-tar_out.c \ diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index f27d46f..5873851 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -466 +467 -- 2.7.4
Richard W.M. Jones
2016-Jul-14 08:49 UTC
[Libguestfs] [PATCH v2 3/7] tests: Add a test of the setfiles API.
--- Makefile.am | 1 + configure.ac | 1 + tests/relabel/Makefile.am | 28 +++++++++ tests/relabel/test-relabel.pl | 134 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 164 insertions(+) create mode 100644 tests/relabel/Makefile.am create mode 100755 tests/relabel/test-relabel.pl diff --git a/Makefile.am b/Makefile.am index 890c62e..edaa642 100644 --- a/Makefile.am +++ b/Makefile.am @@ -65,6 +65,7 @@ SUBDIRS += tests/lvm SUBDIRS += tests/luks SUBDIRS += tests/md SUBDIRS += tests/selinux +SUBDIRS += tests/relabel SUBDIRS += tests/ntfs SUBDIRS += tests/btrfs SUBDIRS += tests/xfs diff --git a/configure.ac b/configure.ac index 35d030c..070dc24 100644 --- a/configure.ac +++ b/configure.ac @@ -276,6 +276,7 @@ AC_CONFIG_FILES([Makefile tests/protocol/Makefile tests/qemu/Makefile tests/regressions/Makefile + tests/relabel/Makefile tests/relative-paths/Makefile tests/rsync/Makefile tests/selinux/Makefile diff --git a/tests/relabel/Makefile.am b/tests/relabel/Makefile.am new file mode 100644 index 0000000..3407bef --- /dev/null +++ b/tests/relabel/Makefile.am @@ -0,0 +1,28 @@ +# libguestfs +# 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. + +# Test setfiles function. + +include $(top_srcdir)/subdir-rules.mk + +TESTS = \ + test-relabel.pl + +TESTS_ENVIRONMENT = $(top_builddir)/run --test + +EXTRA_DIST = \ + test-relabel.pl diff --git a/tests/relabel/test-relabel.pl b/tests/relabel/test-relabel.pl new file mode 100755 index 0000000..0111bf3 --- /dev/null +++ b/tests/relabel/test-relabel.pl @@ -0,0 +1,134 @@ +#!/usr/bin/env perl +# 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. + +use strict; +use warnings; + +use Sys::Guestfs; + +my $prog = $0; +$prog =~ s{.*/}{}; + +# Because we parse error message strings below. +$ENV{LANG} = "C"; + +if ($ENV{"SKIP_TEST_RELABEL_PL"}) { + print "$prog: test skipped because environment variable is set.\n"; + exit 77 +} + +# SELinux labelling won't work (and can be skipped) if SELinux isn't +# installed on the host. +if (! -f "/etc/selinux/config" || ! -x "/usr/sbin/load_policy") { + print "$prog: test skipped because SELinux is not available.\n"; + exit 77 +} + +# Create a filesystem. +my $g = Sys::Guestfs->new (); + +$g->add_drive_scratch (256*1024*1024); +$g->launch (); + +# If Linux extended attrs aren't available then we cannot test this. +unless ($g->feature_available (["linuxxattrs"])) { + print "$prog: test skipped because 'linuxxattrs' feature not available.\n"; + $g->close (); + exit 77 +} + +$g->part_disk ("/dev/sda", "mbr"); +$g->mkfs ("ext4", "/dev/sda1"); + +$g->mount_options ("user_xattr", "/dev/sda1", "/"); + +# Create some files and directories that we want to have relabelled. +$g->mkdir ("/bin"); +$g->touch ("/bin/ls"); +$g->mkdir ("/etc"); +$g->mkdir ("/tmp"); +$g->touch ("/tmp/test"); +$g->mkdir ("/var"); +$g->mkdir ("/var/log"); +$g->touch ("/var/log/messages"); + +# Create a spec file. +# This doesn't test the optional file_type field. XXX +# See also file_contexts(5). +$g->write ("/etc/file_contexts", <<'EOF'); +/.* system_u:object_r:default_t:s0 +/bin/.* system_u:object_r:bin_t:s0 +/etc/.* system_u:object_r:etc_t:s0 +/etc/file_contexts <<none>> +/tmp/.* <<none>> +/var/.* system_u:object_r:var_t:s0 +/var/log/.* system_u:object_r:var_log_t:s0 +EOF + +# Do the relabel. +$g->setfiles ("/etc/file_contexts", "/", force => 1); + +# Check the labels were set correctly. +my $errors = 0; + +sub check_label +{ + my $file = shift; + my $expected_label = shift; + + my $actual_label = $g->lgetxattr ($file, "security.selinux"); + # The label returned from lgetxattr has \0 appended. + if ("$expected_label\0" ne $actual_label) { + print STDERR "$prog: expected label on file $file: expected=$expected_label actual=$actual_label\n"; + $errors++; + } +} + +sub check_label_none +{ + my $file = shift; + my $r; + + eval { + $r = $g->lgetxattr ($file, "security.selinux"); + }; + if (defined $r) { + print STDERR "$prog: expecting no label on file $file, but got $r\n"; + $errors++; + } elsif ($@) { + if ($@ !~ /No data available/) { + print STDERR "$prog: expecting an error reading label from file $file, but got $@\n"; + $errors++; + } + } +} + +check_label ("/bin", "system_u:object_r:default_t:s0"); +check_label ("/bin/ls", "system_u:object_r:bin_t:s0"); +check_label ("/etc", "system_u:object_r:default_t:s0"); +check_label_none ("/etc/file_contexts"); +check_label ("/tmp", "system_u:object_r:default_t:s0"); +check_label_none ("/tmp/test"); +check_label ("/var", "system_u:object_r:default_t:s0"); +check_label ("/var/log", "system_u:object_r:var_t:s0"); +check_label ("/var/log/messages", "system_u:object_r:var_log_t:s0"); + +# Finish up. +$g->shutdown (); +$g->close (); + +exit ($errors == 0 ? 0 : 1); -- 2.7.4
Richard W.M. Jones
2016-Jul-14 08:49 UTC
[Libguestfs] [PATCH v2 4/7] customize: Add module for doing SELinux relabel of filesystem.
This implements the --selinux-relabel option for virt-customize, virt-builder and virt-sysprep. There is no need to autorelabel functionality now. Thanks: Stephen Smalley --- builder/Makefile.am | 1 + builder/virt-builder.pod | 20 +++++++++---------- customize/Makefile.am | 2 ++ customize/SELinux_relabel.ml | 46 +++++++++++++++++++++++++++++++++++++++++++ customize/SELinux_relabel.mli | 23 ++++++++++++++++++++++ customize/customize_run.ml | 14 +------------ generator/customize.ml | 4 ---- sysprep/Makefile.am | 1 + 8 files changed, 84 insertions(+), 27 deletions(-) create mode 100644 customize/SELinux_relabel.ml create mode 100644 customize/SELinux_relabel.mli diff --git a/builder/Makefile.am b/builder/Makefile.am index cc9e51d..d44cf4f 100644 --- a/builder/Makefile.am +++ b/builder/Makefile.am @@ -155,6 +155,7 @@ BOBJECTS = \ $(top_builddir)/customize/perl_edit.cmo \ $(top_builddir)/customize/crypt.cmo \ $(top_builddir)/customize/password.cmo \ + $(top_builddir)/customize/SELinux_relabel.cmo \ $(top_builddir)/customize/ssh_key.cmo \ $(top_builddir)/customize/subscription_manager.cmo \ $(top_builddir)/customize/customize_cmdline.cmo \ diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod index 91c1114..29a67a9 100644 --- a/builder/virt-builder.pod +++ b/builder/virt-builder.pod @@ -1756,20 +1756,21 @@ two possible strategies it can use to ensure correct labelling: =item Using I<--selinux-relabel> -This runs L<fixfiles(8)> just before finalizing the guest, which sets +This runs L<setfiles(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: +This is the recommended method. However it is sometimes not possible, +in particular where the host machine does not have the SELinux +setfiles command. In that case you must use: -=item Touching F</.autorelabel> +=item I<--touch> F</.autorelabel> -Guest templates may already contain a file called F</.autorelabel>, or -it is touched if I<--selinux-relabel> cannot run fixfiles. +Guest templates may already contain a file called F</.autorelabel> or +you may touch it. -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. +For guests that use SELinux, this causes L<restorecon(8)> to run at +first boot. Guests will reboot themselves once the first time you use +them, which is normal and harmless. =back @@ -1884,7 +1885,6 @@ L<gpg(1)>, L<curl(1)>, L<virt-make-fs(1)>, L<genisoimage(1)>, -L<fixfiles(8)>, L<http://libguestfs.org/>. =head1 AUTHOR diff --git a/customize/Makefile.am b/customize/Makefile.am index fbd584d..32104f2 100644 --- a/customize/Makefile.am +++ b/customize/Makefile.am @@ -43,6 +43,7 @@ SOURCES_MLI = \ password.mli \ perl_edit.mli \ random_seed.mli \ + SELinux_relabel.mli \ ssh_key.mli \ subscription_manager.mli \ timezone.mli \ @@ -58,6 +59,7 @@ SOURCES_ML = \ password.ml \ perl_edit.ml \ random_seed.ml \ + SELinux_relabel.ml \ ssh_key.ml \ subscription_manager.ml \ timezone.ml \ diff --git a/customize/SELinux_relabel.ml b/customize/SELinux_relabel.ml new file mode 100644 index 0000000..f3ed16d --- /dev/null +++ b/customize/SELinux_relabel.ml @@ -0,0 +1,46 @@ +(* 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 Common_gettext.Gettext +open Common_utils + +open Printf + +module G = Guestfs + +let relabel (g : G.guestfs) + (* 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". *) + let policy = g#aug_get "/files/etc/selinux/config/SELINUXTYPE" in + g#aug_close (); + + (* Get the spec file name. *) + let specfile + sprintf "/etc/selinux/%s/contexts/files/file_contexts" policy in + + (* Relabel everything. *) + g#setfiles ~force:true specfile "/"; + + (* If that worked, we don't need to autorelabel. *) + g#rm_f "/.autorelabel" diff --git a/customize/SELinux_relabel.mli b/customize/SELinux_relabel.mli new file mode 100644 index 0000000..b1548c8 --- /dev/null +++ b/customize/SELinux_relabel.mli @@ -0,0 +1,23 @@ +(* 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. + *) + +(** SELinux-relabel the filesystem. *) + +val relabel : Guestfs.guestfs -> unit +(** Relabel the mounted guestfs filesystem using the current SELinux + policy that applies to the guest. *) diff --git a/customize/customize_run.ml b/customize/customize_run.ml index b96e40c..6f0d615 100644 --- a/customize/customize_run.ml +++ b/customize/customize_run.ml @@ -414,19 +414,7 @@ exec >>%s 2>&1 if ops.flags.selinux_relabel then ( message (f_"SELinux relabelling"); - if guest_arch_compatible then ( - 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 - ) else ( - g#touch "/.autorelabel" - ) + SELinux_relabel.relabel g ); (* Clean up the log file: diff --git a/generator/customize.ml b/generator/customize.ml index 8caf2b5..d212c82 100644 --- a/generator/customize.ml +++ b/generator/customize.ml @@ -536,10 +536,6 @@ C</etc/pam.d/common-password> (Debian, Ubuntu)."; flag_pod_longdesc = "\ Relabel files in the guest so that they have the correct SELinux label. -This will attempt to relabel files immediately, but if the operation fails -this will instead touch F</.autorelabel> on the image to schedule a -relabel operation for the next time the image boots. - You should only use this option for guests which support SELinux."; }; diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am index 90f6b04..9dba5e1 100644 --- a/sysprep/Makefile.am +++ b/sysprep/Makefile.am @@ -123,6 +123,7 @@ BOBJECTS = \ $(top_builddir)/customize/timezone.cmo \ $(top_builddir)/customize/firstboot.cmo \ $(top_builddir)/customize/perl_edit.cmo \ + $(top_builddir)/customize/SELinux_relabel.cmo \ $(top_builddir)/customize/ssh_key.cmo \ $(top_builddir)/customize/subscription_manager.cmo \ $(top_builddir)/customize/customize_cmdline.cmo \ -- 2.7.4
Richard W.M. Jones
2016-Jul-14 08:49 UTC
[Libguestfs] [PATCH v2 5/7] builder: Use virt-sysprep --selinux-relabel when preparing templates.
Don't need to be clever now. --- builder/website/compress.sh | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/builder/website/compress.sh b/builder/website/compress.sh index bb5500c..1036a60 100644 --- a/builder/website/compress.sh +++ b/builder/website/compress.sh @@ -23,22 +23,11 @@ output=$1 relabel_args=() if [ -n "$DO_RELABEL" ]; then - os_arch=$(uname -m) - guest_arch=$(virt-inspector -a "$output" | virt-inspector --xpath "string(/operatingsystems/operatingsystem/arch)") - - if [ "$os_arch" = "$guest_arch" ] || [ "$os_arch" = "x86_64" -a "$guest_arch" = "i386" ]; then - # this is what --selinux-relabel should really do, but do it ourselves - # in the meanwhile -- see RHBZ#1089100. - relabel_args+=(--run-command "setfiles /etc/selinux/targeted/contexts/files/file_contexts /") - else - relabel_args+=(--selinux-relabel) - fi + relabel_args="--selinux-relabel" fi # Sysprep (removes logfiles and so on). -# Note this also touches /.autorelabel so the further installation -# changes that we make will be labelled properly at first boot. -virt-sysprep -a $output "${relabel_args[@]}" +virt-sysprep -a $output $relabel_args # Sparsify. mv $output $output.old -- 2.7.4
Richard W.M. Jones
2016-Jul-14 08:50 UTC
[Libguestfs] [PATCH v2 6/7] lib: Deprecate old SELinux APIs, rewrite SELinux documentation.
Also turns the --selinux option of guestfish, guestmount and virt-rescue into a no-op -- it didn't work before so this is effectively no change. --- builder/builder.ml | 6 ----- customize/customize_main.ml | 5 ---- dib/dib.ml | 6 ----- fish/fish.c | 5 ++-- fish/guestfish.pod | 2 +- fuse/guestmount.c | 5 ++-- fuse/guestmount.pod | 2 +- generator/actions.ml | 5 ++++ rescue/rescue.c | 5 ++-- rescue/virt-rescue.pod | 3 +-- src/guestfs.pod | 59 +++++++++++++++------------------------------ test-tool/test-tool.c | 1 - tests/selinux/run-test.pl | 2 -- 13 files changed, 33 insertions(+), 73 deletions(-) diff --git a/builder/builder.ml b/builder/builder.ml index b513ca3..15e1696 100644 --- a/builder/builder.ml +++ b/builder/builder.ml @@ -642,12 +642,6 @@ let main () may g#set_smp cmdline.smp; g#set_network cmdline.network; - (* Make sure to turn SELinux off to avoid awkward interactions - * between the appliance kernel and applications/libraries interacting - * with SELinux xattrs. - *) - g#set_selinux false; - (* The output disk is being created, so use cache=unsafe here. *) g#add_drive_opts ~format:output_format ~cachemode:"unsafe" output_filename; diff --git a/customize/customize_main.ml b/customize/customize_main.ml index 3681b32..82e70b7 100644 --- a/customize/customize_main.ml +++ b/customize/customize_main.ml @@ -169,11 +169,6 @@ read the man page virt-customize(1). may g#set_memsize memsize; may g#set_smp smp; g#set_network network; - (* Make sure to turn SELinux off to avoid awkward interactions - * between the appliance kernel and applications/libraries interacting - * with SELinux xattrs. - *) - g#set_selinux false; (* Add disks. *) add g dryrun; diff --git a/dib/dib.ml b/dib/dib.ml index 382c9d2..de4f242 100644 --- a/dib/dib.ml +++ b/dib/dib.ml @@ -634,12 +634,6 @@ let main () may g#set_smp cmdline.smp; g#set_network cmdline.network; - (* Make sure to turn SELinux off to avoid awkward interactions - * between the appliance kernel and applications/libraries interacting - * with SELinux xattrs. - *) - g#set_selinux false; - (* Main disk with the built image. *) let fmt = "raw" in let fn diff --git a/fish/fish.c b/fish/fish.c index f2f288e..49e1aaa 100644 --- a/fish/fish.c +++ b/fish/fish.c @@ -142,7 +142,7 @@ usage (int status) " --no-progress-bars Disable progress bars\n" " --remote[=pid] Send commands to remote %s\n" " -r|--ro Mount read-only\n" - " --selinux Enable SELinux support\n" + " --selinux For backwards compat only, does nothing\n" " -v|--verbose Verbose messages\n" " -V|--version Display version and exit\n" " -w|--rw Mount read-write\n" @@ -267,8 +267,7 @@ main (int argc, char *argv[]) " to the PID of the remote process")); } } else if (STREQ (long_options[option_index].name, "selinux")) { - if (guestfs_set_selinux (g, 1) == -1) - exit (EXIT_FAILURE); + /* nothing */ } else if (STREQ (long_options[option_index].name, "keys-from-stdin")) { keys_from_stdin = 1; } else if (STREQ (long_options[option_index].name, "progress-bars")) { diff --git a/fish/guestfish.pod b/fish/guestfish.pod index bbeea82..257c659 100644 --- a/fish/guestfish.pod +++ b/fish/guestfish.pod @@ -407,7 +407,7 @@ See also L</OPENING DISKS FOR READ AND WRITE> below. =item B<--selinux> -Enable SELinux support for the guest. See L<guestfs(3)/SELINUX>. +This option is provided for backwards compatibility and does nothing. =item B<-v> diff --git a/fuse/guestmount.c b/fuse/guestmount.c index f72ecb8..4461c65 100644 --- a/fuse/guestmount.c +++ b/fuse/guestmount.c @@ -123,7 +123,7 @@ usage (int status) " -o|--option opt Pass extra option to FUSE\n" " --pid-file filename Write PID to filename\n" " -r|--ro Mount read-only\n" - " --selinux Enable SELinux support\n" + " --selinux For backwards compat only, does nothing\n" " -v|--verbose Verbose messages\n" " -V|--version Display version and exit\n" " -w|--rw Mount read-write\n" @@ -225,8 +225,7 @@ main (int argc, char *argv[]) else if (STREQ (long_options[option_index].name, "fuse-help")) fuse_help (); else if (STREQ (long_options[option_index].name, "selinux")) { - if (guestfs_set_selinux (g, 1) == -1) - exit (EXIT_FAILURE); + /* nothing */ } else if (STREQ (long_options[option_index].name, "format")) { OPTION_format; } else if (STREQ (long_options[option_index].name, "keys-from-stdin")) { diff --git a/fuse/guestmount.pod b/fuse/guestmount.pod index e7f37ae..be075e5 100644 --- a/fuse/guestmount.pod +++ b/fuse/guestmount.pod @@ -362,7 +362,7 @@ See also L<guestfish(1)/OPENING DISKS FOR READ AND WRITE>. =item B<--selinux> -Enable SELinux support for the guest. +This option is provided for backwards compatibility and does nothing. =item B<-v> diff --git a/generator/actions.ml b/generator/actions.ml index 49c360c..a86d47a 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -645,6 +645,7 @@ Use C<guestfs_available> or C<guestfs_feature_available> instead." }; style = RErr, [Bool "selinux"], []; fish_alias = ["selinux"]; config_only = true; blocking = false; + deprecated_by = Some "setfiles"; shortdesc = "set SELinux enabled or disabled at appliance boot"; longdesc = "\ This sets the selinux flag that is passed to the appliance @@ -660,6 +661,7 @@ see L<guestfs(3)>." }; name = "get_selinux"; added = (1, 0, 67); style = RBool "selinux", [], []; blocking = false; + deprecated_by = Some "setfiles"; shortdesc = "get SELinux enabled flag"; longdesc = "\ This returns the current setting of the selinux flag which @@ -7555,6 +7557,7 @@ away any pending events, and deallocates all resources." }; style = RErr, [String "context"], []; proc_nr = Some 185; optional = Some "selinux"; + deprecated_by = Some "setfiles"; shortdesc = "set SELinux security context"; longdesc = "\ This sets the SELinux security context of the daemon @@ -7567,6 +7570,7 @@ See the documentation about SELINUX in L<guestfs(3)>." }; style = RString "context", [], []; proc_nr = Some 186; optional = Some "selinux"; + deprecated_by = Some "setfiles"; shortdesc = "get SELinux security context"; longdesc = "\ This gets the SELinux security context of the daemon. @@ -10126,6 +10130,7 @@ This option may not be specified at the same time as the C<correct> option. name = "llz"; added = (1, 17, 6); style = RString "listing", [Pathname "directory"], []; proc_nr = Some 305; + deprecated_by = Some "lgetxattrs"; shortdesc = "list the files in a directory (long format with SELinux contexts)"; longdesc = "\ List the files in F<directory> in the format of 'ls -laZ'. diff --git a/rescue/rescue.c b/rescue/rescue.c index 135c9e6..ba123a3 100644 --- a/rescue/rescue.c +++ b/rescue/rescue.c @@ -73,7 +73,7 @@ usage (int status) " --network Enable network\n" " -r|--ro Access read-only\n" " --scratch[=N] Add scratch disk(s)\n" - " --selinux Enable SELinux\n" + " --selinux For backwards compat only, does nothing\n" " --smp N Enable SMP with N >= 2 virtual CPUs\n" " --suggest Suggest mount commands for this guest\n" " -v|--verbose Verbose messages\n" @@ -147,8 +147,7 @@ main (int argc, char *argv[]) else if (STREQ (long_options[option_index].name, "short-options")) display_short_options (options); else if (STREQ (long_options[option_index].name, "selinux")) { - if (guestfs_set_selinux (g, 1) == -1) - exit (EXIT_FAILURE); + /* nothing */ } else if (STREQ (long_options[option_index].name, "append")) { append = optarg; } else if (STREQ (long_options[option_index].name, "network")) { diff --git a/rescue/virt-rescue.pod b/rescue/virt-rescue.pod index bb563bc..00f03aa 100644 --- a/rescue/virt-rescue.pod +++ b/rescue/virt-rescue.pod @@ -209,8 +209,7 @@ command line. =item B<--selinux> -Enable SELinux in the rescue appliance. You should read -L<guestfs(3)/SELINUX> before using this option. +This option is provided for backwards compatibility and does nothing. =item B<--smp> N diff --git a/src/guestfs.pod b/src/guestfs.pod index 2a199c0..2855d70 100644 --- a/src/guestfs.pod +++ b/src/guestfs.pod @@ -458,8 +458,8 @@ an X86 host). =item * -For SELinux guests, you may need to enable SELinux and load policy -first. See L</SELINUX> in this manpage. +For SELinux guests, you may need to relabel the guest after +creating new files. See L</SELINUX> below. =item * @@ -511,44 +511,23 @@ L<sd-journal(3)>, L<sd_journal_open(3)>. =head2 SELINUX -We support SELinux guests. To ensure that labeling happens correctly -in SELinux guests, you need to enable SELinux and load the guest's -policy: - -=over 4 - -=item 1. - -Before launching, do: - - guestfs_set_selinux (g, 1); - -=item 2. - -After mounting the guest's filesystem(s), load the policy. This -is best done by running the L<load_policy(8)> command in the -guest itself: - - guestfs_sh (g, "/usr/sbin/load_policy"); - -(Older versions of C<load_policy> require you to specify the -name of the policy file). - -=item 3. - -Optionally, set the security context for the API. The correct -security context to use can only be known by inspecting the -guest. As an example: - - guestfs_setcon (g, "unconfined_u:unconfined_r:unconfined_t:s0"); - -=back - -This will work for running commands and editing existing files. - -When new files are created, you may need to label them explicitly, -for example by running the external command -C<restorecon pathname>. +We support SELinux guests. However it is not possible to load the +SELinux policy of the guest into the appliance kernel. Therefore the +strategy for dealing with SELinux guests is to relabel them after +making changes. + +In libguestfs E<ge> 1.34 there is a new API, L</guestfs_setfiles>, +which can be used for this. To properly use this API you have to +parse the guest SELinux configuration. See the L<virt-customize(1)> +module F<customize/SELinux_relabel.ml> for how to do this. + +A simpler but slower alternative is to touch F</.autorelabel> in the +guest, which means that the guest will relabel itself at next boot. + +Libguestfs E<le> 1.32 had APIs C<guestfs_set_selinux>, +C<guestfs_get_selinux>, C<guestfs_setcon> and C<guestfs_getcon>. +These did not work properly, are deprecated, and should not be used in +new code. =head2 UMASK diff --git a/test-tool/test-tool.c b/test-tool/test-tool.c index c632440..ad1601c 100644 --- a/test-tool/test-tool.c +++ b/test-tool/test-tool.c @@ -234,7 +234,6 @@ main (int argc, char *argv[]) printf ("guestfs_get_pgroup: %d\n", guestfs_get_pgroup (g)); printf ("guestfs_get_program: %s\n", guestfs_get_program (g)); printf ("guestfs_get_recovery_proc: %d\n", guestfs_get_recovery_proc (g)); - printf ("guestfs_get_selinux: %d\n", guestfs_get_selinux (g)); printf ("guestfs_get_smp: %d\n", guestfs_get_smp (g)); p = guestfs_get_sockdir (g); printf ("guestfs_get_sockdir: %s\n", p ? : "(null)"); diff --git a/tests/selinux/run-test.pl b/tests/selinux/run-test.pl index f0f241f..7e4620f 100755 --- a/tests/selinux/run-test.pl +++ b/tests/selinux/run-test.pl @@ -105,8 +105,6 @@ if ($test_type eq "selinux" && $test_via eq "fuse") { # Create a filesystem that could support xattrs and SELinux labels. my $g = Sys::Guestfs->new (); -#$g->set_selinux (1) if $test_type eq "selinux"; - $g->add_drive_scratch (256*1024*1024); $g->launch (); -- 2.7.4
Richard W.M. Jones
2016-Jul-14 08:50 UTC
[Libguestfs] [PATCH v2 7/7] v2v: linux: Use new SELinux_relabel module to relabel Linux guests.
--- v2v/Makefile.am | 1 + v2v/convert_linux.ml | 14 ++++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/v2v/Makefile.am b/v2v/Makefile.am index fc83600..cd15e30 100644 --- a/v2v/Makefile.am +++ b/v2v/Makefile.am @@ -131,6 +131,7 @@ BOBJECTS = \ $(top_builddir)/mllib/curl.cmo \ $(top_builddir)/customize/customize_utils.cmo \ $(top_builddir)/customize/firstboot.cmo \ + $(top_builddir)/customize/SELinux_relabel.cmo \ $(SOURCES_ML:.ml=.cmo) XOBJECTS = $(BOBJECTS:.cmo=.cmx) diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml index e8bb0d3..ef71318 100644 --- a/v2v/convert_linux.ml +++ b/v2v/convert_linux.ml @@ -405,12 +405,13 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps | `Grub2 -> () (* Not necessary for grub2. *) - and autorelabel () - (* Only do autorelabel if load_policy binary exists. Actually - * loading the policy is problematic. + and relabel () + (* Only do relabel if load_policy binary and /etc/selinux/config + * files exist, indicating that the guest uses SELinux. *) - if g#is_file ~followsymlinks:true "/usr/sbin/load_policy" then - g#touch "/.autorelabel"; + if g#is_file ~followsymlinks:true "/usr/sbin/load_policy" && + g#is_file ~followsymlinks:true "/etc/selinux/config" then + SELinux_relabel.relabel g; and unconfigure_xen () (* Remove kmod-xenpv-* (RHEL 3). *) @@ -1411,7 +1412,6 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps in augeas_grub_configuration (); - autorelabel (); unconfigure_xen (); unconfigure_vbox (); @@ -1452,6 +1452,8 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps configure_kernel_modules block_type net_type; rebuild_initrd kernel; + relabel (); + let guestcaps = { gcaps_block_bus = block_type; gcaps_net_bus = net_type; -- 2.7.4
Pino Toscano
2016-Jul-14 09:48 UTC
Re: [Libguestfs] [PATCH v2 2/7] New API: setfiles - SELinux relabel parts of the filesystem.
On Thursday, 14 July 2016 09:49:56 CEST Richard W.M. Jones wrote:> --- > appliance/packagelist.in | 1 + > daemon/Makefile.am | 1 + > daemon/setfiles.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++ > generator/actions.ml | 22 ++++++++++++ > gobject/Makefile.inc | 2 ++ > src/MAX_PROC_NR | 2 +- > 6 files changed, 120 insertions(+), 1 deletion(-) > create mode 100644 daemon/setfiles.c > > diff --git a/appliance/packagelist.in b/appliance/packagelist.in > index 5f04c1c..3a4790b 100644 > --- a/appliance/packagelist.in > +++ b/appliance/packagelist.in > @@ -43,6 +43,7 @@ ifelse(REDHAT,1, > ntfs-3g > openssh-clients > pcre > + policycoreutils > reiserfs-utils > libselinux > syslinux-extlinux > diff --git a/daemon/Makefile.am b/daemon/Makefile.am > index b77d1e7..9bd495f 100644 > --- a/daemon/Makefile.am > +++ b/daemon/Makefile.am > @@ -168,6 +168,7 @@ guestfsd_SOURCES = \ > rsync.c \ > scrub.c \ > selinux.c \ > + setfiles.c \Why not directly in selinux.c? IMHO would be more logic (all the SELinux stuff in the daemon grouped there).> sfdisk.c \ > sh.c \ > sleep.c \ > diff --git a/daemon/setfiles.c b/daemon/setfiles.c > new file mode 100644 > index 0000000..3f249c3 > --- /dev/null > +++ b/daemon/setfiles.c > @@ -0,0 +1,93 @@ > +/* libguestfs - the guestfsd daemon > + * 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. > + */ > + > +#include <config.h> > + > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > + > +#include "guestfs_protocol.h" > +#include "daemon.h" > +#include "actions.h" > + > +GUESTFSD_EXT_CMD(str_setfiles, setfiles); > + > +#define MAX_ARGS 64 > + > +/* Takes optional arguments, consult optargs_bitmask. */ > +int > +do_setfiles (const char *specfile, const char *path, > + int force) > +{ > + const char *argv[MAX_ARGS]; > + CLEANUP_FREE char *s_dev = NULL, *s_proc = NULL, *s_selinux = NULL, > + *s_sys = NULL, *s_specfile = NULL, *s_path = NULL; > + CLEANUP_FREE char *err = NULL; > + size_t i = 0; > + > + s_dev = sysroot_path ("/dev"); > + if (!s_dev) { > + malloc_error: > + reply_with_perror ("malloc"); > + return -1; > + } > + s_proc = sysroot_path ("/proc"); if (!s_proc) goto malloc_error; > + s_selinux = sysroot_path ("/selinux"); if (!s_selinux) goto malloc_error; > + s_sys = sysroot_path ("/sys"); if (!s_sys) goto malloc_error; > + s_specfile = sysroot_path (specfile); if (!s_specfile) goto malloc_error; > + s_path = sysroot_path (path); if (!s_path) goto malloc_error;I'd simpy do all the sysroot_path calls one after each other, and then check all the results at once: if (!s_dev || !s_proc ...) All these buffers are CLEANUP_FREE anyway, and this could IMHO simplify the reading/organization of the code.> + /* Default settings if not selected. */ > + if (!(optargs_bitmask & GUESTFS_SETFILES_FORCE_BITMASK)) > + force = 0; > + > + ADD_ARG (argv, i, str_setfiles); > + if (force) > + ADD_ARG (argv, i, "-F"); > + > + /* Exclude some directories that should never be relabelled in > + * ordinary Linux guests. These won't be mounted anyway. We have > + * to prefix all these with the sysroot path. > + */ > + ADD_ARG (argv, i, "-e"); ADD_ARG (argv, i, s_dev); > + ADD_ARG (argv, i, "-e"); ADD_ARG (argv, i, s_proc); > + ADD_ARG (argv, i, "-e"); ADD_ARG (argv, i, s_selinux); > + ADD_ARG (argv, i, "-e"); ADD_ARG (argv, i, s_sys); > + > + /* Relabelling in a chroot. */ > + if (STRNEQ (sysroot, "/")) { > + ADD_ARG (argv, i, "-r"); > + ADD_ARG (argv, i, sysroot); > + } > + > + /* Suppress non-error output. */ > + ADD_ARG (argv, i, "-q"); > + > + /* Add parameters. */ > + ADD_ARG (argv, i, s_specfile); > + ADD_ARG (argv, i, s_path); > + ADD_ARG (argv, i, NULL); > + > + if (commandv (NULL, &err, argv) == -1) { > + reply_with_perror ("%s", err); > + return -1; > + } > + > + return 0; > +} > diff --git a/generator/actions.ml b/generator/actions.ml > index 25108a2..49c360c 100644 > --- a/generator/actions.ml > +++ b/generator/actions.ml > @@ -13149,6 +13149,28 @@ fails and the C<errno> is set to C<ENODEV>." }; > shortdesc = "walk through the filesystem content"; > longdesc = "Internal function for filesystem_walk." }; > > + { defaults with > + name = "setfiles"; added = (1, 33, 43); > + style = RErr, [String "specfile"; Pathname "path"], [OBool "force"]; > + proc_nr = Some 467;This needs to be feature-dependent IMHO, so it will fail gracefully on non-SELinux hosts. Thanks, -- Pino Toscano
Pino Toscano
2016-Jul-14 09:48 UTC
Re: [Libguestfs] [PATCH v2 4/7] customize: Add module for doing SELinux relabel of filesystem.
On Thursday, 14 July 2016 09:49:58 CEST Richard W.M. Jones wrote:> This implements the --selinux-relabel option for virt-customize, > virt-builder and virt-sysprep. There is no need to autorelabel > functionality now.IMHO this needs to fallback on /.autorelabel, on hosts where the SELinux stuff is not available. As suggested for patch #2, a feature could do it. Also, this could mention rhbz#554829 & rhbz#983969 & rhbz#1089100. Thanks, -- Pino Toscano
Pino Toscano
2016-Jul-14 09:48 UTC
Re: [Libguestfs] [PATCH v2 6/7] lib: Deprecate old SELinux APIs, rewrite SELinux documentation.
On Thursday, 14 July 2016 09:50:00 CEST Richard W.M. Jones wrote:> Also turns the --selinux option of guestfish, guestmount and > virt-rescue into a no-op -- it didn't work before so this is > effectively no change.Could this mention rhbz#1152825? -- Pino Toscano