https://bugzilla.redhat.com/2082806 is a private kernel bug (sigh) for
RHEL 8, where some missing backports caused 5-level page tables to
fail when qemu emulated them. This was fixed back in 2023, so let's
remove this workaround now.
On RHEL 10.2 aarch64 (only) we see:
$ echo '{ "execute": "qmp_capabilities" }' '{ "execute": "query-kvm" }' '{ "execute": "quit" }' | QEMU_AUDIO_DRV=none "/usr/libexec/qemu-kvm" -display none -machine "virt,accel=kvm:hvf:tcg" -qmp stdio
qemu-kvm: invalid accelerator hvf
qemu-kvm: falling back to KVM
{"QMP": {"version": {"qemu": {"micro": 0, "minor": 1, "major": 9}, "package": "qemu-kvm-9.1.0-15.el10_0.4"}, "capabilities": ["oob"]}}
qemu-kvm: warning: CPU model cortex-a57-arm-cpu is deprecated -- use 'host' / 'max'
qemu-kvm: kvm_init_vcpu: kvm_arch_init_vcpu failed (0): Invalid argument
Unfortunately we cannot use guestfs_int_get_cpu_model (as that
requires us to already know if KVM is supported), so we just have to
guess that -cpu max will work, at least enough for QMP to work.
Fixes: https://issues.redhat.com/browse/RHEL-121076
Reported-by: Xiang Hua Chen
virt-customize and friends have the following options:
--sm-register
--sm-unregister
--sm-attach
--sm-remove
--sm-credentials
These run `subscription-manager` commands inside the VM, which
is often necessary to get working package install for RHEL VMs.
These were added in 2015ish. Conceptually I understand why we
might want native support in the tools: virt-customize and
virt-builder have package management knowledge, and
for some distros subscription-manager is necessary.
But this support doesn't add much convenience over calling the commands
directly with `--run-command`. And on RHEL10, subscription-manager was
reworked and complete drops the backing commands for `--sm-attach` and
`--sm-remove`.
We _could_ make this code smarter, try to detect that situation,
and not error when subscription-manager is new enough. But if
subscription-manager itself doesn't care about maintaining that kind
of compat, I'm not sure why we should care either.
Instead we decided to just rip it all out and document the
alternatives.
common module is updated to sync related changes:
Cole Robinson (1):
mlcustomize: deprecate and remove --sm-* options
Richard W.M. Jones (3):
mlstdutils: Export List.find_opt
daemon, generator: Use power of 2 for initial size of Hashtbl.create
mlcustomize/inject_virtio_win.ml: Use viostor.inf instead of guestor
https://issues.redhat.com/browse/RHEL-113397https://issues.redhat.com/browse/RHEL-113398
Signed-off-by: Cole Robinson <crobinso@redhat.com>
test-parallel-mount-local reliably fails when my machines are
under load (like running the test suite in parallel). The
issue is /usr/libexec/gvfs-udisks2-volume-monitor fiddling with
the fuse mounts, preventing them from being unmounted.
./fuse/guestunmount defaults to 5 unmount retries with increasing
time backoff, but apparently that isn't enough. Bumping it to
use 10 retries makes things more reliable for me.
Signed-off-by: Cole Robinson <crobinso@redhat.com>
On macOS this fails with:
guestunmount.c:170:5: error: call to undeclared function 'sigaction'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
170 | sigaction (SIGINT, &sa, NULL);
| ^
1 error generated.
Reported-by: Mohamed Akram
Related: https://github.com/libguestfs/libguestfs/pull/188
macOS macfuse has an extra options parameter for the setxattr and
getxattr FUSE callbacks. The possible options are documented below.
However the underlying libguestfs APIs don't allow us to act on these
flags, so we ignore them for now.
(from https://manp.gs/mac/2/setxattr)
XATTR_NOFOLLOW
do not follow symbolic links. setxattr() normally sets attributes
on the target of path if it is a symbolic link. With this option,
setxattr() will act on the link itself.
XATTR_NOFOLLOW_ANY
do not follow any symbolic links encountered during pathname
resolution. An error is returned if a symlink is encountered
before the last component of path.
XATTR_CREATE
fail if the named attribute already exists.
XATTR_REPLACE
fail if the named attribute does not exist. Failure to specify
XATTR_REPLACE or XATTR_CREATE allows creation and replacement.
Reported-by: Mohamed Akram
Fixes: https://github.com/libguestfs/libguestfs/issues/180
Related: https://github.com/macfuse/macfuse/issues/1065
Previously we tested if KVM was available, and cached that for the
qemu binary. I think this was actually wrong. For example, if the
machine restarts, then the cache is still around, but KVM might be
enabled or disabled because of a new host kernel.
In any case, let's radically simplify this.
Test for KVM on each run. Consequently we can remove all the qemu
test caching stuff as it is no longer used anywhere.
I also tightened up the code that runs the QMP query-kvm command, so
now any unexpected output will cause a runtime failure. This command
ought to work, and if it breaks we ought to know about it and fix it.
Previously we ran 'qemu -device ?' to list devices, using the output
to test if qemu supported particular devices. This was extensively
used in the past, but after recent commits there are no further users
of this code, so we can remove it all completely.
It's always a good idea to provide proper entropy to the libguestfs
appliance (eg. for any cryptographic operations). We already assume
virtio, so we can assume virtio-rng is present.
We no longer use the libvirt version anywhere, except when reporting
the version. Remove this from the handle.
Simplify the remaining code. In particular:
* don't bother parsing the libvirt version, just print what
virGetVersion gives us
* guestfs_int_version_from_libvirt is dead code, so it can be removed
Libvirt 9.0.0 was released in January 2023, and it seems safe to
assume that if you're enabling the non-default backend, you can at
least use a new version of libvirt.
If you're using new libvirt, might as well also assume passt is
available.
Previously we parsed qemu -help output to get the version of qemu and
to test for other features. After prior commits, this is no longer
done, so we can remove the qemu -help invocation and associated code
completely.
This function is now only used in one place, to print the version of
qemu in direct mode, when debugging is enabled.
Remove this function and replace with a direct command invocation
('qemu --version'). We only need to run this command when debugging
is enabled, and we copy all of the output to the debug channel.
I have made the assumption here that qemu -version does not try to
create a display device. (The previous invocation of qemu -help
actually ran 'qemu -display none -help' indicating that this was not
always the case.)
This is actually an improvement on before, since now we get to see the
full output of 'qemu --version'. The new output looks like:
libguestfs: begin testing qemu features
libguestfs: command: run: /usr/bin/qemu-kvm
libguestfs: command: run: \ -version
libguestfs: qemu: QEMU emulator version 10.1.0 (qemu-10.1.0-8.fc44)
libguestfs: qemu: Copyright (c) 2003-2025 Fabrice Bellard and the QEMU Project developers
We already effectively assume that qemu is much newer than the 1.3.0
baseline previously documented. As one example, commit 47857751a7
("lib: direct: Remove test for qemu mandatory locking") assumes that
qemu >= 2.10. Because passt support is desirable in general, let's
assume that qemu is at least version 7.2.0, and document it.
qemu 7.2.0 was released in December 2022, nearly 3 years ago, and RHEL
9 is currently on qemu 9.1.0.
This keeps the SLIRP fallback path in case passt isn't installed, but
we should remove that fallback in future too.
We can safely assume that qemu supports -nodefaults and
-no-user-config, since these have been supported since forever.
-no-hpet was deprecated in qemu 8.0 and the option removed in early
2024, replaced with -machine hpet=off. HPET defaults to 'on' in
upstream qemu, and to 'off' in downstream RHEL rebuilds.
Since (for libguestfs) we can assume an up to date Linux kernel is
running inside the guest, and that the kernel will do the right thing
with regards to timers, we don't need to mess with qemu defaults. In
practice, Linux chooses kvm-clock.
Thanks: Thomas Huth, Daniel Berrange
We used to read the QMP schema so we could see if the binary supported
qemu mandatory locking. However after commit 47857751a7 ("lib:
direct: Remove test for qemu mandatory locking") this is dead code, so
remove it.
Updates: commit 47857751a7
This was a test for a 13 year old problem to do with problems
launching libguestfs appliances in parallel. That problem does not
affect current code.
Testing build/launch of libguestfs appliances is a valuable thing to
test. However we start libguestfs in parallel in both the current
test suite and in higher level tools, and this test was dubious (and
breaks with recent changes). Therefore remove the test.
Before 2011 it was recommended to use a prime number for the initial
size. In 2011 the OCaml hash table was reimplemented using a hash
function based on Murmur 3. Hashtbl.create now adjusts the initial
size to the next power of 2 (minimum 16). So replace obsolete
'Hashtbl.create 13' with 'Hashtbl.create 16'.
In filesystems that have many millions of files, the default behaviour
of setfiles is to build a huge hash table containing every filename.
This uses up lots of memory which prevents relabelling from happening
in the reduced memory environment of the libguestfs appliance.
I added the setfiles -A option to change this default behaviour. If
setfiles has the option then use it.
Fixes: https://issues.redhat.com/browse/RHEL-114292
Related: https://issues.redhat.com/browse/RHEL-111165
Related: https://issues.redhat.com/browse/RHEL-111505
It turns out that ubuntu-latest is the same as 24.04, so we're just
testing on the same version twice. Remove the duplication.
Thanks: Stephen Gallagher
Fixes: commit e218dd73cc
Add an API to do the equivalent of `chmod [-r] MODE PATH` for
NTFS filesystems.
Files created on a linux ntfs-3g mount can not change permissions
directly. New files and directories are created with rough windows
equivalent of `chmod 777`. These wide open permissions can generate
security warnings on windows after virt-v2v installs bits into
`Program Files\Guestfs`.
Behind the scenes we use `ntfssecaudit(8)` from `ntfsprogs`
which is already part of the appliance. We only expose the chmod-style
feature; the rest of `ntfssecaudit` is concerned reporting and
managing fine grained windows security info which is way more than
we need.
Also note, `ntfssecaudit` needs to run on an unmounted partition
so using this is more complicated than a traditional `chmod` call.
Related: https://issues.redhat.com/browse/RHEL-104352
Signed-off-by: Cole Robinson <crobinso@redhat.com>
This builds libguestfs and runs the in-tree tests, ie. the basic
'./configure && make && make check'.
We're using the "free for public repositories" plan. We run the tests
directly on an Ubuntu VM, versions 24.04 & latest. Also on Fedora 42,
43 in a container (running on the Ubuntu VM).
The tests are run on pushes to the master branch, and on pull
requests to the master branch.
GObject is not built, since the tests fail and anyway there are some
deep problems with the GObject bindings and they probably will be
removed.
Thanks: Stephen Gallagher, Cole Robinson
This change was done almost entirely automatically using the script
below. This uses the OCaml lexer to read the source files and extract
the strings and locations. Strings which are "candidates" (in this
case, longer than 3 lines) are replaced in the output with quoted
string literals.
Since the OCaml lexer is used, it already substitutes all escape
sequences correctly. I diffed the output of the generator and it is
identical after this change, except for UUIDs, which change because of
how Utils.stable_uuid is implemented.
Thanks: Nicolas Ojeda Bar
$ ocamlfind opt -package unix,compiler-libs.common find_strings.ml \
-o find_strings.opt -linkpkg
$ for f in $( git ls-files -- \*.ml ) ; do ./find_strings.opt $f ; done
open Printf
let read_whole_file path =
let buf = Buffer.create 16384 in
let chan = open_in path in
let maxlen = 16384 in
let b = Bytes.create maxlen in
let rec loop () =
let r = input chan b 0 maxlen in
if r > 0 then (
Buffer.add_substring buf (Bytes.to_string b) 0 r;
loop ()
)
in
loop ();
close_in chan;
Buffer.contents buf
let count_chars c str =
let count = ref 0 in
for i = 0 to String.length str - 1 do
if c = String.unsafe_get str i then incr count
done;
!count
let subs = ref []
let consider_string str loc =
let nr_lines = count_chars '\n' str in
if nr_lines > 3 then
subs := (str, loc) :: !subs
let () =
Lexer.init ();
let filename = Sys.argv.(1) in
let content = read_whole_file filename in
let lexbuf = Lexing.from_string content in
let rec loop () =
let token = Lexer.token lexbuf in
(match token with
| Parser.EOF -> ();
| STRING (s, loc, sopt) ->
consider_string s loc; (* sopt? *)
loop ();
| token ->
loop ();
)
in
loop ();
(* The list of subs is already reversed, which is convenient
* because we must the file substitutions in reverse order.
*)
let subs = !subs in
let new_content = ref content in
List.iter (
fun (str, loc) ->
let { Location.loc_start = { pos_cnum = p1 };
loc_end = { pos_cnum = p2 } } = loc in
let len = String.length !new_content in
let before = String.sub !new_content 0 (p1-1) in
let after = String.sub !new_content (p2+1) (len - p2 - 1) in
new_content := before ^ "{|" ^ str ^ "|}" ^ after
) subs;
let new_content = !new_content in
if content <> new_content then (
(* Update the file in place. *)
let new_filename = filename ^ ".new"
and backup_filename = filename ^ ".bak" in
let chan = open_out new_filename in
fprintf chan "%s" new_content;
close_out chan;
Unix.rename filename backup_filename;
Unix.rename new_filename filename
)
Pulls in the commits listed below. This has no effect as all changes
are confined to the common/mlcustomize subdirectory which we do not
use or ship.
Richard W.M. Jones (4):
mlcustomize/SELinux_relabel.ml: Add comment
mlcustomize/SELinux_relabel.ml: Use new guestfs_setfiles API
mlcustomize/SELinux_relabel.ml: Relabel every mountpoint
mlcustomize/firstboot.ml: Use quoted string literals for firstboot
Vadim Rozenfeld (1):
Modify the firstboot script to check the scripts execution return status
If HKLM\System\MountedDevices references a blank disk, then when we
try to search for the actual backing device we will get an error from
parted:
parted: /dev/sdb: parted exited with status 1: Error: /dev/sdb: unrecognised disk label: Invalid argument
Just ignore these errors instead of failing inspection.
Fixes: https://issues.redhat.com/browse/RHEL-108803
Reported-by: Ameen Barakat
Thanks: Ming Xie
The function 'map_registry_disk_blob_gpt' immediately below this one
has a debugging statement. Add the equivalent to the function
'map_registry_disk_blob_mbr'.
The output looks like:
map_registry_disk_blob_mbr: searching for MBR disk ID 31 32 33 34
map_registry_disk_blob_mbr: searching for MBR partition offset 00 00 00 10 00 00 00 00
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
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.