From 583fc558f3cc7a38cb35eb91f63273dbba95e871 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Wed, 13 Aug 2025 18:09:20 +0100 Subject: [PATCH] Fix conversion of SLES15 with encrypted btrfs filesystem resolves: RHEL-93584 Add guestfs_setfiles API resolves: RHEL-108832 --- 0006-docs-Fix-dead-ntfs-3g-doc-links.patch | 50 +++ ...ct-check-etc-crypttab-for-dev-mapper.patch | 178 ++++++++ ...void-double-when-creating-sysroot-pa.patch | 42 ++ ...void-copying-the-path-every-time-we-.patch | 49 +++ ...ent-guestfs_selinux_relabel-in-OCaml.patch | 406 ++++++++++++++++++ ...ement-StringList-for-OCaml-functions.patch | 99 +++++ ...Allow-StringList-Pathname-parameters.patch | 83 ++++ ...-guestfs_selinux_relabel-replace-wit.patch | 311 ++++++++++++++ ...upported-remote-drive-protocols-RHBZ.patch | 6 +- ...of-libguestfs-winsupport-features-ex.patch | 2 +- ...nit-Run-depmod-a-to-rebuild-kernel-m.patch | 2 +- libguestfs.spec | 22 +- 12 files changed, 1240 insertions(+), 10 deletions(-) create mode 100644 0006-docs-Fix-dead-ntfs-3g-doc-links.patch create mode 100644 0007-daemon-inspect-check-etc-crypttab-for-dev-mapper.patch create mode 100644 0008-daemon-sysroot-Avoid-double-when-creating-sysroot-pa.patch create mode 100644 0009-daemon-sysroot-Avoid-copying-the-path-every-time-we-.patch create mode 100644 0010-daemon-Reimplement-guestfs_selinux_relabel-in-OCaml.patch create mode 100644 0011-generator-Implement-StringList-for-OCaml-functions.patch create mode 100644 0012-generator-Allow-StringList-Pathname-parameters.patch create mode 100644 0013-daemon-Deprecate-guestfs_selinux_relabel-replace-wit.patch rename 0006-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch => 0014-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch (99%) rename 0007-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch => 0015-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch (97%) rename 0008-RHEL-appliance-init-Run-depmod-a-to-rebuild-kernel-m.patch => 0016-RHEL-appliance-init-Run-depmod-a-to-rebuild-kernel-m.patch (90%) diff --git a/0006-docs-Fix-dead-ntfs-3g-doc-links.patch b/0006-docs-Fix-dead-ntfs-3g-doc-links.patch new file mode 100644 index 0000000..9bb3e31 --- /dev/null +++ b/0006-docs-Fix-dead-ntfs-3g-doc-links.patch @@ -0,0 +1,50 @@ +From 701667b6f581a824059c4da50eb4df176decbb82 Mon Sep 17 00:00:00 2001 +From: Cole Robinson +Date: Thu, 31 Jul 2025 15:27:38 -0400 +Subject: [PATCH] docs: Fix dead ntfs-3g doc links + +--- + generator/actions_core.ml | 4 ++-- + lib/guestfs.pod | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/generator/actions_core.ml b/generator/actions_core.ml +index 0f39fd509..108494ece 100644 +--- a/generator/actions_core.ml ++++ b/generator/actions_core.ml +@@ -4661,8 +4661,8 @@ as F may appear as F or F + they were created. In Windows itself this would not be + a problem. + +-Bug or feature? You decide: +-L ++Bug or feature? You decide. See the relevant entry in the ntfs-3g FAQ: ++L + + C attempts to resolve the true case of + each element in the path. It will return a resolved path if either the +diff --git a/lib/guestfs.pod b/lib/guestfs.pod +index f69d5a070..505978aa1 100644 +--- a/lib/guestfs.pod ++++ b/lib/guestfs.pod +@@ -984,7 +984,7 @@ Ntfs-3g tries to rewrite "Junction Points" and NTFS "symbolic links" + to provide something which looks like a Linux symlink. The way it + tries to do the rewriting is described here: + +-L ++L + + The essential problem is that ntfs-3g simply does not have enough + information to do a correct job. NTFS links can contain drive letters +@@ -1003,7 +1003,7 @@ format documented in various places around the web). + There are other useful extended attributes that can be read from + ntfs-3g filesystems (using L). See: + +-L ++L + + =head3 WINDOWS HIBERNATION AND WINDOWS 8 FAST STARTUP + +-- +2.47.1 + diff --git a/0007-daemon-inspect-check-etc-crypttab-for-dev-mapper.patch b/0007-daemon-inspect-check-etc-crypttab-for-dev-mapper.patch new file mode 100644 index 0000000..d8d2c37 --- /dev/null +++ b/0007-daemon-inspect-check-etc-crypttab-for-dev-mapper.patch @@ -0,0 +1,178 @@ +From 06db19c56c0a4e81596b24a7ab74ed545b422e4c Mon Sep 17 00:00:00 2001 +From: Cole Robinson +Date: Thu, 12 Jun 2025 14:42:33 -0400 +Subject: [PATCH] daemon: inspect: check /etc/crypttab for /dev/mapper/* + +Encrypted root fs on SUSE distros will present itself like so: + +``` +/dev/mapper/cr_root / btrfs defaults 0 0 +UUID=588905f9-bfa4-47b5-9fe8-893cb8ad4a0b /var btrfs subvol=/@/var 0 0 +... more subvols here ... +UUID=8a278363-3042-4dea-a878-592f5e1b7381 swap btrfs defaults 0 0 +/dev/mapper/cr_root /.snapshots btrfs subvol=/@/.snapshots 0 0 + +cr_root UUID=5289379a-a707-41b5-994c-c383f7ed54cc none x-initrd.attach +``` + +This breaks `-i` inspection, since libguestfs doesn't know what +/dev/mapper/cr_root is supposed to be, and nothing in the appliance +will autopopulate that path. This isn't a problem on Fedora, where +it uses UUID= instead of a /dev/mapper path. + +Currently when we see /dev/mapper as a mount prefix, we only attempt +to do some LVM name mapping. This extends libguestfs to check +/etc/crypttab first. If we find an entry for the mapper path, and it +points to the encrypted luks UUID, we use that UUID to build the +associated /dev/disk/by-id/dm-uuid-CRYPT-* path, which is a symlink +to the unencrypted /dev/dm-X path + +Resolves: https://issues.redhat.com/browse/RHEL-93584 + +Signed-off-by: Cole Robinson +--- + daemon/inspect_fs_unix_fstab.ml | 93 +++++++++++++++++++++++++-------- + 1 file changed, 70 insertions(+), 23 deletions(-) + +diff --git a/daemon/inspect_fs_unix_fstab.ml b/daemon/inspect_fs_unix_fstab.ml +index b4652a39d..bd1b8e540 100644 +--- a/daemon/inspect_fs_unix_fstab.ml ++++ b/daemon/inspect_fs_unix_fstab.ml +@@ -41,7 +41,7 @@ let rec check_fstab ?(mdadm_conf = false) (root_mountable : Mountable.t) + os_type = + let mdadmfiles = + if mdadm_conf then ["/etc/mdadm.conf"; "/etc/mdadm/mdadm.conf"] else [] in +- let configfiles = "/etc/fstab" :: mdadmfiles in ++ let configfiles = "/etc/fstab" :: "/etc/crypttab" :: mdadmfiles in + + (* If verbose, dump the contents of each config file as that can be + * useful for debugging. +@@ -179,7 +179,7 @@ and check_fstab_entry md_map root_mountable os_type aug entry = + root_mountable + (* Resolve guest block device names. *) + else if String.starts_with "/dev/" spec then +- resolve_fstab_device spec md_map os_type ++ resolve_fstab_device spec md_map os_type aug + (* In OpenBSD's fstab you can specify partitions + * on a disk by appending a period and a partition + * letter to a Disklable Unique Identifier. The +@@ -194,7 +194,7 @@ and check_fstab_entry md_map root_mountable os_type aug entry = + * assume that this is the first disk. + *) + let device = sprintf "/dev/sd0%c" part in +- resolve_fstab_device device md_map os_type ++ resolve_fstab_device device md_map os_type aug + ) + (* Ignore "/.swap" (Pardus) and pseudo-devices + * like "tmpfs". If we haven't resolved the device +@@ -353,7 +353,7 @@ and parse_md_uuid uuid = + * the real VM, which is a reasonable assumption to make. Return + * anything we don't recognize unchanged. + *) +-and resolve_fstab_device spec md_map os_type = ++and resolve_fstab_device spec md_map os_type aug = + (* In any case where we didn't match a device pattern or there was + * another problem, return this default mountable derived from [spec]. + *) +@@ -366,7 +366,7 @@ and resolve_fstab_device spec md_map os_type = + + if String.starts_with "/dev/mapper" spec then ( + debug_matching "/dev/mapper"; +- resolve_dev_mapper spec default ++ resolve_dev_mapper spec default aug + ) + + else if PCRE.matches re_xdev spec then ( +@@ -540,24 +540,71 @@ and resolve_fstab_device spec md_map os_type = + default + ) + +-and resolve_dev_mapper spec default = +- (* LVM2 does some strange munging on /dev/mapper paths for VGs and +- * LVs which contain '-' character: +- * +- * > lvcreate LV--test VG--test 32 +- * > debug ls /dev/mapper +- * VG----test-LV----test +- * +- * This makes it impossible to reverse those paths directly, so +- * we have implemented lvm_canonical_lv_name in the daemon. +- *) +- try +- match Lvm_utils.lv_canonical spec with +- | None -> default +- | Some device -> Mountable.of_device device +- with +- (* Ignore devices that don't exist. (RHBZ#811872) *) +- | Unix.Unix_error (Unix.ENOENT, _, _) -> default ++and resolve_dev_mapper spec default aug = ++ let augpath = ++ sprintf "/files/etc/crypttab/*[target='%s']/device" ++ (Filename.basename spec) in ++ match aug_get_noerrors aug augpath with ++ | Some device -> ++ (* /dev/mapper name is present in /etc/crypttab *) ++ if verbose() then eprintf "mapped to crypttab device=%s\n%!" device; ++ (* device string is one of: ++ * + UUID=... without any shell quoting ++ * + An absolute path ++ *) ++ if String.starts_with "UUID=" device then ( ++ (* We found the UUID for the encrypted LUKS partition, now we use ++ * that to get the unencrypted /dev/dm-X via ++ * /dev/disk/by-id/dm-uuid-CRYPT-* automagic paths. The format is ++ * ++ * /dev/disk/by-id/dm-uuid-CRYPT-$TYPE-$LUKSUUID-$DMNAME ++ * ++ * The fields are ++ * + $TYPE: `LUKS1` or `LUKS2` ++ * + $LUKSUUID: The UUID we got from crypttab, but with `-` removed ++ * + $DMNAME: this would be `cr_root` for `/dev/mapper/cr_root`, but ++ * we just ignore that. ++ *) ++ let byid_dir = "/dev/disk/by-id" in ++ let uuid = String.sub device 5 (String.length device - 5) in ++ let short_uuid = String.replace uuid "-" "" in ++ let regstr = sprintf "^dm-uuid-CRYPT-LUKS.-%s-.*$" short_uuid in ++ let re_dmcrypt = PCRE.compile regstr in ++ let entries = Sys.readdir byid_dir |> Array.to_list in ++ try ++ let filename = List.find (fun f -> PCRE.matches re_dmcrypt f) entries in ++ let fullpath = Filename.concat byid_dir filename in ++ let resolved_path = Unix_utils.Realpath.realpath fullpath in ++ eprintf("Found crypttab mapping %s -> %s\n%!") fullpath resolved_path; ++ Mountable.of_device (resolved_path) ++ with ++ Failure _ | Not_found -> ++ eprintf("Failed to find matching regex %s/%s\n%!") byid_dir regstr; ++ Mountable.of_device spec ++ ) else ( ++ Mountable.of_device spec ++ ) ++ | None -> ++ (* Assume /dev/mapper device is LVM *) ++ ++ (* LVM2 does some strange munging on /dev/mapper paths for VGs and ++ * LVs which contain '-' character: ++ * ++ * > lvcreate LV--test VG--test 32 ++ * > debug ls /dev/mapper ++ * VG----test-LV----test ++ * ++ * This makes it impossible to reverse those paths directly, so ++ * we have implemented lvm_canonical_lv_name in the daemon. ++ *) ++ try ++ match Lvm_utils.lv_canonical spec with ++ | None -> default ++ | Some device -> Mountable.of_device device ++ with ++ (* Ignore devices that don't exist. (RHBZ#811872) *) ++ | Unix.Unix_error (Unix.ENOENT, _, _) -> default ++ + + (* type: (h|s|v|xv) + * disk: [a-z]+ +-- +2.47.1 + diff --git a/0008-daemon-sysroot-Avoid-double-when-creating-sysroot-pa.patch b/0008-daemon-sysroot-Avoid-double-when-creating-sysroot-pa.patch new file mode 100644 index 0000000..bfc41fd --- /dev/null +++ b/0008-daemon-sysroot-Avoid-double-when-creating-sysroot-pa.patch @@ -0,0 +1,42 @@ +From 1e0099671a2cd75e3407fc02cd16584fce3ba4ee Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 12 Aug 2025 13:04:45 +0100 +Subject: [PATCH] daemon: sysroot: Avoid double-/ when creating sysroot paths + in OCaml + +Previously calling 'sysroot_path "/dev"' for example would return the +string "/sysroot//dev". While this is not wrong, it confuses some +external programs (hello, setfiles), and it's not very "clean". Be a +bit more careful to avoid doubling the '/' character in the common case. +--- + daemon/sysroot.ml | 6 +++++- + daemon/sysroot.mli | 2 +- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/daemon/sysroot.ml b/daemon/sysroot.ml +index 286d125b9..57e727066 100644 +--- a/daemon/sysroot.ml ++++ b/daemon/sysroot.ml +@@ -20,4 +20,8 @@ open Std_utils + + external sysroot : unit -> string = "guestfs_int_daemon_sysroot" + +-let sysroot_path path = sysroot () // path ++let sysroot_path path = ++ let sysroot = sysroot () in ++ if path = "" then sysroot ++ else if path.[0] = '/' then sysroot ^ path ++ else sysroot // path +diff --git a/daemon/sysroot.mli b/daemon/sysroot.mli +index 7f8970cd8..1e6e75902 100644 +--- a/daemon/sysroot.mli ++++ b/daemon/sysroot.mli +@@ -22,4 +22,4 @@ val sysroot : unit -> string + in default. *) + + val sysroot_path : string -> string +-(** Equivalent to calling [sysroot () // path] *) ++(** Prepend [path] parameter with the sysroot. *) +-- +2.47.1 + diff --git a/0009-daemon-sysroot-Avoid-copying-the-path-every-time-we-.patch b/0009-daemon-sysroot-Avoid-copying-the-path-every-time-we-.patch new file mode 100644 index 0000000..f82df19 --- /dev/null +++ b/0009-daemon-sysroot-Avoid-copying-the-path-every-time-we-.patch @@ -0,0 +1,49 @@ +From c931ab3bc807cff785b1271c575855f0906e27b3 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 12 Aug 2025 13:09:16 +0100 +Subject: [PATCH] daemon: sysroot: Avoid copying the path every time we call + sysroot () + +This path never changes once the daemon has started up, so we don't +need to call into C code and copy the string every time. +--- + daemon/sysroot-c.c | 4 ++-- + daemon/sysroot.ml | 5 ++++- + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/daemon/sysroot-c.c b/daemon/sysroot-c.c +index ad31d36ee..e664232b0 100644 +--- a/daemon/sysroot-c.c ++++ b/daemon/sysroot-c.c +@@ -28,10 +28,10 @@ + + #include "daemon.h" + +-extern value guestfs_int_daemon_sysroot (value unitv); ++extern value guestfs_int_daemon_get_sysroot (value unitv); + + value +-guestfs_int_daemon_sysroot (value unitv) ++guestfs_int_daemon_get_sysroot (value unitv) + { + return caml_copy_string (sysroot); + } +diff --git a/daemon/sysroot.ml b/daemon/sysroot.ml +index 57e727066..35ae11f3f 100644 +--- a/daemon/sysroot.ml ++++ b/daemon/sysroot.ml +@@ -18,7 +18,10 @@ + + open Std_utils + +-external sysroot : unit -> string = "guestfs_int_daemon_sysroot" ++external get_sysroot : unit -> string = "guestfs_int_daemon_get_sysroot" ++ ++let sysroot = lazy (get_sysroot ()) ++let sysroot () = Lazy.force sysroot + + let sysroot_path path = + let sysroot = sysroot () in +-- +2.47.1 + diff --git a/0010-daemon-Reimplement-guestfs_selinux_relabel-in-OCaml.patch b/0010-daemon-Reimplement-guestfs_selinux_relabel-in-OCaml.patch new file mode 100644 index 0000000..d53b776 --- /dev/null +++ b/0010-daemon-Reimplement-guestfs_selinux_relabel-in-OCaml.patch @@ -0,0 +1,406 @@ +From ed40333a23ae8f20ac0360df444d10db369fa6d9 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 12 Aug 2025 12:22:42 +0100 +Subject: [PATCH] daemon: Reimplement guestfs_selinux_relabel in OCaml + +No change, just reimplement the existing C implementation in OCaml. +--- + .gitignore | 1 + + daemon/Makefile.am | 4 +- + daemon/selinux-relabel.c | 169 -------------------------------------- + daemon/selinux.c | 7 ++ + daemon/selinux.ml | 101 +++++++++++++++++++++++ + docs/C_SOURCE_FILES | 1 - + generator/actions_core.ml | 1 + + po/POTFILES | 1 - + 8 files changed, 113 insertions(+), 172 deletions(-) + delete mode 100644 daemon/selinux-relabel.c + create mode 100644 daemon/selinux.ml + +diff --git a/.gitignore b/.gitignore +index 81cd278cc..02160caff 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -108,6 +108,7 @@ Makefile.in + /daemon/parted.mli + /daemon/realpath.mli + /daemon/rpm.mli ++/daemon/selinux.mli + /daemon/sfdisk.mli + /daemon/stamp-guestfsd.pod + /daemon/statvfs.mli +diff --git a/daemon/Makefile.am b/daemon/Makefile.am +index 6d7492013..c644d9881 100644 +--- a/daemon/Makefile.am ++++ b/daemon/Makefile.am +@@ -59,6 +59,7 @@ generator_built = \ + parted.mli \ + realpath.mli \ + rpm.mli \ ++ selinux.mli \ + sfdisk.mli \ + statvfs.mli \ + structs.ml \ +@@ -173,7 +174,6 @@ guestfsd_SOURCES = \ + rsync.c \ + scrub.c \ + selinux.c \ +- selinux-relabel.c \ + sfdisk.c \ + sh.c \ + sleep.c \ +@@ -307,6 +307,7 @@ SOURCES_MLI = \ + parted.mli \ + realpath.mli \ + rpm.mli \ ++ selinux.mli \ + sfdisk.mli \ + statvfs.mli \ + structs.mli \ +@@ -345,6 +346,7 @@ SOURCES_ML = \ + listfs.ml \ + realpath.ml \ + statvfs.ml \ ++ selinux.ml \ + inspect_types.ml \ + inspect_utils.ml \ + inspect_fs_unix_fstab.ml \ +diff --git a/daemon/selinux-relabel.c b/daemon/selinux-relabel.c +deleted file mode 100644 +index cfc5a31d9..000000000 +--- a/daemon/selinux-relabel.c ++++ /dev/null +@@ -1,169 +0,0 @@ +-/* 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 +- +-#include +-#include +-#include +-#include +- +-#include "guestfs_protocol.h" +-#include "daemon.h" +-#include "actions.h" +-#include "optgroups.h" +- +-#include "ignore-value.h" +- +-#define MAX_ARGS 64 +- +-int +-optgroup_selinuxrelabel_available (void) +-{ +- return prog_exists ("setfiles"); +-} +- +-static int +-dir_exists (const char *dir) +-{ +- struct stat statbuf; +- +- if (stat (dir, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) +- return 1; +- else +- return 0; +-} +- +-static int +-setfiles_has_option (int *flag, char opt_char) +-{ +- CLEANUP_FREE char *err = NULL; +- +- if (*flag == -1) { +- char option[] = { '-', opt_char, '\0' }; /* "-X" */ +- char err_opt[32]; /* "invalid option -- 'X'" */ +- +- snprintf(err_opt, sizeof(err_opt), "invalid option -- '%c'", opt_char); +- ignore_value (command (NULL, &err, "setfiles", option, NULL)); +- *flag = err && strstr (err, /* "invalid option -- " */ err_opt) == NULL; +- } +- +- return *flag; +-} +- +-/* Takes optional arguments, consult optargs_bitmask. */ +-int +-do_selinux_relabel (const char *specfile, const char *path, +- int force) +-{ +- static int flag_m = -1; +- static int flag_C = -1; +- static int flag_T = -1; +- 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; +- int setfiles_status; +- +- 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_SELINUX_RELABEL_FORCE_BITMASK)) +- force = 0; +- +- /* If setfiles takes an excessively long time to run (but still +- * completes) then removing .../contexts/files/file_contexts.bin +- * appears to help. If you find any such cases, please add +- * observations to the bug report: +- * https://bugzilla.redhat.com/show_bug.cgi?id=1396297 +- */ +- ADD_ARG (argv, i, "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_sys); +- if (dir_exists (s_selinux)) { +- ADD_ARG (argv, i, "-e"); ADD_ARG (argv, i, s_selinux); +- } +- +- /* 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 (&flag_m, 'm')) +- ADD_ARG (argv, i, "-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 (&flag_C, 'C')) +- ADD_ARG (argv, i, "-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 (&flag_T, 'T')) { +- ADD_ARG (argv, i, "-T"); ADD_ARG (argv, i, "0"); +- } +- +- /* Relabelling in a chroot. */ +- if (STRNEQ (sysroot, "/")) { +- ADD_ARG (argv, i, "-r"); +- ADD_ARG (argv, i, sysroot); +- } +- +- if (verbose) +- ADD_ARG (argv, i, "-v"); +- else +- /* 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); +- +- setfiles_status = commandrv (NULL, &err, argv); +- if ((setfiles_status == 0) || (setfiles_status == 1 && flag_C)) +- return 0; +- +- reply_with_error ("%s", err); +- return -1; +-} +diff --git a/daemon/selinux.c b/daemon/selinux.c +index f4d839c19..4500d0096 100644 +--- a/daemon/selinux.c ++++ b/daemon/selinux.c +@@ -39,6 +39,13 @@ optgroup_selinux_available (void) + return 1; + } + ++/* For historical reasons, this is really "is setfiles available" */ ++int ++optgroup_selinuxrelabel_available (void) ++{ ++ return prog_exists ("setfiles"); ++} ++ + /* setcon is only valid under the following circumstances: + * - single threaded + * - enforcing=0 +diff --git a/daemon/selinux.ml b/daemon/selinux.ml +new file mode 100644 +index 000000000..d954fdead +--- /dev/null ++++ b/daemon/selinux.ml +@@ -0,0 +1,101 @@ ++(* SELinux functions. ++ * Copyright (C) 2009-2025 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 Printf ++ ++open Std_utils ++ ++open Sysroot ++open Utils ++ ++(* Test if setfiles has various options. ++ * ++ * The only way to do this is to run setfiles with the option alone, and ++ * test for the stderr message [invalid option -- 'X']. ++ *) ++let setfiles_has_option_m, ++ setfiles_has_option_C, ++ setfiles_has_option_T = ++ let setfiles_has_option flag = ++ let err_msg = sprintf "invalid option -- '%c'" flag in ++ let opt = sprintf "-%c" flag in ++ let _, _, err = commandr "setfiles" [opt] in ++ String.find err err_msg = -1 ++ in ++ let setfiles_has_option_m = lazy (setfiles_has_option 'm') ++ and setfiles_has_option_C = lazy (setfiles_has_option 'C') ++ and setfiles_has_option_T = lazy (setfiles_has_option 'T') in ++ (fun () -> Lazy.force 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 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"; ++ ++ (* 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" ]; ++ ++ (* 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"; ++ ++ (* Add parameters. *) ++ List.push_back_list args [ specfile; path ]; ++ ++ 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 +diff --git a/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES +index cdfb1d615..5270667bf 100644 +--- a/docs/C_SOURCE_FILES ++++ b/docs/C_SOURCE_FILES +@@ -132,7 +132,6 @@ daemon/rename.c + daemon/rpm-c.c + daemon/rsync.c + daemon/scrub.c +-daemon/selinux-relabel.c + daemon/selinux.c + daemon/sfdisk.c + daemon/sh.c +diff --git a/generator/actions_core.ml b/generator/actions_core.ml +index 108494ece..128cbe0e9 100644 +--- a/generator/actions_core.ml ++++ b/generator/actions_core.ml +@@ -9359,6 +9359,7 @@ 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"; +diff --git a/po/POTFILES b/po/POTFILES +index acf3a68d7..fbe0a7fe2 100644 +--- a/po/POTFILES ++++ b/po/POTFILES +@@ -110,7 +110,6 @@ daemon/rename.c + daemon/rpm-c.c + daemon/rsync.c + daemon/scrub.c +-daemon/selinux-relabel.c + daemon/selinux.c + daemon/sfdisk.c + daemon/sh.c +-- +2.47.1 + diff --git a/0011-generator-Implement-StringList-for-OCaml-functions.patch b/0011-generator-Implement-StringList-for-OCaml-functions.patch new file mode 100644 index 0000000..a38d98a --- /dev/null +++ b/0011-generator-Implement-StringList-for-OCaml-functions.patch @@ -0,0 +1,99 @@ +From fd4db60cffd9d0ece25a436932aca5411e13b94e Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 12 Aug 2025 14:05:44 +0100 +Subject: [PATCH] generator: Implement StringList for OCaml functions + +No existing OCaml functions have a StringList parameter, but we would +like to add one. + +The original plan seems to have been to map these to 'string array' +types, but 'string list' is more natural, albeit marginally less +efficient. The implementation here just has to convert the 'char **' +into the OCaml linked list of values. +--- + daemon/daemon-c.c | 24 ++++++++++++++++++++++++ + daemon/daemon-c.h | 1 + + generator/daemon.ml | 6 ++++-- + 3 files changed, 29 insertions(+), 2 deletions(-) + +diff --git a/daemon/daemon-c.c b/daemon/daemon-c.c +index 1754cf0d2..371c2a9e4 100644 +--- a/daemon/daemon-c.c ++++ b/daemon/daemon-c.c +@@ -114,6 +114,30 @@ guestfs_int_daemon_copy_mountable (const mountable_t *mountable) + CAMLreturn (r); + } + ++/* Implement StringList(...) parameter. */ ++value ++guestfs_int_daemon_copy_string_list (char * const *strs) ++{ ++ CAMLparam0 (); ++ CAMLlocal3 (v, tlv, rv); ++ size_t i; ++ ++ /* We need to build the list backwards so start at the end. */ ++ for (i = 0; strs[i] != NULL; ++i) ++ ; ++ ++ while (i > 0) { ++ --i; ++ v = caml_copy_string (strs[i]); ++ rv = caml_alloc (2, 0); ++ Store_field (rv, 0, v); ++ Store_field (rv, 1, tlv); ++ tlv = rv; ++ } ++ ++ CAMLreturn (rv); ++} ++ + /* Implement RStringList. */ + char ** + guestfs_int_daemon_return_string_list (value retv) +diff --git a/daemon/daemon-c.h b/daemon/daemon-c.h +index 9b7085bce..b06efc0cf 100644 +--- a/daemon/daemon-c.h ++++ b/daemon/daemon-c.h +@@ -29,6 +29,7 @@ + + extern void guestfs_int_daemon_exn_to_reply_with_error (const char *func, value exn); + extern value guestfs_int_daemon_copy_mountable (const mountable_t *mountable); ++extern value guestfs_int_daemon_copy_string_list (char * const *strs); + extern char **guestfs_int_daemon_return_string_list (value retv); + extern char *guestfs_int_daemon_return_string_mountable (value retv); + extern char **guestfs_int_daemon_return_string_mountable_list (value retv); +diff --git a/generator/daemon.ml b/generator/daemon.ml +index 6221531d2..2b74f3059 100644 +--- a/generator/daemon.ml ++++ b/generator/daemon.ml +@@ -558,7 +558,7 @@ and generate_ocaml_daemon_prototype name (ret, args, optargs) = + | OInt n -> pr "?%s:int -> " n + | OInt64 n -> pr "?%s:int64 -> " n + | OString n -> pr "?%s:string -> " n +- | OStringList n -> pr "?%s:string array -> " n ++ | OStringList n -> pr "?%s:string list -> " n + ) optargs; + if args <> [] then + List.iter ( +@@ -566,7 +566,7 @@ and generate_ocaml_daemon_prototype name (ret, args, optargs) = + | String (typ, _) -> pr "%s -> " (type_for_stringt typ) + | BufferIn _ -> pr "string -> " + | OptString _ -> pr "string option -> " +- | StringList (typ, _) -> pr "%s array -> " (type_for_stringt typ) ++ | StringList (typ, _) -> pr "%s list -> " (type_for_stringt typ) + | Bool _ -> pr "bool -> " + | Int _ -> pr "int -> " + | Int64 _ | Pointer _ -> pr "int64 -> " +@@ -820,6 +820,8 @@ let generate_daemon_caml_stubs () = + pr "guestfs_int_daemon_copy_mountable (%s)" n + | String _ -> assert false + | OptString _ -> assert false ++ | StringList ((PlainString|Filename|Pathname), n) -> ++ pr "guestfs_int_daemon_copy_string_list (%s)" n + | StringList _ -> assert false + | BufferIn _ -> assert false + | Pointer _ -> assert false +-- +2.47.1 + diff --git a/0012-generator-Allow-StringList-Pathname-parameters.patch b/0012-generator-Allow-StringList-Pathname-parameters.patch new file mode 100644 index 0000000..6343a38 --- /dev/null +++ b/0012-generator-Allow-StringList-Pathname-parameters.patch @@ -0,0 +1,83 @@ +From e4d9ee3fbc58c5993db0c75c647fdf904c520918 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 12 Aug 2025 14:04:42 +0100 +Subject: [PATCH] generator: Allow StringList(Pathname) parameters + +This was previously not implemented. It just requires us to call +ABS_PATH on each parameter. ABS_PATH checks the parameter is an +absolute path. +--- + generator/checks.ml | 1 - + generator/daemon.ml | 16 ++++++++++++---- + 2 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/generator/checks.ml b/generator/checks.ml +index d64d49d66..4207c0677 100644 +--- a/generator/checks.ml ++++ b/generator/checks.ml +@@ -166,7 +166,6 @@ let () = + | StringList (FileIn, _) + | StringList (FileOut, _) + | StringList (Mountable, _) +- | StringList (Pathname, _) + | StringList (Dev_or_Path, _) + | StringList (Mountable_or_Path, _) + | StringList (Key, _) +diff --git a/generator/daemon.ml b/generator/daemon.ml +index 2b74f3059..6197288df 100644 +--- a/generator/daemon.ml ++++ b/generator/daemon.ml +@@ -173,7 +173,7 @@ let generate_daemon_stubs actions () = + | String ((Mountable|Mountable_or_Path), n) -> + pr " CLEANUP_FREE_MOUNTABLE mountable_t %s\n" n; + pr " = { .device = NULL, .volume = NULL };\n" +- | StringList ((PlainString|Filename), n) -> ++ | StringList ((PlainString|Filename|Pathname), n) -> + pr " char **%s;\n" n + | StringList (Device, n) -> + pr " CLEANUP_FREE_STRING_LIST char **%s = NULL;\n" n +@@ -184,7 +184,7 @@ let generate_daemon_stubs actions () = + pr " const char *%s;\n" n; + pr " size_t %s_size;\n" n + | String ((FileIn|FileOut|Filename), _) +- | StringList ((Mountable|Pathname|FileIn|FileOut|Key|GUID ++ | StringList ((Mountable|FileIn|FileOut|Key|GUID + |Dev_or_Path|Mountable_or_Path), _) + | Pointer _ -> assert false + ) args_passed_to_daemon +@@ -260,7 +260,7 @@ let generate_daemon_stubs actions () = + n n is_filein; + | String ((PlainString|Key|GUID), n) -> pr_args n + | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n +- | StringList ((PlainString|Filename) as arg, n) -> ++ | StringList ((PlainString|Filename|Pathname) as arg, n) -> + (match arg with + | Filename -> + pr " {\n"; +@@ -275,6 +275,14 @@ let generate_daemon_stubs actions () = + pr " }\n"; + pr " }\n"; + pr " }\n" ++ | Pathname -> ++ pr " {\n"; ++ pr " size_t i;\n"; ++ pr " for (i = 0; i < args.%s.%s_len; ++i) {\n" n n; ++ pr " ABS_PATH (args.%s.%s_val[i], %b, return);\n" ++ n n is_filein; ++ pr " }\n"; ++ pr " }\n" + | _ -> () + ); + pr " /* Ugly, but safe and avoids copying the strings. */\n"; +@@ -307,7 +315,7 @@ let generate_daemon_stubs actions () = + pr " %s = args.%s.%s_val;\n" n n n; + pr " %s_size = args.%s.%s_len;\n" n n n + | String ((FileIn|FileOut|Filename), _) +- | StringList ((Mountable|Pathname|FileIn|FileOut|Key|GUID ++ | StringList ((Mountable|FileIn|FileOut|Key|GUID + |Dev_or_Path|Mountable_or_Path), _) + | Pointer _ -> assert false + ) args_passed_to_daemon; +-- +2.47.1 + diff --git a/0013-daemon-Deprecate-guestfs_selinux_relabel-replace-wit.patch b/0013-daemon-Deprecate-guestfs_selinux_relabel-replace-wit.patch new file mode 100644 index 0000000..a393125 --- /dev/null +++ b/0013-daemon-Deprecate-guestfs_selinux_relabel-replace-wit.patch @@ -0,0 +1,311 @@ +From 1c0b56158aa63359d1e53f7a31b483194f235a34 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 12 Aug 2025 13:27:32 +0100 +Subject: [PATCH] daemon: Deprecate guestfs_selinux_relabel, replace with + guestfs_setfiles + +The guestfs_selinux_relabel function was very hard to use. In +particular it didn't just do an SELinux relabel as you might expect. +Instead you have to write a whole bunch of code around it (example[1]) +to make it useful. + +Another problem is that it doesn't let you pass multiple paths to the +setfiles command, but the command itself does permit that (and, as it +turns out, will require it). There is no backwards compatible way to +extend the existing definition to allow a list parameter without +breaking API. + +So deprecate guestfs_selinux_relabel. Reimplement it as +guestfs_setfiles. The new function is basically the same as the old +one, but allows you to pass a list of paths. The old function calls +the new function with a single path parameter. + +[1] https://github.com/libguestfs/libguestfs-common/blob/master/mlcustomize/SELinux_relabel.ml +--- + daemon/selinux.ml | 117 ++++++++++++++------------- + generator/actions_core.ml | 49 +++++------ + generator/actions_core_deprecated.ml | 24 ++++++ + generator/proc_nr.ml | 1 + + gobject/Makefile.inc | 2 + + lib/MAX_PROC_NR | 2 +- + tests/relabel/test-relabel.pl | 2 +- + 7 files changed, 117 insertions(+), 80 deletions(-) + +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 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"; +- +- (* 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" ]; +- +- (* 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"; +- +- (* Add parameters. *) +- List.push_back_list args [ specfile; path ]; +- +- 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 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; ++ ++ (* 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"; ++ ++ (* 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 () ]; ++ ++ if verbose () then ++ List.push_back args "-v" ++ else ++ (* Suppress non-error output. *) ++ List.push_back args "-q"; ++ ++ (* 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 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; +-- +2.47.1 + diff --git a/0006-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch b/0014-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch similarity index 99% rename from 0006-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch rename to 0014-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch index a73d0d9..00bf729 100644 --- a/0006-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch +++ b/0014-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch @@ -1,4 +1,4 @@ -From e80928d0242730dd613ad9b30a72ef23760b4a6d Mon Sep 17 00:00:00 2001 +From ad17d4a59c67c43170f8b364981ee34e14e4e268 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Mon, 29 Jul 2013 14:47:56 +0100 Subject: [PATCH] RHEL: Disable unsupported remote drive protocols @@ -180,7 +180,7 @@ index e4e1021db..8419ce78a 100755 rm test-add-uri.out rm test-add-uri.img diff --git a/generator/actions_core.ml b/generator/actions_core.ml -index 0f39fd509..acf5ae5fa 100644 +index 60d3140ed..d374ffbf8 100644 --- a/generator/actions_core.ml +++ b/generator/actions_core.ml @@ -350,22 +350,6 @@ F is interpreted as a local file or device. @@ -394,7 +394,7 @@ index c068b8ecb..6e4453ce5 100644 error (g, _("unknown protocol ā€˜%s’"), protocol); drv = NULL; /*FALLTHROUGH*/ diff --git a/lib/guestfs.pod b/lib/guestfs.pod -index f69d5a070..e54d98d35 100644 +index 505978aa1..07737c839 100644 --- a/lib/guestfs.pod +++ b/lib/guestfs.pod @@ -723,51 +723,6 @@ a qcow2 backing file specification, libvirt does not construct an diff --git a/0007-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch b/0015-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch similarity index 97% rename from 0007-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch rename to 0015-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch index c8da22b..24124c7 100644 --- a/0007-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch +++ b/0015-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch @@ -1,4 +1,4 @@ -From 4a0e2396b9ed6426733dc9d2d9e033c8a769d0d1 Mon Sep 17 00:00:00 2001 +From 3a905a409f19496664ba0ca82d7ed4950fd0d07b Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 7 Jul 2015 09:28:03 -0400 Subject: [PATCH] RHEL: Reject use of libguestfs-winsupport features except for diff --git a/0008-RHEL-appliance-init-Run-depmod-a-to-rebuild-kernel-m.patch b/0016-RHEL-appliance-init-Run-depmod-a-to-rebuild-kernel-m.patch similarity index 90% rename from 0008-RHEL-appliance-init-Run-depmod-a-to-rebuild-kernel-m.patch rename to 0016-RHEL-appliance-init-Run-depmod-a-to-rebuild-kernel-m.patch index 66fdf39..d41c4da 100644 --- a/0008-RHEL-appliance-init-Run-depmod-a-to-rebuild-kernel-m.patch +++ b/0016-RHEL-appliance-init-Run-depmod-a-to-rebuild-kernel-m.patch @@ -1,4 +1,4 @@ -From 4490b82bc44ef2fe8b5619dfaf5debc93d8e32d4 Mon Sep 17 00:00:00 2001 +From 13ca6121971b8fdca211ee5b0acef30bde2248ff Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 13 May 2025 17:28:25 +0100 Subject: [PATCH] RHEL: appliance/init: Run depmod -a to rebuild kernel module diff --git a/libguestfs.spec b/libguestfs.spec index cd39f3c..98562ab 100644 --- a/libguestfs.spec +++ b/libguestfs.spec @@ -42,7 +42,7 @@ Summary: Access and modify virtual machine disk images Name: libguestfs Epoch: 1 Version: 1.56.1 -Release: 1%{?dist} +Release: 2%{?dist} License: LGPL-2.1-or-later # Build only for architectures that have a kernel @@ -85,9 +85,17 @@ Patch0002: 0002-lib-libvirt-Debug-error-from-virDomainDestroyFlags.patch Patch0003: 0003-lib-libvirt-Sleep-before-retrying-virDomainDestroyFl.patch Patch0004: 0004-daemon-Add-contents-of-etc-fstab-to-verbose-log.patch Patch0005: 0005-appliance-init-Add-lsblk-and-blkid-output-to-verbose.patch -Patch0006: 0006-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch -Patch0007: 0007-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch -Patch0008: 0008-RHEL-appliance-init-Run-depmod-a-to-rebuild-kernel-m.patch +Patch0006: 0006-docs-Fix-dead-ntfs-3g-doc-links.patch +Patch0007: 0007-daemon-inspect-check-etc-crypttab-for-dev-mapper.patch +Patch0008: 0008-daemon-sysroot-Avoid-double-when-creating-sysroot-pa.patch +Patch0009: 0009-daemon-sysroot-Avoid-copying-the-path-every-time-we-.patch +Patch0010: 0010-daemon-Reimplement-guestfs_selinux_relabel-in-OCaml.patch +Patch0011: 0011-generator-Implement-StringList-for-OCaml-functions.patch +Patch0012: 0012-generator-Allow-StringList-Pathname-parameters.patch +Patch0013: 0013-daemon-Deprecate-guestfs_selinux_relabel-replace-wit.patch +Patch0014: 0014-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch +Patch0015: 0015-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch +Patch0016: 0016-RHEL-appliance-init-Run-depmod-a-to-rebuild-kernel-m.patch BuildRequires: autoconf, automake, libtool, gettext-devel @@ -1074,7 +1082,7 @@ rm ocaml/html/.gitignore %changelog -* Wed Jul 30 2025 Richard W.M. Jones - 1:1.56.1-1 +* Wed Aug 13 2025 Richard W.M. Jones - 1:1.56.1-2 - Rebase to libguestfs 1.56.1 resolves: RHEL-81733 - Include host kernel information in libguestfs debugging output @@ -1096,6 +1104,10 @@ rm ocaml/html/.gitignore resolves: RHEL-93109 - Add /etc/fstab, lsblk and blkid to verbose output resolves: RHEL-106490 +- Fix conversion of SLES15 with encrypted btrfs filesystem + resolves: RHEL-93584 +- Add guestfs_setfiles API + resolves: RHEL-108832 * Tue Nov 26 2024 Richard W.M. Jones - 1:1.54.0-5 - Rebase to libguestfs 1.54.0