From: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
To: qemu-devel@nongnu.org, "Daniel P. Berrangé " <berrange@redhat.com>
Cc: "Marc-André Lureau" <marcandre.lureau@redhat.com>,
"Philippe Mathieu-Daudé " <philmd@linaro.org>,
"Konstantin Kostiuk" <kkostiuk@redhat.com>,
"Daniel P. Berrangé " <berrange@redhat.com>,
"Thomas Huth" <thuth@redhat.com>,
"Michael Roth" <michael.roth@amd.com>,
"Paolo Bonzini" <pbonzini@redhat.com>
Subject: Re: [PATCH v2 22/22] qga: centralize logic for disabling/enabling commands
Date: Wed, 03 Jul 2024 13:01:11 +0300 [thread overview]
Message-ID: <g1m2c.r93vk15jos2y@linaro.org> (raw)
In-Reply-To: <20240613154406.1365469-17-berrange@redhat.com>
Hello Daniel,
This cleanup seems like a good idea,
On Thu, 13 Jun 2024 18:44, "Daniel P. Berrangé" <berrange@redhat.com> wrote:
>It is confusing having many different pieces of code enabling and
>disabling commands, and it is not clear that they all have the same
>semantics, especially wrt prioritization of the block/allow lists.
>The code attempted to prevent the user from setting both the block
>and allow lists concurrently, however, the logic was flawed as it
>checked settings in the configuration file separately from the
>command line arguments. Thus it was possible to set a block list
>in the config file and an allow list via a command line argument.
>The --dump-conf option also creates a configuration file with both
>keys present, even if unset, which means it is creating a config
>that cannot actually be loaded again.
>
>Centralizing the code in a single method "ga_apply_command_filters"
>will provide a strong guarantee of consistency and clarify the
>intended behaviour. With this there is no compelling technical
>reason to prevent concurrent setting of both the allow and block
>lists, so this flawed restriction is removed.
>
>Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
>---
> docs/interop/qemu-ga.rst | 14 +++++
> qga/commands-posix.c | 6 --
> qga/commands-win32.c | 6 --
> qga/main.c | 128 +++++++++++++++++----------------------
> 4 files changed, 70 insertions(+), 84 deletions(-)
>
>diff --git a/docs/interop/qemu-ga.rst b/docs/interop/qemu-ga.rst
>index e42b370319..e35dcaf0e7 100644
>--- a/docs/interop/qemu-ga.rst
>+++ b/docs/interop/qemu-ga.rst
>@@ -28,6 +28,20 @@ configuration options on the command line. For the same key, the last
> option wins, but the lists accumulate (see below for configuration
> 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, and then allowed list will
>+be applied, followed by the blocked list.
Nit: Missing an article here
-then all RPCs will be blocked by default, and then allowed list will
+then all RPCs will be blocked by default, then the allowed list will
>+
>+While filesystems are frozen, all except for a designated safe set
>+of RPCs will blocked, regardless of what the general configuration
>+declares.
>+
> Options
> -------
>
>diff --git a/qga/commands-posix.c b/qga/commands-posix.c
>index f4104f2760..578d29f228 100644
>--- a/qga/commands-posix.c
>+++ b/qga/commands-posix.c
>@@ -1136,12 +1136,6 @@ error:
>
> #endif /* HAVE_GETIFADDRS */
>
>-/* add unsupported commands to the list of blocked RPCs */
>-GList *ga_command_init_blockedrpcs(GList *blockedrpcs)
>-{
>- return blockedrpcs;
>-}
>-
> /* register init/cleanup routines for stateful command groups */
> void ga_command_state_init(GAState *s, GACommandState *cs)
> {
>diff --git a/qga/commands-win32.c b/qga/commands-win32.c
>index 5866cc2e3c..61b36da469 100644
>--- a/qga/commands-win32.c
>+++ b/qga/commands-win32.c
>@@ -1958,12 +1958,6 @@ done:
> g_free(rawpasswddata);
> }
>
>-/* add unsupported commands to the list of blocked RPCs */
>-GList *ga_command_init_blockedrpcs(GList *blockedrpcs)
>-{
>- return blockedrpcs;
>-}
>-
> /* register init/cleanup routines for stateful command groups */
> void ga_command_state_init(GAState *s, GACommandState *cs)
> {
>diff --git a/qga/main.c b/qga/main.c
>index f68a32bf7b..72c16fead8 100644
>--- a/qga/main.c
>+++ b/qga/main.c
>@@ -419,60 +419,79 @@ static gint ga_strcmp(gconstpointer str1, gconstpointer str2)
> return strcmp(str1, str2);
> }
>
>-/* disable commands that aren't safe for fsfreeze */
>-static void ga_disable_not_allowed_freeze(const QmpCommand *cmd, void *opaque)
>+static bool ga_command_is_allowed(const QmpCommand *cmd, GAState *state)
> {
>- bool allowed = false;
> int i = 0;
>+ GAConfig *config = state->config;
> const char *name = qmp_command_name(cmd);
>+ /* Fallback policy is allow everything */
>+ bool allowed = true;
>
>- while (ga_freeze_allowlist[i] != NULL) {
>- if (strcmp(name, ga_freeze_allowlist[i]) == 0) {
>+ if (config->allowedrpcs) {
>+ /*
>+ * 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;
> }
>- i++;
> }
>- if (!allowed) {
>- g_debug("disabling command: %s", name);
>- qmp_disable_command(&ga_commands, name, "the agent is in frozen state");
>- }
>-}
>
>-/* [re-]enable all commands, except those explicitly blocked by user */
>-static void ga_enable_non_blocked(const QmpCommand *cmd, void *opaque)
>-{
>- GAState *s = opaque;
>- GList *blockedrpcs = s->blockedrpcs;
>- GList *allowedrpcs = s->allowedrpcs;
>- const char *name = qmp_command_name(cmd);
>-
>- if (g_list_find_custom(blockedrpcs, name, ga_strcmp) == NULL) {
>- if (qmp_command_is_enabled(cmd)) {
>- return;
>+ /*
>+ * 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 (allowedrpcs &&
>- g_list_find_custom(allowedrpcs, name, ga_strcmp) == NULL) {
>- return;
>- }
>+ /*
>+ * If frozen, this filtering must take priority over
>+ * absolutely everything
>+ */
>+ if (state->frozen) {
>+ allowed = false;
>
>- g_debug("enabling command: %s", name);
>- qmp_enable_command(&ga_commands, name);
>+ while (ga_freeze_allowlist[i] != NULL) {
>+ if (strcmp(name, ga_freeze_allowlist[i]) == 0) {
>+ allowed = true;
>+ }
>+ i++;
>+ }
> }
>+
>+ return allowed;
> }
IUUC, we can check by priority here: first check if (state->frozen),
then blockedrpcs, then allowedrpcs and then return a default fallback
value allowed = config->blockedrpcs != NULL && config->allowedrpcs !=
NULL
This way the function will sort of document what is written on the docs
as well.
>
>-/* disable commands that aren't allowed */
>-static void ga_disable_not_allowed(const QmpCommand *cmd, void *opaque)
>+static void ga_apply_command_filters_iter(const QmpCommand *cmd, void *opaque)
> {
>- GList *allowedrpcs = opaque;
>+ GAState *state = opaque;
>+ bool want = ga_command_is_allowed(cmd, state);
>+ bool have = qmp_command_is_enabled(cmd);
> const char *name = qmp_command_name(cmd);
>
>- if (g_list_find_custom(allowedrpcs, name, ga_strcmp) == NULL) {
>+ if (want == have) {
>+ return;
>+ }
>+
>+ if (qmp_command_is_enabled(cmd)) {
Nit:
if (have) {
Since it's already declared.
> g_debug("disabling command: %s", name);
> qmp_disable_command(&ga_commands, name, "the command is not allowed");
>+ } else {
>+ g_debug("enabling command: %s", name);
>+ qmp_enable_command(&ga_commands, name);
> }
> }
>
>+static void ga_apply_command_filters(GAState *state)
Nit: inline?
>+{
>+ qmp_for_each_command(&ga_commands, ga_apply_command_filters_iter, state);
>+}
>+
> static bool ga_create_file(const char *path)
> {
> int fd = open(path, O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR);
>@@ -505,15 +524,14 @@ void ga_set_frozen(GAState *s)
> if (ga_is_frozen(s)) {
> 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");
>- ga_disable_logging(s);
> s->frozen = true;
> if (!ga_create_file(s->state_filepath_isfrozen)) {
> g_warning("unable to create %s, fsfreeze may not function properly",
> s->state_filepath_isfrozen);
> }
>+ ga_apply_command_filters(s);
>+ ga_disable_logging(s);
> }
>
> void ga_unset_frozen(GAState *s)
>@@ -545,12 +563,12 @@ void ga_unset_frozen(GAState *s)
> }
>
> /* enable all disabled, non-blocked and allowed commands */
>- qmp_for_each_command(&ga_commands, ga_enable_non_blocked, s);
> s->frozen = false;
> if (!ga_delete_file(s->state_filepath_isfrozen)) {
> g_warning("unable to delete %s, fsfreeze may not function properly",
> s->state_filepath_isfrozen);
> }
>+ ga_apply_command_filters(s);
> }
>
> #ifdef CONFIG_FSFREEZE
>@@ -1082,13 +1100,6 @@ static void config_load(GAConfig *config, const char *confpath, bool required)
> split_list(config->aliststr, ","));
> }
>
>- if (g_key_file_has_key(keyfile, "general", "block-rpcs", 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:
> g_key_file_free(keyfile);
> if (gerr && (required ||
>@@ -1168,7 +1179,6 @@ static void config_parse(GAConfig *config, int argc, char **argv)
> {
> const char *sopt = "hVvdc:m:p:l:f:F::b:a:s:t:Dr";
> int opt_ind = 0, ch;
>- bool block_rpcs = false, allow_rpcs = false;
> const struct option lopt[] = {
> { "help", 0, NULL, 'h' },
> { "version", 0, NULL, 'V' },
>@@ -1264,7 +1274,6 @@ static void config_parse(GAConfig *config, int argc, char **argv)
> }
> config->blockedrpcs = g_list_concat(config->blockedrpcs,
> split_list(optarg, ","));
>- block_rpcs = true;
> break;
> }
> case 'a': {
>@@ -1274,7 +1283,6 @@ static void config_parse(GAConfig *config, int argc, char **argv)
> }
> config->allowedrpcs = g_list_concat(config->allowedrpcs,
> split_list(optarg, ","));
>- allow_rpcs = true;
> break;
> }
> #ifdef _WIN32
>@@ -1315,12 +1323,6 @@ static void config_parse(GAConfig *config, int argc, char **argv)
> 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)
>@@ -1431,7 +1433,6 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation)
> s->deferred_options.log_filepath = config->log_filepath;
> }
> ga_disable_logging(s);
>- qmp_for_each_command(&ga_commands, ga_disable_not_allowed_freeze, NULL);
> } else {
> if (config->daemonize) {
> become_daemon(config->pid_filepath);
>@@ -1455,25 +1456,6 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation)
> 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();
> ga_command_state_init(s, s->command_state);
> ga_command_state_init_all(s->command_state);
>@@ -1499,6 +1481,8 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation)
> }
> #endif
>
>+ ga_apply_command_filters(s);
>+
> ga_state = s;
> return s;
> }
>--
>2.45.1
>
>
next prev parent reply other threads:[~2024-07-03 10:21 UTC|newest]
Thread overview: 70+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-13 15:01 [PATCH v2 00/22] qga: clean up command source locations and conditionals Daniel P. Berrangé
2024-06-13 15:01 ` [PATCH v2 01/22] qga: drop blocking of guest-get-memory-block-size command Daniel P. Berrangé
2024-07-12 9:33 ` Konstantin Kostiuk
2024-06-13 15:01 ` [PATCH v2 02/22] qga: move linux vcpu command impls to commands-linux.c Daniel P. Berrangé
2024-07-03 8:45 ` Philippe Mathieu-Daudé
2024-07-12 8:30 ` Konstantin Kostiuk
2024-06-13 15:01 ` [PATCH v2 03/22] qga: move linux suspend " Daniel P. Berrangé
2024-07-03 8:45 ` Philippe Mathieu-Daudé
2024-07-12 8:29 ` Konstantin Kostiuk
2024-06-13 15:01 ` [PATCH v2 04/22] qga: move linux fs/disk " Daniel P. Berrangé
2024-07-03 8:46 ` Philippe Mathieu-Daudé
2024-07-12 8:29 ` Konstantin Kostiuk
2024-06-13 15:01 ` [PATCH v2 05/22] qga: move linux disk/cpu stats " Daniel P. Berrangé
2024-07-03 8:25 ` Philippe Mathieu-Daudé
2024-07-12 8:33 ` Konstantin Kostiuk
2024-06-13 15:43 ` [PATCH v2 06/22] qga: move linux memory block " Daniel P. Berrangé
2024-06-13 15:43 ` [PATCH v2 07/22] qga: move CONFIG_FSFREEZE/TRIM to be meson defined options Daniel P. Berrangé
2024-06-13 15:43 ` [PATCH v2 08/22] qga: conditionalize schema for commands unsupported on Windows Daniel P. Berrangé
2024-07-03 8:30 ` Philippe Mathieu-Daudé
2024-07-12 8:34 ` Konstantin Kostiuk
2024-06-13 15:43 ` [PATCH v2 09/22] qga: conditionalize schema for commands unsupported on non-Linux POSIX Daniel P. Berrangé
2024-07-03 8:31 ` Philippe Mathieu-Daudé
2024-07-12 8:35 ` Konstantin Kostiuk
2024-06-13 15:43 ` [PATCH v2 10/22] qga: conditionalize schema for commands requiring getifaddrs Daniel P. Berrangé
2024-07-03 8:32 ` Philippe Mathieu-Daudé
2024-07-12 8:35 ` Konstantin Kostiuk
2024-06-13 15:43 ` [PATCH v2 11/22] qga: conditionalize schema for commands requiring linux/win32 Daniel P. Berrangé
2024-06-13 15:43 ` [PATCH v2 12/22] qga: conditionalize schema for commands only supported on Windows Daniel P. Berrangé
2024-07-03 8:35 ` Philippe Mathieu-Daudé
2024-07-12 8:37 ` Konstantin Kostiuk
2024-06-13 15:43 ` [PATCH v2 13/22] qga: conditionalize schema for commands requiring fsfreeze Daniel P. Berrangé
2024-07-03 8:37 ` Philippe Mathieu-Daudé
2024-07-12 8:37 ` Konstantin Kostiuk
2024-06-13 15:43 ` [PATCH v2 14/22] qga: conditionalize schema for commands requiring fstrim Daniel P. Berrangé
2024-07-03 8:36 ` Philippe Mathieu-Daudé
2024-07-12 8:38 ` Konstantin Kostiuk
2024-06-13 15:43 ` [PATCH v2 15/22] qga: conditionalize schema for commands requiring libudev Daniel P. Berrangé
2024-07-03 8:37 ` Philippe Mathieu-Daudé
2024-07-12 8:40 ` Konstantin Kostiuk
2024-06-13 15:44 ` [PATCH v2 16/22] qga: conditionalize schema for commands requiring utmpx Daniel P. Berrangé
2024-07-03 8:38 ` Philippe Mathieu-Daudé
2024-07-12 8:43 ` Konstantin Kostiuk
2024-06-13 15:44 ` [PATCH v2 17/22] qga: conditionalize schema for commands not supported on other UNIX Daniel P. Berrangé
2024-07-03 8:39 ` Philippe Mathieu-Daudé
2024-07-12 8:43 ` Konstantin Kostiuk
2024-06-13 15:44 ` [PATCH v2 18/22] qga: don't disable fsfreeze commands if vss_init fails Daniel P. Berrangé
2024-07-03 10:21 ` Manos Pitsidianakis
2024-07-12 12:45 ` Daniel P. Berrangé
2024-06-13 15:44 ` [PATCH v2 19/22] qga: move declare of QGAConfig struct to top of file Daniel P. Berrangé
2024-07-03 8:40 ` Philippe Mathieu-Daudé
2024-07-12 8:44 ` Konstantin Kostiuk
2024-06-13 15:44 ` [PATCH v2 20/22] qga: remove pointless 'blockrpcs_key' variable Daniel P. Berrangé
2024-07-03 8:41 ` Philippe Mathieu-Daudé
2024-07-12 8:46 ` Konstantin Kostiuk
2024-06-13 15:44 ` [PATCH v2 21/22] qga: allow configuration file path via the cli Daniel P. Berrangé
2024-07-03 8:44 ` Philippe Mathieu-Daudé
2024-07-12 9:05 ` Konstantin Kostiuk
2024-07-12 9:18 ` Daniel P. Berrangé
2024-06-13 15:44 ` [PATCH v2 22/22] qga: centralize logic for disabling/enabling commands Daniel P. Berrangé
2024-07-03 10:01 ` Manos Pitsidianakis [this message]
2024-07-03 12:09 ` Philippe Mathieu-Daudé
2024-07-12 13:01 ` Daniel P. Berrangé
2024-07-03 8:26 ` [PATCH v2 06/22] qga: move linux memory block command impls to commands-linux.c Philippe Mathieu-Daudé
2024-07-12 8:34 ` Konstantin Kostiuk
2024-06-14 8:34 ` [PATCH v2 00/22] qga: clean up command source locations and conditionals Marc-André Lureau
2024-06-14 9:19 ` Daniel P. Berrangé
2024-07-02 18:00 ` Daniel P. Berrangé
2024-07-03 6:15 ` Marc-André Lureau
2024-07-03 8:06 ` Daniel P. Berrangé
2024-07-03 8:17 ` Marc-André Lureau
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=g1m2c.r93vk15jos2y@linaro.org \
--to=manos.pitsidianakis@linaro.org \
--cc=berrange@redhat.com \
--cc=kkostiuk@redhat.com \
--cc=marcandre.lureau@redhat.com \
--cc=michael.roth@amd.com \
--cc=pbonzini@redhat.com \
--cc=philmd@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).