mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'qga-pull-2024-07-23' of https://github.com/kostyanf14/qemu into staging
qga-pull-2024-07-23 # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEwsLBCepDxjwUI+uE711egWG6hOcFAmafUs0ACgkQ711egWG6 # hOffwQ/+PMFMOq3jwV11Na0GnrFHT0SLlcxNWYGQjE0Q/nwuYWMTKdo2iB9rVC7T # qxaT6PLtTZPgRsJudJ5kkvLFw88Nr6BuWl31tCVeALUO7C0oTg/oRDfYVeH4/jfG # PS5TiM6ie27SvI5lhGZhd9sRAy8N6NGgT6Fh+pS2tVVfftcfVYKVmnzgtvk314A+ # MpeW8ukVruSW+9G+suXaE750g/drZJAoepC5pW1HXdHE+IuzXNdMWZqwMqBZSM5T # X8VcLvMjFrFrfLOP2el6mloriw67aJyKe9Uwsp548HdXfZKrLCmaR7cZK5zKVQDK # Rzolyuw19wNNi0TZAwmP+MBioDiIHcM4nNhVDCHIVCbXzQHa4BhAr/cr8uucyfM5 # hdCWmaTl4Tksk4q4ooHurDWshV26QNRbLRD1Vx1Rhrwz42MmU2VG13PsSWqLj00I # fj1LzhQOmr26cewgayIL7ODwHDXiwKi+6lKS1OyTjXXubucScgxSyTNC785T6Rvk # T58KAnBRD3vDhE7Dn/4KdRClRFY+7R2/jcHdFnA4vfvOVV8ZXp/m0O0wfLEikH6/ # dGDDVBLNG5gqV477++0wdqkYFq6MmON3PH/EA6rgZYc4At5kS+HFNASBvnFRYMGf # dgtyj8jV5uoffqYOqyXxClP6eTgV1EZ0/wKZ8uJipivB7azjnkE= # =xzjT # -----END PGP SIGNATURE----- # gpg: Signature made Tue 23 Jul 2024 04:50:53 PM AEST # gpg: using RSA key C2C2C109EA43C63C1423EB84EF5D5E8161BA84E7 # gpg: Good signature from "Kostiantyn Kostiuk (Upstream PR sign) <kkostiuk@redhat.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: C2C2 C109 EA43 C63C 1423 EB84 EF5D 5E81 61BA 84E7 * tag 'qga-pull-2024-07-23' of https://github.com/kostyanf14/qemu: (25 commits) qga/linux: Add new api 'guest-network-get-route' guest-agent: document allow-rpcs in config file section qga/commands-posix: Make ga_wait_child() return boolean qga: centralize logic for disabling/enabling commands qga: allow configuration file path via the cli qga: remove pointless 'blockrpcs_key' variable qga: move declare of QGAConfig struct to top of file qga: don't disable fsfreeze commands if vss_init fails qga: conditionalize schema for commands not supported on other UNIX qga: conditionalize schema for commands requiring utmpx qga: conditionalize schema for commands requiring libudev qga: conditionalize schema for commands requiring fstrim qga: conditionalize schema for commands requiring fsfreeze qga: conditionalize schema for commands only supported on Windows qga: conditionalize schema for commands requiring linux/win32 qga: conditionalize schema for commands requiring getifaddrs qga: conditionalize schema for commands unsupported on non-Linux POSIX qga: conditionalize schema for commands unsupported on Windows qga: move CONFIG_FSFREEZE/TRIM to be meson defined options qga: move linux memory block command impls to commands-linux.c ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
@@ -28,11 +28,30 @@ configuration options on the command line. For the same key, the last
|
|||||||
option wins, but the lists accumulate (see below for configuration
|
option wins, but the lists accumulate (see below for configuration
|
||||||
file format).
|
file format).
|
||||||
|
|
||||||
|
If an allowed RPCs list is defined in the configuration, then all
|
||||||
|
RPCs will be blocked by default, except for the allowed list.
|
||||||
|
|
||||||
|
If a blocked RPCs list is defined in the configuration, then all
|
||||||
|
RPCs will be allowed by default, except for the blocked list.
|
||||||
|
|
||||||
|
If both allowed and blocked RPCs lists are defined in the configuration,
|
||||||
|
then all RPCs will be blocked by default, then the allowed list will
|
||||||
|
be applied, followed by the blocked list.
|
||||||
|
|
||||||
|
While filesystems are frozen, all except for a designated safe set
|
||||||
|
of RPCs will blocked, regardless of what the general configuration
|
||||||
|
declares.
|
||||||
|
|
||||||
Options
|
Options
|
||||||
-------
|
-------
|
||||||
|
|
||||||
.. program:: qemu-ga
|
.. program:: qemu-ga
|
||||||
|
|
||||||
|
.. option:: -c, --config=PATH
|
||||||
|
|
||||||
|
Configuration file path (the default is |CONFDIR|\ ``/qemu-ga.conf``,
|
||||||
|
unless overriden by the QGA_CONF environment variable)
|
||||||
|
|
||||||
.. option:: -m, --method=METHOD
|
.. option:: -m, --method=METHOD
|
||||||
|
|
||||||
Transport method: one of ``unix-listen``, ``virtio-serial``, or
|
Transport method: one of ``unix-listen``, ``virtio-serial``, or
|
||||||
@@ -131,6 +150,7 @@ fsfreeze-hook string
|
|||||||
statedir string
|
statedir string
|
||||||
verbose boolean
|
verbose boolean
|
||||||
block-rpcs string list
|
block-rpcs string list
|
||||||
|
allow-rpcs string list
|
||||||
============= ===========
|
============= ===========
|
||||||
|
|
||||||
See also
|
See also
|
||||||
|
|||||||
+16
@@ -2187,6 +2187,19 @@ have_virtfs_proxy_helper = get_option('virtfs_proxy_helper') \
|
|||||||
.require(libcap_ng.found(), error_message: 'the virtfs proxy helper requires libcap-ng') \
|
.require(libcap_ng.found(), error_message: 'the virtfs proxy helper requires libcap-ng') \
|
||||||
.allowed()
|
.allowed()
|
||||||
|
|
||||||
|
qga_fsfreeze = false
|
||||||
|
qga_fstrim = false
|
||||||
|
if host_os == 'linux'
|
||||||
|
if cc.has_header_symbol('linux/fs.h', 'FIFREEZE')
|
||||||
|
qga_fsfreeze = true
|
||||||
|
endif
|
||||||
|
if cc.has_header_symbol('linux/fs.h', 'FITRIM')
|
||||||
|
qga_fstrim = true
|
||||||
|
endif
|
||||||
|
elif host_os == 'freebsd' and cc.has_header_symbol('ufs/ffs/fs.h', 'UFSSUSPEND')
|
||||||
|
qga_fsfreeze = true
|
||||||
|
endif
|
||||||
|
|
||||||
if get_option('block_drv_ro_whitelist') == ''
|
if get_option('block_drv_ro_whitelist') == ''
|
||||||
config_host_data.set('CONFIG_BDRV_RO_WHITELIST', '')
|
config_host_data.set('CONFIG_BDRV_RO_WHITELIST', '')
|
||||||
else
|
else
|
||||||
@@ -2263,6 +2276,7 @@ config_host_data.set('CONFIG_ATTR', libattr.found())
|
|||||||
config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools'))
|
config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools'))
|
||||||
config_host_data.set('CONFIG_BRLAPI', brlapi.found())
|
config_host_data.set('CONFIG_BRLAPI', brlapi.found())
|
||||||
config_host_data.set('CONFIG_BSD', host_os in bsd_oses)
|
config_host_data.set('CONFIG_BSD', host_os in bsd_oses)
|
||||||
|
config_host_data.set('CONFIG_FREEBSD', host_os == 'freebsd')
|
||||||
config_host_data.set('CONFIG_CAPSTONE', capstone.found())
|
config_host_data.set('CONFIG_CAPSTONE', capstone.found())
|
||||||
config_host_data.set('CONFIG_COCOA', cocoa.found())
|
config_host_data.set('CONFIG_COCOA', cocoa.found())
|
||||||
config_host_data.set('CONFIG_DARWIN', host_os == 'darwin')
|
config_host_data.set('CONFIG_DARWIN', host_os == 'darwin')
|
||||||
@@ -2423,6 +2437,8 @@ config_host_data.set('CONFIG_DEBUG_TCG', get_option('debug_tcg'))
|
|||||||
config_host_data.set('CONFIG_DEBUG_REMAP', get_option('debug_remap'))
|
config_host_data.set('CONFIG_DEBUG_REMAP', get_option('debug_remap'))
|
||||||
config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
|
config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
|
||||||
config_host_data.set('CONFIG_REPLICATION', get_option('replication').allowed())
|
config_host_data.set('CONFIG_REPLICATION', get_option('replication').allowed())
|
||||||
|
config_host_data.set('CONFIG_FSFREEZE', qga_fsfreeze)
|
||||||
|
config_host_data.set('CONFIG_FSTRIM', qga_fstrim)
|
||||||
|
|
||||||
# has_header
|
# has_header
|
||||||
config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
|
config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
|
||||||
|
|||||||
@@ -149,30 +149,6 @@ int qmp_guest_fsfreeze_do_thaw(Error **errp)
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
|
|
||||||
{
|
|
||||||
error_setg(errp, QERR_UNSUPPORTED);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
|
|
||||||
{
|
|
||||||
error_setg(errp, QERR_UNSUPPORTED);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GuestDiskStatsInfoList *qmp_guest_get_diskstats(Error **errp)
|
|
||||||
{
|
|
||||||
error_setg(errp, QERR_UNSUPPORTED);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
|
|
||||||
{
|
|
||||||
error_setg(errp, QERR_UNSUPPORTED);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_FSFREEZE */
|
#endif /* CONFIG_FSFREEZE */
|
||||||
|
|
||||||
#ifdef HAVE_GETIFADDRS
|
#ifdef HAVE_GETIFADDRS
|
||||||
|
|||||||
@@ -15,19 +15,10 @@
|
|||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#ifdef FIFREEZE
|
|
||||||
#define CONFIG_FSFREEZE
|
|
||||||
#endif
|
|
||||||
#ifdef FITRIM
|
|
||||||
#define CONFIG_FSTRIM
|
|
||||||
#endif
|
|
||||||
#endif /* __linux__ */
|
#endif /* __linux__ */
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
#include <ufs/ffs/fs.h>
|
#include <ufs/ffs/fs.h>
|
||||||
#ifdef UFSSUSPEND
|
|
||||||
#define CONFIG_FSFREEZE
|
|
||||||
#endif
|
|
||||||
#endif /* __FreeBSD__ */
|
#endif /* __FreeBSD__ */
|
||||||
|
|
||||||
#if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
|
#if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+5
-2022
File diff suppressed because it is too large
Load Diff
+3
-75
@@ -1203,7 +1203,7 @@ GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
|
|||||||
GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp)
|
GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp)
|
||||||
{
|
{
|
||||||
if (!vss_initialized()) {
|
if (!vss_initialized()) {
|
||||||
error_setg(errp, QERR_UNSUPPORTED);
|
error_setg(errp, "fsfreeze not possible as VSS failed to initialize");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1231,7 +1231,7 @@ int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints,
|
|||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
if (!vss_initialized()) {
|
if (!vss_initialized()) {
|
||||||
error_setg(errp, QERR_UNSUPPORTED);
|
error_setg(errp, "fsfreeze not possible as VSS failed to initialize");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1266,7 +1266,7 @@ int64_t qmp_guest_fsfreeze_thaw(Error **errp)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!vss_initialized()) {
|
if (!vss_initialized()) {
|
||||||
error_setg(errp, QERR_UNSUPPORTED);
|
error_setg(errp, "fsfreeze not possible as VSS failed to initialize");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1494,11 +1494,6 @@ out:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_guest_suspend_hybrid(Error **errp)
|
|
||||||
{
|
|
||||||
error_setg(errp, QERR_UNSUPPORTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
static IP_ADAPTER_ADDRESSES *guest_get_adapters_addresses(Error **errp)
|
static IP_ADAPTER_ADDRESSES *guest_get_adapters_addresses(Error **errp)
|
||||||
{
|
{
|
||||||
IP_ADAPTER_ADDRESSES *adptr_addrs = NULL;
|
IP_ADAPTER_ADDRESSES *adptr_addrs = NULL;
|
||||||
@@ -1862,12 +1857,6 @@ GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
|
|
||||||
{
|
|
||||||
error_setg(errp, QERR_UNSUPPORTED);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gchar *
|
static gchar *
|
||||||
get_net_error_message(gint error)
|
get_net_error_message(gint error)
|
||||||
{
|
{
|
||||||
@@ -1969,55 +1958,6 @@ done:
|
|||||||
g_free(rawpasswddata);
|
g_free(rawpasswddata);
|
||||||
}
|
}
|
||||||
|
|
||||||
GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp)
|
|
||||||
{
|
|
||||||
error_setg(errp, QERR_UNSUPPORTED);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GuestMemoryBlockResponseList *
|
|
||||||
qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp)
|
|
||||||
{
|
|
||||||
error_setg(errp, QERR_UNSUPPORTED);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp)
|
|
||||||
{
|
|
||||||
error_setg(errp, QERR_UNSUPPORTED);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add unsupported commands to the list of blocked RPCs */
|
|
||||||
GList *ga_command_init_blockedrpcs(GList *blockedrpcs)
|
|
||||||
{
|
|
||||||
const char *list_unsupported[] = {
|
|
||||||
"guest-suspend-hybrid",
|
|
||||||
"guest-set-vcpus",
|
|
||||||
"guest-get-memory-blocks", "guest-set-memory-blocks",
|
|
||||||
"guest-get-memory-block-size", "guest-get-memory-block-info",
|
|
||||||
NULL};
|
|
||||||
char **p = (char **)list_unsupported;
|
|
||||||
|
|
||||||
while (*p) {
|
|
||||||
blockedrpcs = g_list_append(blockedrpcs, g_strdup(*p++));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vss_init(true)) {
|
|
||||||
g_debug("vss_init failed, vss commands are going to be disabled");
|
|
||||||
const char *list[] = {
|
|
||||||
"guest-get-fsinfo", "guest-fsfreeze-status",
|
|
||||||
"guest-fsfreeze-freeze", "guest-fsfreeze-thaw", NULL};
|
|
||||||
p = (char **)list;
|
|
||||||
|
|
||||||
while (*p) {
|
|
||||||
blockedrpcs = g_list_append(blockedrpcs, g_strdup(*p++));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return blockedrpcs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* register init/cleanup routines for stateful command groups */
|
/* register init/cleanup routines for stateful command groups */
|
||||||
void ga_command_state_init(GAState *s, GACommandState *cs)
|
void ga_command_state_init(GAState *s, GACommandState *cs)
|
||||||
{
|
{
|
||||||
@@ -2505,15 +2445,3 @@ char *qga_get_host_name(Error **errp)
|
|||||||
|
|
||||||
return g_utf16_to_utf8(tmp, size, NULL, NULL, NULL);
|
return g_utf16_to_utf8(tmp, size, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
GuestDiskStatsInfoList *qmp_guest_get_diskstats(Error **errp)
|
|
||||||
{
|
|
||||||
error_setg(errp, QERR_UNSUPPORTED);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
|
|
||||||
{
|
|
||||||
error_setg(errp, QERR_UNSUPPORTED);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|||||||
+117
-107
@@ -70,6 +70,28 @@ typedef struct GAPersistentState {
|
|||||||
|
|
||||||
typedef struct GAConfig GAConfig;
|
typedef struct GAConfig GAConfig;
|
||||||
|
|
||||||
|
struct GAConfig {
|
||||||
|
char *channel_path;
|
||||||
|
char *method;
|
||||||
|
char *log_filepath;
|
||||||
|
char *pid_filepath;
|
||||||
|
#ifdef CONFIG_FSFREEZE
|
||||||
|
char *fsfreeze_hook;
|
||||||
|
#endif
|
||||||
|
char *state_dir;
|
||||||
|
#ifdef _WIN32
|
||||||
|
const char *service;
|
||||||
|
#endif
|
||||||
|
gchar *bliststr; /* blockedrpcs may point to this string */
|
||||||
|
gchar *aliststr; /* allowedrpcs may point to this string */
|
||||||
|
GList *blockedrpcs;
|
||||||
|
GList *allowedrpcs;
|
||||||
|
int daemonize;
|
||||||
|
GLogLevelFlags log_level;
|
||||||
|
int dumpconf;
|
||||||
|
bool retry_path;
|
||||||
|
};
|
||||||
|
|
||||||
struct GAState {
|
struct GAState {
|
||||||
JSONMessageParser parser;
|
JSONMessageParser parser;
|
||||||
GMainLoop *main_loop;
|
GMainLoop *main_loop;
|
||||||
@@ -226,12 +248,16 @@ static void usage(const char *cmd)
|
|||||||
#ifdef CONFIG_FSFREEZE
|
#ifdef CONFIG_FSFREEZE
|
||||||
g_autofree char *fsfreeze_hook = get_relocated_path(QGA_FSFREEZE_HOOK_DEFAULT);
|
g_autofree char *fsfreeze_hook = get_relocated_path(QGA_FSFREEZE_HOOK_DEFAULT);
|
||||||
#endif
|
#endif
|
||||||
|
g_autofree char *conf_path = get_relocated_path(QGA_CONF_DEFAULT);
|
||||||
|
|
||||||
printf(
|
printf(
|
||||||
"Usage: %s [-m <method> -p <path>] [<options>]\n"
|
"Usage: %s [-m <method> -p <path>] [<options>]\n"
|
||||||
"QEMU Guest Agent " QEMU_FULL_VERSION "\n"
|
"QEMU Guest Agent " QEMU_FULL_VERSION "\n"
|
||||||
QEMU_COPYRIGHT "\n"
|
QEMU_COPYRIGHT "\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
" -c, --config=PATH configuration file path (default is\n"
|
||||||
|
" %s/qemu-ga.conf\n"
|
||||||
|
" unless overriden by the QGA_CONF environment variable)\n"
|
||||||
" -m, --method transport method: one of unix-listen, virtio-serial,\n"
|
" -m, --method transport method: one of unix-listen, virtio-serial,\n"
|
||||||
" isa-serial, or vsock-listen (virtio-serial is the default)\n"
|
" isa-serial, or vsock-listen (virtio-serial is the default)\n"
|
||||||
" -p, --path device/socket path (the default for virtio-serial is:\n"
|
" -p, --path device/socket path (the default for virtio-serial is:\n"
|
||||||
@@ -272,8 +298,8 @@ QEMU_COPYRIGHT "\n"
|
|||||||
" plug/unplug, etc.)\n"
|
" plug/unplug, etc.)\n"
|
||||||
" -h, --help display this help and exit\n"
|
" -h, --help display this help and exit\n"
|
||||||
"\n"
|
"\n"
|
||||||
QEMU_HELP_BOTTOM "\n"
|
QEMU_HELP_BOTTOM "\n",
|
||||||
, cmd, QGA_VIRTIO_PATH_DEFAULT, QGA_SERIAL_PATH_DEFAULT,
|
cmd, conf_path, QGA_VIRTIO_PATH_DEFAULT, QGA_SERIAL_PATH_DEFAULT,
|
||||||
dfl_pathnames.pidfile,
|
dfl_pathnames.pidfile,
|
||||||
#ifdef CONFIG_FSFREEZE
|
#ifdef CONFIG_FSFREEZE
|
||||||
fsfreeze_hook,
|
fsfreeze_hook,
|
||||||
@@ -397,58 +423,77 @@ static gint ga_strcmp(gconstpointer str1, gconstpointer str2)
|
|||||||
return strcmp(str1, str2);
|
return strcmp(str1, str2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* disable commands that aren't safe for fsfreeze */
|
static bool ga_command_is_allowed(const QmpCommand *cmd, GAState *state)
|
||||||
static void ga_disable_not_allowed_freeze(const QmpCommand *cmd, void *opaque)
|
|
||||||
{
|
{
|
||||||
bool allowed = false;
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
GAConfig *config = state->config;
|
||||||
const char *name = qmp_command_name(cmd);
|
const char *name = qmp_command_name(cmd);
|
||||||
|
/* Fallback policy is allow everything */
|
||||||
|
bool allowed = true;
|
||||||
|
|
||||||
while (ga_freeze_allowlist[i] != NULL) {
|
if (config->allowedrpcs) {
|
||||||
if (strcmp(name, ga_freeze_allowlist[i]) == 0) {
|
/*
|
||||||
|
* If an allow-list is given, this changes the fallback
|
||||||
|
* policy to deny everything
|
||||||
|
*/
|
||||||
|
allowed = false;
|
||||||
|
|
||||||
|
if (g_list_find_custom(config->allowedrpcs, name, ga_strcmp) != NULL) {
|
||||||
allowed = true;
|
allowed = true;
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
if (!allowed) {
|
|
||||||
g_debug("disabling command: %s", name);
|
/*
|
||||||
qmp_disable_command(&ga_commands, name, "the agent is in frozen state");
|
* If both allowedrpcs and blockedrpcs are set, the blocked
|
||||||
|
* list will take priority
|
||||||
|
*/
|
||||||
|
if (config->blockedrpcs) {
|
||||||
|
if (g_list_find_custom(config->blockedrpcs, name, ga_strcmp) != NULL) {
|
||||||
|
allowed = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If frozen, this filtering must take priority over
|
||||||
|
* absolutely everything
|
||||||
|
*/
|
||||||
|
if (state->frozen) {
|
||||||
|
allowed = false;
|
||||||
|
|
||||||
|
while (ga_freeze_allowlist[i] != NULL) {
|
||||||
|
if (strcmp(name, ga_freeze_allowlist[i]) == 0) {
|
||||||
|
allowed = true;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [re-]enable all commands, except those explicitly blocked by user */
|
static void ga_apply_command_filters_iter(const QmpCommand *cmd, void *opaque)
|
||||||
static void ga_enable_non_blocked(const QmpCommand *cmd, void *opaque)
|
|
||||||
{
|
{
|
||||||
GAState *s = opaque;
|
GAState *state = opaque;
|
||||||
GList *blockedrpcs = s->blockedrpcs;
|
bool want = ga_command_is_allowed(cmd, state);
|
||||||
GList *allowedrpcs = s->allowedrpcs;
|
bool have = qmp_command_is_enabled(cmd);
|
||||||
const char *name = qmp_command_name(cmd);
|
const char *name = qmp_command_name(cmd);
|
||||||
|
|
||||||
if (g_list_find_custom(blockedrpcs, name, ga_strcmp) == NULL) {
|
if (want == have) {
|
||||||
if (qmp_command_is_enabled(cmd)) {
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (allowedrpcs &&
|
|
||||||
g_list_find_custom(allowedrpcs, name, ga_strcmp) == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (have) {
|
||||||
|
g_debug("disabling command: %s", name);
|
||||||
|
qmp_disable_command(&ga_commands, name, "the command is not allowed");
|
||||||
|
} else {
|
||||||
g_debug("enabling command: %s", name);
|
g_debug("enabling command: %s", name);
|
||||||
qmp_enable_command(&ga_commands, name);
|
qmp_enable_command(&ga_commands, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* disable commands that aren't allowed */
|
static void ga_apply_command_filters(GAState *state)
|
||||||
static void ga_disable_not_allowed(const QmpCommand *cmd, void *opaque)
|
|
||||||
{
|
{
|
||||||
GList *allowedrpcs = opaque;
|
qmp_for_each_command(&ga_commands, ga_apply_command_filters_iter, state);
|
||||||
const char *name = qmp_command_name(cmd);
|
|
||||||
|
|
||||||
if (g_list_find_custom(allowedrpcs, name, ga_strcmp) == NULL) {
|
|
||||||
g_debug("disabling command: %s", name);
|
|
||||||
qmp_disable_command(&ga_commands, name, "the command is not allowed");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ga_create_file(const char *path)
|
static bool ga_create_file(const char *path)
|
||||||
@@ -483,15 +528,14 @@ void ga_set_frozen(GAState *s)
|
|||||||
if (ga_is_frozen(s)) {
|
if (ga_is_frozen(s)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* disable all forbidden (for frozen state) commands */
|
|
||||||
qmp_for_each_command(&ga_commands, ga_disable_not_allowed_freeze, NULL);
|
|
||||||
g_warning("disabling logging due to filesystem freeze");
|
g_warning("disabling logging due to filesystem freeze");
|
||||||
ga_disable_logging(s);
|
|
||||||
s->frozen = true;
|
s->frozen = true;
|
||||||
if (!ga_create_file(s->state_filepath_isfrozen)) {
|
if (!ga_create_file(s->state_filepath_isfrozen)) {
|
||||||
g_warning("unable to create %s, fsfreeze may not function properly",
|
g_warning("unable to create %s, fsfreeze may not function properly",
|
||||||
s->state_filepath_isfrozen);
|
s->state_filepath_isfrozen);
|
||||||
}
|
}
|
||||||
|
ga_apply_command_filters(s);
|
||||||
|
ga_disable_logging(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ga_unset_frozen(GAState *s)
|
void ga_unset_frozen(GAState *s)
|
||||||
@@ -523,12 +567,12 @@ void ga_unset_frozen(GAState *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* enable all disabled, non-blocked and allowed commands */
|
/* enable all disabled, non-blocked and allowed commands */
|
||||||
qmp_for_each_command(&ga_commands, ga_enable_non_blocked, s);
|
|
||||||
s->frozen = false;
|
s->frozen = false;
|
||||||
if (!ga_delete_file(s->state_filepath_isfrozen)) {
|
if (!ga_delete_file(s->state_filepath_isfrozen)) {
|
||||||
g_warning("unable to delete %s, fsfreeze may not function properly",
|
g_warning("unable to delete %s, fsfreeze may not function properly",
|
||||||
s->state_filepath_isfrozen);
|
s->state_filepath_isfrozen);
|
||||||
}
|
}
|
||||||
|
ga_apply_command_filters(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_FSFREEZE
|
#ifdef CONFIG_FSFREEZE
|
||||||
@@ -996,38 +1040,14 @@ static GList *split_list(const gchar *str, const gchar *delim)
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GAConfig {
|
static void config_load(GAConfig *config, const char *confpath, bool required)
|
||||||
char *channel_path;
|
|
||||||
char *method;
|
|
||||||
char *log_filepath;
|
|
||||||
char *pid_filepath;
|
|
||||||
#ifdef CONFIG_FSFREEZE
|
|
||||||
char *fsfreeze_hook;
|
|
||||||
#endif
|
|
||||||
char *state_dir;
|
|
||||||
#ifdef _WIN32
|
|
||||||
const char *service;
|
|
||||||
#endif
|
|
||||||
gchar *bliststr; /* blockedrpcs may point to this string */
|
|
||||||
gchar *aliststr; /* allowedrpcs may point to this string */
|
|
||||||
GList *blockedrpcs;
|
|
||||||
GList *allowedrpcs;
|
|
||||||
int daemonize;
|
|
||||||
GLogLevelFlags log_level;
|
|
||||||
int dumpconf;
|
|
||||||
bool retry_path;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void config_load(GAConfig *config)
|
|
||||||
{
|
{
|
||||||
GError *gerr = NULL;
|
GError *gerr = NULL;
|
||||||
GKeyFile *keyfile;
|
GKeyFile *keyfile;
|
||||||
g_autofree char *conf = g_strdup(g_getenv("QGA_CONF")) ?: get_relocated_path(QGA_CONF_DEFAULT);
|
|
||||||
const gchar *blockrpcs_key = "block-rpcs";
|
|
||||||
|
|
||||||
/* read system config */
|
/* read system config */
|
||||||
keyfile = g_key_file_new();
|
keyfile = g_key_file_new();
|
||||||
if (!g_key_file_load_from_file(keyfile, conf, 0, &gerr)) {
|
if (!g_key_file_load_from_file(keyfile, confpath, 0, &gerr)) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
if (g_key_file_has_key(keyfile, "general", "daemon", NULL)) {
|
if (g_key_file_has_key(keyfile, "general", "daemon", NULL)) {
|
||||||
@@ -1071,9 +1091,9 @@ static void config_load(GAConfig *config)
|
|||||||
g_key_file_get_boolean(keyfile, "general", "retry-path", &gerr);
|
g_key_file_get_boolean(keyfile, "general", "retry-path", &gerr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_key_file_has_key(keyfile, "general", blockrpcs_key, NULL)) {
|
if (g_key_file_has_key(keyfile, "general", "block-rpcs", NULL)) {
|
||||||
config->bliststr =
|
config->bliststr =
|
||||||
g_key_file_get_string(keyfile, "general", blockrpcs_key, &gerr);
|
g_key_file_get_string(keyfile, "general", "block-rpcs", &gerr);
|
||||||
config->blockedrpcs = g_list_concat(config->blockedrpcs,
|
config->blockedrpcs = g_list_concat(config->blockedrpcs,
|
||||||
split_list(config->bliststr, ","));
|
split_list(config->bliststr, ","));
|
||||||
}
|
}
|
||||||
@@ -1084,19 +1104,12 @@ static void config_load(GAConfig *config)
|
|||||||
split_list(config->aliststr, ","));
|
split_list(config->aliststr, ","));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_key_file_has_key(keyfile, "general", blockrpcs_key, NULL) &&
|
|
||||||
g_key_file_has_key(keyfile, "general", "allow-rpcs", NULL)) {
|
|
||||||
g_critical("wrong config, using 'block-rpcs' and 'allow-rpcs' keys at"
|
|
||||||
" the same time is not allowed");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
g_key_file_free(keyfile);
|
g_key_file_free(keyfile);
|
||||||
if (gerr &&
|
if (gerr && (required ||
|
||||||
!(gerr->domain == G_FILE_ERROR && gerr->code == G_FILE_ERROR_NOENT)) {
|
!(gerr->domain == G_FILE_ERROR && gerr->code == G_FILE_ERROR_NOENT))) {
|
||||||
g_critical("error loading configuration from path: %s, %s",
|
g_critical("error loading configuration from path: %s, %s",
|
||||||
conf, gerr->message);
|
confpath, gerr->message);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
g_clear_error(&gerr);
|
g_clear_error(&gerr);
|
||||||
@@ -1168,12 +1181,12 @@ static void config_dump(GAConfig *config)
|
|||||||
|
|
||||||
static void config_parse(GAConfig *config, int argc, char **argv)
|
static void config_parse(GAConfig *config, int argc, char **argv)
|
||||||
{
|
{
|
||||||
const char *sopt = "hVvdm:p:l:f:F::b:a:s:t:Dr";
|
const char *sopt = "hVvdc:m:p:l:f:F::b:a:s:t:Dr";
|
||||||
int opt_ind = 0, ch;
|
int opt_ind = 0, ch;
|
||||||
bool block_rpcs = false, allow_rpcs = false;
|
|
||||||
const struct option lopt[] = {
|
const struct option lopt[] = {
|
||||||
{ "help", 0, NULL, 'h' },
|
{ "help", 0, NULL, 'h' },
|
||||||
{ "version", 0, NULL, 'V' },
|
{ "version", 0, NULL, 'V' },
|
||||||
|
{ "config", 1, NULL, 'c' },
|
||||||
{ "dump-conf", 0, NULL, 'D' },
|
{ "dump-conf", 0, NULL, 'D' },
|
||||||
{ "logfile", 1, NULL, 'l' },
|
{ "logfile", 1, NULL, 'l' },
|
||||||
{ "pidfile", 1, NULL, 'f' },
|
{ "pidfile", 1, NULL, 'f' },
|
||||||
@@ -1193,6 +1206,26 @@ static void config_parse(GAConfig *config, int argc, char **argv)
|
|||||||
{ "retry-path", 0, NULL, 'r' },
|
{ "retry-path", 0, NULL, 'r' },
|
||||||
{ NULL, 0, NULL, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
g_autofree char *confpath = g_strdup(g_getenv("QGA_CONF")) ?:
|
||||||
|
get_relocated_path(QGA_CONF_DEFAULT);
|
||||||
|
bool confrequired = false;
|
||||||
|
|
||||||
|
while ((ch = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
|
||||||
|
switch (ch) {
|
||||||
|
case 'c':
|
||||||
|
g_free(confpath);
|
||||||
|
confpath = g_strdup(optarg);
|
||||||
|
confrequired = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config_load(config, confpath, confrequired);
|
||||||
|
|
||||||
|
/* Reset for second pass */
|
||||||
|
optind = 1;
|
||||||
|
|
||||||
while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
|
while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
@@ -1245,7 +1278,6 @@ static void config_parse(GAConfig *config, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
config->blockedrpcs = g_list_concat(config->blockedrpcs,
|
config->blockedrpcs = g_list_concat(config->blockedrpcs,
|
||||||
split_list(optarg, ","));
|
split_list(optarg, ","));
|
||||||
block_rpcs = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'a': {
|
case 'a': {
|
||||||
@@ -1255,7 +1287,6 @@ static void config_parse(GAConfig *config, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
config->allowedrpcs = g_list_concat(config->allowedrpcs,
|
config->allowedrpcs = g_list_concat(config->allowedrpcs,
|
||||||
split_list(optarg, ","));
|
split_list(optarg, ","));
|
||||||
allow_rpcs = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -1296,12 +1327,6 @@ static void config_parse(GAConfig *config, int argc, char **argv)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block_rpcs && allow_rpcs) {
|
|
||||||
g_critical("wrong commandline, using --block-rpcs and --allow-rpcs at the"
|
|
||||||
" same time is not allowed");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void config_free(GAConfig *config)
|
static void config_free(GAConfig *config)
|
||||||
@@ -1395,6 +1420,10 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation)
|
|||||||
" '%s': %s", config->state_dir, strerror(errno));
|
" '%s': %s", config->state_dir, strerror(errno));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!vss_init(true)) {
|
||||||
|
g_debug("vss_init failed, vss commands will not function");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ga_is_frozen(s)) {
|
if (ga_is_frozen(s)) {
|
||||||
@@ -1408,7 +1437,6 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation)
|
|||||||
s->deferred_options.log_filepath = config->log_filepath;
|
s->deferred_options.log_filepath = config->log_filepath;
|
||||||
}
|
}
|
||||||
ga_disable_logging(s);
|
ga_disable_logging(s);
|
||||||
qmp_for_each_command(&ga_commands, ga_disable_not_allowed_freeze, NULL);
|
|
||||||
} else {
|
} else {
|
||||||
if (config->daemonize) {
|
if (config->daemonize) {
|
||||||
become_daemon(config->pid_filepath);
|
become_daemon(config->pid_filepath);
|
||||||
@@ -1432,25 +1460,6 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config->allowedrpcs) {
|
|
||||||
qmp_for_each_command(&ga_commands, ga_disable_not_allowed, config->allowedrpcs);
|
|
||||||
s->allowedrpcs = config->allowedrpcs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Some commands can be blocked due to system limitation.
|
|
||||||
* Initialize blockedrpcs list even if allowedrpcs specified.
|
|
||||||
*/
|
|
||||||
config->blockedrpcs = ga_command_init_blockedrpcs(config->blockedrpcs);
|
|
||||||
if (config->blockedrpcs) {
|
|
||||||
GList *l = config->blockedrpcs;
|
|
||||||
s->blockedrpcs = config->blockedrpcs;
|
|
||||||
do {
|
|
||||||
g_debug("disabling command: %s", (char *)l->data);
|
|
||||||
qmp_disable_command(&ga_commands, l->data, NULL);
|
|
||||||
l = g_list_next(l);
|
|
||||||
} while (l);
|
|
||||||
}
|
|
||||||
s->command_state = ga_command_state_new();
|
s->command_state = ga_command_state_new();
|
||||||
ga_command_state_init(s, s->command_state);
|
ga_command_state_init(s, s->command_state);
|
||||||
ga_command_state_init_all(s->command_state);
|
ga_command_state_init_all(s->command_state);
|
||||||
@@ -1476,6 +1485,8 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ga_apply_command_filters(s);
|
||||||
|
|
||||||
ga_state = s;
|
ga_state = s;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@@ -1579,7 +1590,6 @@ int main(int argc, char **argv)
|
|||||||
qga_qmp_init_marshal(&ga_commands);
|
qga_qmp_init_marshal(&ga_commands);
|
||||||
|
|
||||||
init_dfl_pathnames();
|
init_dfl_pathnames();
|
||||||
config_load(config);
|
|
||||||
config_parse(config, argc, argv);
|
config_parse(config, argc, argv);
|
||||||
|
|
||||||
if (config->pid_filepath == NULL) {
|
if (config->pid_filepath == NULL) {
|
||||||
|
|||||||
+175
-51
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user