Skip to content

Commit

Permalink
QMP: Enforce capability negotiation rules
Browse files Browse the repository at this point in the history
With this commit QMP will be started in Capabilities Negotiation
mode, where the only command allowed to run is 'qmp_capabilities'.

All other commands will return CommandNotFound error. Asynchronous
messages are not delivered either.

When 'qmp_capabilities' is successfully executed QMP enters in
Command mode, where all commands (except 'qmp_capabilities') are
allowed to run and asynchronous messages are delivered.

Signed-off-by: Luiz Capitulino <[email protected]>
Signed-off-by: Anthony Liguori <[email protected]>
  • Loading branch information
Luiz Capitulino authored and 6-9-6-9 committed Sep 22, 2021
1 parent 5d1b9bf commit d240d7e
Showing 1 changed file with 17 additions and 1 deletion.
18 changes: 17 additions & 1 deletion monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ Monitor *cur_mon = NULL;
static void monitor_command_cb(Monitor *mon, const char *cmdline,
void *opaque);

static inline int qmp_cmd_mode(const Monitor *mon)
{
return (mon->mc ? mon->mc->command_mode : 0);
}

/* Return true if in control mode, false otherwise */
static inline int monitor_ctrl_mode(const Monitor *mon)
{
Expand Down Expand Up @@ -369,7 +374,7 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
}

QLIST_FOREACH(mon, &mon_list, entry) {
if (monitor_ctrl_mode(mon)) {
if (monitor_ctrl_mode(mon) && qmp_cmd_mode(mon)) {
monitor_json_emitter(mon, QOBJECT(qmp));
}
}
Expand Down Expand Up @@ -4128,6 +4133,12 @@ static int monitor_check_qmp_args(const mon_cmd_t *cmd, QDict *args)
return err;
}

static int invalid_qmp_mode(const Monitor *mon, const char *cmd_name)
{
int is_cap = compare_cmd(cmd_name, "qmp_capabilities");
return (qmp_cmd_mode(mon) ? is_cap : !is_cap);
}

static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
{
int err;
Expand Down Expand Up @@ -4167,6 +4178,11 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)

cmd_name = qstring_get_str(qobject_to_qstring(obj));

if (invalid_qmp_mode(mon, cmd_name)) {
qemu_error_new(QERR_COMMAND_NOT_FOUND, cmd_name);
goto err_input;
}

/*
* XXX: We need this special case until we get info handlers
* converted into 'query-' commands
Expand Down

0 comments on commit d240d7e

Please sign in to comment.