diff --git a/daemon/selinux.ml b/daemon/selinux.ml index d954fdead..db0d71455 100644 --- a/daemon/selinux.ml +++ b/daemon/selinux.ml @@ -44,58 +44,65 @@ let setfiles_has_option_m, (fun () -> Lazy.force setfiles_has_option_C), (fun () -> Lazy.force setfiles_has_option_T) -let selinux_relabel ?(force = false) specfile path = - (* Prefix /sysroot on all paths. *) - let ignored_paths = - [ "/dev"; "/proc"; "/selinux"; "/sys" ] |> - List.map sysroot_path in - let specfile = sysroot_path specfile in - let path = sysroot_path path in +let setfiles ?(force = false) specfile paths = + if paths = [] then () + else ( + (* Prefix /sysroot on all paths. *) + let ignored_paths = + [ "/dev"; "/proc"; "/selinux"; "/sys" ] |> + List.map sysroot_path in + let specfile = sysroot_path specfile in + let paths = List.map sysroot_path paths in - let args = ref [] in - if force then List.push_back args "-F"; - List.iter ( - fun ignored_path -> - List.push_back_list args [ "-e"; ignored_path ] - ) ignored_paths; + let args = ref [] in + if force then List.push_back args "-F"; + List.iter ( + fun ignored_path -> + List.push_back_list args [ "-e"; ignored_path ] + ) ignored_paths; - (* You have to use the -m option (where available) otherwise - * setfiles puts all the mountpoints on the excludes list for no - * useful reason (RHBZ#1433577). - *) - if setfiles_has_option_m () then List.push_back args "-m"; + (* You have to use the -m option (where available) otherwise + * setfiles puts all the mountpoints on the excludes list for no + * useful reason (RHBZ#1433577). + *) + if setfiles_has_option_m () then List.push_back args "-m"; - (* Not only do we want setfiles to trudge through individual relabeling - * errors, we also want the setfiles exit status to differentiate a fatal - * error from "relabeling errors only". See RHBZ#1794518. - *) - if setfiles_has_option_C () then List.push_back args "-C"; + (* Not only do we want setfiles to trudge through individual relabeling + * errors, we also want the setfiles exit status to differentiate a fatal + * error from "relabeling errors only". See RHBZ#1794518. + *) + if setfiles_has_option_C () then List.push_back args "-C"; - (* If the appliance is being run with multiple vCPUs, running setfiles - * in multithreading mode might speeds up the process. Option "-T" was - * introduced in SELinux userspace v3.4, and we need to check whether it's - * supported. Passing "-T 0" creates as many threads as there're available - * vCPU cores. - * https://github.com/SELinuxProject/selinux/releases/tag/3.4 - *) - if setfiles_has_option_T () then - List.push_back_list args [ "-T"; "0" ]; + (* If the appliance is being run with multiple vCPUs, running setfiles + * in multithreading mode might speeds up the process. Option "-T" was + * introduced in SELinux userspace v3.4, and we need to check whether it's + * supported. Passing "-T 0" creates as many threads as there're available + * vCPU cores. + * https://github.com/SELinuxProject/selinux/releases/tag/3.4 + *) + if setfiles_has_option_T () then + List.push_back_list args [ "-T"; "0" ]; - (* Relabelling in a chroot. *) - if sysroot () <> "/" then - List.push_back_list args [ "-r"; sysroot () ]; + (* Relabelling in a chroot. *) + if sysroot () <> "/" then + List.push_back_list args [ "-r"; sysroot () ]; - if verbose () then - List.push_back args "-v" - else - (* Suppress non-error output. *) - List.push_back args "-q"; + if verbose () then + List.push_back args "-v" + else + (* Suppress non-error output. *) + List.push_back args "-q"; - (* Add parameters. *) - List.push_back_list args [ specfile; path ]; + (* Add parameters. *) + List.push_back args specfile; + List.push_back_list args paths; - let args = !args in - let r, _, err = commandr "setfiles" args in + let args = !args in + let r, _, err = commandr "setfiles" args in - let ok = r = 0 || r = 1 && setfiles_has_option_C () in - if not ok then failwithf "setfiles: %s" err + let ok = r = 0 || r = 1 && setfiles_has_option_C () in + if not ok then failwithf "setfiles: %s" err + ) + +(* This is the deprecated selinux_relabel function from libguestfs <= 1.56. *) +let selinux_relabel ?force specfile path = setfiles ?force specfile [path] diff --git a/generator/actions_core.ml b/generator/actions_core.ml index 128cbe0e9..60d3140ed 100644 --- a/generator/actions_core.ml +++ b/generator/actions_core.ml @@ -9356,29 +9356,6 @@ Show all the devices where the filesystems in C is spanned over. If not all the devices for the filesystems are present, then this function fails and the C is set to C." }; - { defaults with - name = "selinux_relabel"; added = (1, 33, 43); - style = RErr, [String (PlainString, "specfile"); String (Pathname, "path")], [OBool "force"]; - impl = OCaml "Selinux.selinux_relabel"; - optional = Some "selinuxrelabel"; - test_excuse = "tests are in the tests/relabel directory"; - shortdesc = "relabel parts of the filesystem"; - longdesc = "\ -SELinux relabel parts of the filesystem. - -The C parameter controls the policy spec file used. -You have to parse C to find the correct -SELinux policy and then pass the spec file, usually: -C + I + C. - -The required C parameter is the top level directory where -relabelling starts. Normally you should pass C as C -to relabel the whole guest filesystem. - -The optional C 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." }; - { defaults with name = "mksquashfs"; added = (1, 35, 25); style = RErr, [String (Pathname, "path"); String (FileOut, "filename")], [OString "compress"; OStringList "excludes"]; @@ -9820,4 +9797,30 @@ them visible. Use C to list all device mapper devices." }; + { defaults with + name = "setfiles"; added = (1, 57, 1); + style = RErr, [String (PlainString, "specfile"); StringList (Pathname, "paths")], [OBool "force"]; + impl = OCaml "Selinux.setfiles"; + optional = Some "selinuxrelabel"; + test_excuse = "tests are in the tests/relabel directory"; + shortdesc = "low level relabel parts of the filesystem"; + longdesc = "\ +This invokes the SELinux C command which is a low +level tool used to relabel parts of the filesystem. + +The C parameter controls the policy spec file used. +You have to parse C to find the correct +SELinux policy and then pass the spec file, usually: +C + I + C. + +The required C parameter is the list of top level directories +where relabelling starts. C will only relabel up to +filesystem boundaries so, for example, passing just C<\"/\"> will +relabel the whole root filesystem, but no other mounted filesystems. +If the list is empty, setfiles is not called. + +The optional C 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." }; + ] diff --git a/generator/actions_core_deprecated.ml b/generator/actions_core_deprecated.ml index 9d4b29f9d..2b1f5cdb4 100644 --- a/generator/actions_core_deprecated.ml +++ b/generator/actions_core_deprecated.ml @@ -942,4 +942,28 @@ This call does nothing and returns an error." }; Used to check a btrfs filesystem, C is the device file where the filesystem is stored." }; + { defaults with + name = "selinux_relabel"; added = (1, 33, 43); + style = RErr, [String (PlainString, "specfile"); String (Pathname, "path")], [OBool "force"]; + impl = OCaml "Selinux.selinux_relabel"; + optional = Some "selinuxrelabel"; + deprecated_by = Replaced_by "setfiles"; + test_excuse = "tests are in the tests/relabel directory"; + shortdesc = "relabel parts of the filesystem"; + longdesc = "\ +SELinux relabel parts of the filesystem. + +The C parameter controls the policy spec file used. +You have to parse C to find the correct +SELinux policy and then pass the spec file, usually: +C + I + C. + +The required C parameter is the top level directory where +relabelling starts. Normally you should pass C as C +to relabel the whole guest filesystem. + +The optional C 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." }; + ] diff --git a/generator/proc_nr.ml b/generator/proc_nr.ml index 63cd72a3c..42624afef 100644 --- a/generator/proc_nr.ml +++ b/generator/proc_nr.ml @@ -521,6 +521,7 @@ let proc_nr = [ 516, "command_out"; 517, "sh_out"; 518, "btrfs_scrub_full"; +519, "setfiles"; ] (* End of list. If adding a new entry, add it at the end of the list diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc index b54245977..b828113c6 100644 --- a/gobject/Makefile.inc +++ b/gobject/Makefile.inc @@ -106,6 +106,7 @@ guestfs_gobject_headers= \ include/guestfs-gobject/optargs-rsync_out.h \ include/guestfs-gobject/optargs-selinux_relabel.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 \ @@ -201,6 +202,7 @@ guestfs_gobject_sources= \ src/optargs-rsync_out.c \ src/optargs-selinux_relabel.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/lib/MAX_PROC_NR b/lib/MAX_PROC_NR index 9a26b94d0..08f851b6e 100644 --- a/lib/MAX_PROC_NR +++ b/lib/MAX_PROC_NR @@ -1 +1 @@ -518 +519 diff --git a/tests/relabel/test-relabel.pl b/tests/relabel/test-relabel.pl index 06fb0840b..4d4f6c7ba 100755 --- a/tests/relabel/test-relabel.pl +++ b/tests/relabel/test-relabel.pl @@ -87,7 +87,7 @@ $g->write ("/etc/file_contexts", <<'EOF'); EOF # Do the relabel. -$g->selinux_relabel ("/etc/file_contexts", "/", force => 1); +$g->setfiles ("/etc/file_contexts", ["/"], force => 1); # Check the labels were set correctly. my $errors = 0;