Fix conversion of SLES15 with encrypted btrfs filesystem

resolves: RHEL-93584
Add guestfs_setfiles API
resolves: RHEL-108832
This commit is contained in:
Richard W.M. Jones 2025-08-13 18:09:20 +01:00
parent dfca9e5c9b
commit 583fc558f3
12 changed files with 1240 additions and 10 deletions

View File

@ -0,0 +1,50 @@
From 701667b6f581a824059c4da50eb4df176decbb82 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
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<C:\\windows> may appear as F</WINDOWS> or F</windows>
they were created. In Windows itself this would not be
a problem.
-Bug or feature? You decide:
-L<https://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
+Bug or feature? You decide. See the relevant entry in the ntfs-3g FAQ:
+L<https://github.com/tuxera/ntfs-3g/wiki/NTFS-3G-FAQ>
C<guestfs_case_sensitive_path> 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<http://www.tuxera.com/community/ntfs-3g-advanced/junction-points-and-symbolic-links/>
+L<https://github.com/tuxera/ntfs-3g/wiki/Junctions-Points,-Symbolic-Links-and-Reparse-Points>
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</guestfs_getxattr>). See:
-L<http://www.tuxera.com/community/ntfs-3g-advanced/extended-attributes/>
+L<https://github.com/tuxera/ntfs-3g/wiki/Using-Extended-Attributes>
=head3 WINDOWS HIBERNATION AND WINDOWS 8 FAST STARTUP
--
2.47.1

View File

@ -0,0 +1,178 @@
From 06db19c56c0a4e81596b24a7ab74ed545b422e4c Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
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 <crobinso@redhat.com>
---
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:
- *
- * ><fs> lvcreate LV--test VG--test 32
- * ><fs> 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:
+ *
+ * ><fs> lvcreate LV--test VG--test 32
+ * ><fs> 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

View File

@ -0,0 +1,42 @@
From 1e0099671a2cd75e3407fc02cd16584fce3ba4ee Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
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

View File

@ -0,0 +1,49 @@
From c931ab3bc807cff785b1271c575855f0906e27b3 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
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

View File

@ -0,0 +1,406 @@
From ed40333a23ae8f20ac0360df444d10db369fa6d9 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
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 <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#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<errno> is set to C<ENODEV>." };
{ 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

View File

@ -0,0 +1,99 @@
From fd4db60cffd9d0ece25a436932aca5411e13b94e Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
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

View File

@ -0,0 +1,83 @@
From e4d9ee3fbc58c5993db0c75c647fdf904c520918 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
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

View File

@ -0,0 +1,311 @@
From 1c0b56158aa63359d1e53f7a31b483194f235a34 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
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<device> is spanned over.
If not all the devices for the filesystems are present, then this function
fails and the C<errno> is set to C<ENODEV>." };
- { 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<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." };
-
{ 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<guestfs_list_dm_devices> 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<setfiles> command which is a low
+level tool used to 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<paths> parameter is the list of top level directories
+where relabelling starts. C<setfiles> 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<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." };
+
]
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<device> 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<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." };
+
]
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

View File

@ -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" <rjones@redhat.com>
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<filename> 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

View File

@ -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" <rjones@redhat.com>
Date: Tue, 7 Jul 2015 09:28:03 -0400
Subject: [PATCH] RHEL: Reject use of libguestfs-winsupport features except for

View File

@ -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" <rjones@redhat.com>
Date: Tue, 13 May 2025 17:28:25 +0100
Subject: [PATCH] RHEL: appliance/init: Run depmod -a to rebuild kernel module

View File

@ -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 <rjones@redhat.com> - 1:1.56.1-1
* Wed Aug 13 2025 Richard W.M. Jones <rjones@redhat.com> - 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 <rjones@redhat.com> - 1:1.54.0-5
- Rebase to libguestfs 1.54.0