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
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>
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
This saves us going into a loop if virDomainDestroyFlags keeps
returning -EBUSY quickly, which apparenrly can happen in containers.
The equivalent 'direct' backend code sleeps for 2 seconds in this case.
Many years ago we used to pass acpi=off on the Linux kernel command
line. In commit db1f811b2 we stopped doing that (around 2016).
However unless you also use:
<features>
<acpi/>
</features>
then it turns out that libvirt disables ACPI generation at the qemu
level. None of this mattered until SeaBIOS 1.17 changed its
behaviour, causing ACPI to be required for virtio devices to work.
Updates: commit db1f811b29
Related: https://bugzilla.redhat.com/show_bug.cgi?id=2372329
Thanks: Gerd Hoffmann
libosinfo changes the naming scheme it uses for SUSE starting with
major version 15. Previously it used names like "sles12" (or
"sles12sp1"), "sled12" for Server and Desktop variants. In 15+ it
uses "sle15" as there are no variants any longer (instead the
installer asks you what variant you want to install). We're only
interested in the Server variant. Change the name that we return to
"sle15" or "sle15sp1".
See: b0fa386699
Fixes: https://issues.redhat.com/browse/RHEL-95791
Thanks: Ming Xie, Victor Toso
Related: https://issues.redhat.com/browse/RHEL-95540
They will be removed in libguestfs 1.58 (the next but one version).
Currently they don't actually compile. The larger problem is that
they don't handle 64 bit quantities properly (using floats instead),
meaning that any disk size or offset above a certain size will be
improperly passed through the API, usually rounded to the nearest
53 bits.
create.c: In function 'disk_create_qcow2':
create.c:372:5: error: format not a string literal and no format arguments [-Werror=format-security]
372 | debug (g, cmd_stdout);
| ^~~~~
Fixes: commit 606aa1d182
https://issues.redhat.com/browse/RHEL-92239
After this, output looks like
$ ./run guestfish --ro --format=qcow2 -a test.img
libguestfs: error: qemu-img: qemu-img: /home/crobinso/src/libguestfs/tmp/libguestfsFlxnb0/overlay1.qcow2: Image is not in qcow2 format Could not open backing image. : qemu-img exited with error status 1.
To see full error messages you may need to enable debugging.
...
Signed-off-by: Cole Robinson <crobinso@redhat.com>
The old btrfs-fsck API used "btrfs check" which appears to be broken
or deprecated. The real tool you should use is "btrfs scrub". We
have already implemented that API, but it is very awkward to use from
libguestfs. In particular there's no existing way to run the scrub
and wait for it to finish.
Fix this by deprecating btrfs-fsck. Implement a new API
btrfs-scrub-full which runs btrfs scrub in the foreground, waits for
it to finish, and handles errors. It's much more like fsck tools in
other filesystems.
Thanks: Eric Sandeen
Fixes: https://issues.redhat.com/browse/RHEL-91936
We didn't correctly check for an error from the ioctl. Thus when
using a raw block device you would often see a bogus warning in
debugging output.
Related: https://issues.redhat.com/browse/MTV-2441
Useful for debugging problems caused by the host kernel. In
particular we were looking at a problem with passt creating a user
namespace but didn't know what exact kernel was being used.
These APIs allow you to capture output from guest commands that
generate more output than the protocol limit allows.
Thanks: Nijin Ashok
Fixes: https://issues.redhat.com/browse/RHEL-80159
After previous changes, this library is no longer used. We have
switched to json-c, for better compatibility with libvirt.
(cherry picked from
guestfs-tools commit e6dcf7e3a7e9170978e57ce6df1b34f92fac5ae3)
We tested for QEMU >= 2.10 support for mandatory locking. I believe
this is for all practical purposes always enabled now (and qemu 2.10
is ancient history) so simply assume it's true always.
All recent compilers support this (except MS compilers which we don't
care about). Assume it is supported. We test it in ./configure and
hard fail if it doesn't work.
We still define HAVE_ATTRIBUTE_CLEANUP but you can now assume it is
always defined and don't have to check it.
The guest was found to have these inspection fields:
type: windows
distro: windows
product_name: Windows Server 2025 Standard
product_variant: Server
version: 10.0
arch: x86_64
hostname: WIN-84V4KKQ30SM
build ID: 26080
windows_systemroot: /Windows
windows_software_hive: /Windows/System32/config/SOFTWARE
windows_system_hive: /Windows/System32/config/SYSTEM
windows_current_control_set: ControlSet001
Reported-by: Ming Xie
Fixes: https://issues.redhat.com/browse/RHEL-62935
This was only theoretically supported, via curl. It's unlikely that
it really worked as it was never tested.
If needed it's better to use nbdkit-curl-plugin instead (this applies
to http and ftp as well).
After many, many years, although libvirt does still often fail to
work, it's generally more secure to stick with libvirt than to try
running qemu directly. The main issue here is that people have
cargo-culted LIBGUESTFS_BACKEND=direct everywhere (even when it's not
necessary).
On QEMU 7.2.0+, if "passt" is available, ask QEMU for passt ("stream")
rather than SLIRP ("user") networking.
For this, we need to run passt ourselves. Given that passt daemonizes by
default, start it with our traditional function guestfs_int_cmd_run(). Ask
passt to save its PID file, because in case something goes wrong before
we're completely sure the appliance (i.e. QEMU) is up and running, we'll
need to kill passt, the *grandchild*, ourselves.
Pass "--one-off" to passt (same as libvirt). This way, once we have proof
that QEMU has connected to passt (because the appliance shows signs of
life), we need not clean up passt ourselves -- once QEMU exits, passt will
see an EOF on the unix domain socket, and exit as well.
Passt is way more flexible than SLIRP, and passt normally intends to
imitate the host environment in the guest as much as possible. This means
that, when switching from SLIRP to passt, the guest would see changes to
the following:
- guest IP address,
- guest subnet mask,
- host (= gateway) IP address,
- host (= gateway) MAC address.
Extract the SLIRP defaults into the new macros NETWORK_GW_IP and
NETWORK_GW_MAC, and pass them explicitly to passt. In particular,
"tests/rsync/test-rsync.sh" fails without setting the host address
(NETWORK_GW_IP) properly.
(These artifacts can be verified in the appliance with "virt-rescue
--network", by running "ip addr", "ip route", and "ip neighbor" at the
virt-rescue prompt. There are four scenarios: two libguest backends, times
passt being installed or not installed.)
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2184967
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20230714132213.96616-8-lersek@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Introduce a small function for creating pathnames for PID files.
guestfs_int_make_pid_path() is something of an amalgamation of
guestfs_int_make_temp_path() [1] and guestfs_int_create_socketname() [2]:
- it creates a pathname under sockdir, like [2],
- it uses the handle's unique counter, like [1],
- it takes a name like both [1] and [2], but the name is not size-limited
like in [2], plus we hardcode the suffix from [1] as ".pid".
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2184967
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20230714132213.96616-7-lersek@redhat.com>
Consider the following inverted call tree (effectively a dependency tree
-- callees are at the top and near the left margin):
lazy_make_tmpdir() [lib/tmpdirs.c]
guestfs_int_lazy_make_tmpdir() [lib/tmpdirs.c]
guestfs_int_make_temp_path() [lib/tmpdirs.c]
guestfs_int_lazy_make_sockdir() [lib/tmpdirs.c]
guestfs_int_create_socketname() [lib/launch.c]
lazy_make_tmpdir() is our common workhorse / helper function that
centralizes the mkdtemp() function call.
guestfs_int_lazy_make_tmpdir() and guestfs_int_lazy_make_sockdir() are the
next level functions, both calling lazy_make_tmpdir(), just feeding it
different dirname generator functions, and different "is_runtime_dir"
qualifications. These functions create temp dirs for various, more
specific, purposes (see the manual and "lib/guestfs-internal.h" for more
details).
On a yet higher level are guestfs_int_make_temp_path() and
guestfs_int_create_socketname() -- they serve for creating *entries* in
those specific temp directories.
The discrepancy here is that, although all the other functions live in
"lib/tmpdirs.c", guestfs_int_create_socketname() is defined in
"lib/launch.c". That makes for a confusing code reading; move the function
to "lib/tmpdirs.c", just below its sibling function
guestfs_int_make_temp_path().
While at it, correct the leading comment on
guestfs_int_create_socketname() -- the socket pathname is created in the
socket directory, not in the temporary directory.
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2184967
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20230714132213.96616-6-lersek@redhat.com>
We generate the <interface type="user"> element on libvirt 3.8.0+ already.
For selecting passt rather than SLIRP, we only need to insert the child
element <backend type='passt'>. Make that child element conditional on
libvirt 9.0.0+, plus "passt --help" being executable.
For the latter, place the new helper function guestfs_int_passt_runnable()
in "lib/launch.c" -- we're going to use the same function for the direct
backend as well.
This change exposes a number of (perceived) shortcomings in libvirt; I've
filed <https://bugzilla.redhat.com/show_bug.cgi?id=2222766> about those.
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2184967
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20230714132213.96616-3-lersek@redhat.com>