lib: direct: Remove assumptions that g->hv != NULL

In a following commit, g->hv may now be NULL if the user does not
explicitly either call guestfs_set_hv or set LIBGUESTFS_HV.

There were multiple places in the code that assumed g->hv was not
NULL, so they were all revised so that now g->hv is only not NULL if
set by the user and (in the normal case) is NULL meaning "use the
default hypervisor".

For the direct backend we call get_default_hv_direct early on and set
data->qemu in the handle.  We need to modify the KVM test so that the
current qemu binary is passed along.

We also have to change execve to execvpe since the path to qemu is not
absolute.
This commit is contained in:
Richard W.M. Jones
2026-03-17 14:52:43 +00:00
committed by rwmjones
parent 0818f31960
commit 503e9fde5a
3 changed files with 17 additions and 12 deletions

View File

@@ -796,7 +796,7 @@ void guestfs_int_init_libvirt_backend (void) __attribute__((constructor));
#endif
/* qemu.c */
extern int guestfs_int_platform_has_kvm (guestfs_h *g);
extern int guestfs_int_platform_has_kvm (guestfs_h *g, const char *qemu);
extern char *guestfs_int_drive_source_qemu_param (guestfs_h *g, const struct drive_source *src);
extern bool guestfs_int_discard_possible (guestfs_h *g, struct drive *drv);
extern char *guestfs_int_qemu_escape_param (guestfs_h *g, const char *param);

View File

@@ -53,6 +53,7 @@
/* Per-handle data. */
struct backend_direct_data {
const char *qemu; /* Qemu binary name. */
pid_t pid; /* Qemu PID. */
pid_t recoverypid; /* Recovery process PID. */
@@ -499,20 +500,23 @@ launch_direct (guestfs_h *g, void *datav, const char *arg)
guestfs_int_launch_send_progress (g, 3);
data->qemu = g->hv ? : get_default_hv_direct (g, data);
debug (g, "chosen qemu: %s", data->qemu);
debug (g, "begin testing qemu features");
/* If debugging, print the qemu version. */
if (g->verbose) {
CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
guestfs_int_cmd_add_arg (cmd, g->hv);
guestfs_int_cmd_add_arg (cmd, data->qemu);
guestfs_int_cmd_add_arg (cmd, "-version");
guestfs_int_cmd_set_stdout_callback (cmd, debug_lines, NULL, 0);
guestfs_int_cmd_run (cmd);
}
/* Work out if KVM is supported or if the user wants to force TCG. */
if ((has_kvm = guestfs_int_platform_has_kvm (g)) == -1)
if ((has_kvm = guestfs_int_platform_has_kvm (g, data->qemu)) == -1)
goto cleanup0;
debug (g, "qemu KVM: %s", has_kvm ? "enabled" : "disabled");
@@ -588,7 +592,7 @@ launch_direct (guestfs_h *g, void *datav, const char *arg)
perrorf (g, "qemuopts");
goto cleanup0;
}
if (qemuopts_set_binary (qopts, g->hv) == -1) goto qemuopts_error;
if (qemuopts_set_binary (qopts, data->qemu) == -1) goto qemuopts_error;
/* CVE-2011-4127 mitigation: Disable SCSI ioctls on virtio-blk
* devices.
@@ -874,8 +878,8 @@ launch_direct (guestfs_h *g, void *datav, const char *arg)
if (g->pgroup)
setpgid (0, 0);
execve (g->hv, argv, env); /* Run qemu. */
perror (g->hv);
execvpe (data->qemu, argv, env); /* Run qemu. */
perror (data->qemu);
_exit (EXIT_FAILURE);
}
@@ -1078,7 +1082,7 @@ shutdown_direct (guestfs_h *g, void *datav, int check_for_errors)
if (guestfs_int_wait4 (g, data->pid, &status, &rusage, "qemu") == -1)
ret = -1;
else if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) {
guestfs_int_external_command_failed (g, status, g->hv, NULL);
guestfs_int_external_command_failed (g, status, data->qemu, NULL);
ret = -1;
}
else

View File

@@ -59,7 +59,8 @@ cleanup_json_object_put (void *ptr)
* Run a generic QMP test on the QEMU binary.
*/
static int
generic_qmp_test (guestfs_h *g, const char *qmp_command, char **outp)
generic_qmp_test (guestfs_h *g,
const char *qemu, const char *qmp_command, char **outp)
{
CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
int r, fd;
@@ -81,7 +82,7 @@ generic_qmp_test (guestfs_h *g, const char *qmp_command, char **outp)
guestfs_int_cmd_add_string_unquoted (cmd, "'{ \"execute\": \"quit\" }' ");
guestfs_int_cmd_add_string_unquoted (cmd, " | ");
guestfs_int_cmd_add_string_unquoted (cmd, "QEMU_AUDIO_DRV=none ");
guestfs_int_cmd_add_string_quoted (cmd, g->hv);
guestfs_int_cmd_add_string_quoted (cmd, qemu);
guestfs_int_cmd_add_string_unquoted (cmd, " -display none");
guestfs_int_cmd_add_string_unquoted (cmd, " -machine none,accel=kvm:hvf:tcg");
guestfs_int_cmd_add_string_unquoted (cmd, " -qmp stdio");
@@ -143,7 +144,7 @@ generic_qmp_test (guestfs_h *g, const char *qmp_command, char **outp)
err:
errors = guestfs_int_cmd_get_pipe_errors (cmd);
error (g, "%s: %s\nError output of qemu: %s", g->hv, errmsg, errors);
error (g, "%s: %s\nError output of qemu: %s", qemu, errmsg, errors);
return -1;
}
@@ -191,11 +192,11 @@ parse_has_kvm (guestfs_h *g, const char *json)
* that command.
*/
int
guestfs_int_platform_has_kvm (guestfs_h *g)
guestfs_int_platform_has_kvm (guestfs_h *g, const char *qemu)
{
CLEANUP_FREE char *query_kvm = NULL;
if (generic_qmp_test (g, "query-kvm", &query_kvm) == -1)
if (generic_qmp_test (g, qemu, "query-kvm", &query_kvm) == -1)
return -1;
return parse_has_kvm (g, query_kvm);