Browse Source

plugins: prohibit writing to read-only registers

The opaque register handle encodes whether a register is read-only in
the lowest bit and prevents writing to the register via the plugin API
in this case.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Florian Hofhammer <florian.hofhammer@epfl.ch>
Link: https://lore.kernel.org/qemu-devel/20260305-setpc-v5-v7-7-4c3adba52403@epfl.ch
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
master
Florian Hofhammer 4 weeks ago
committed by Pierrick Bouvier
parent
commit
55327b85ce
  1. 11
      plugins/api.c

11
plugins/api.c

@ -424,6 +424,7 @@ static GArray *create_register_handles(GArray *gdbstub_regs)
for (int i = 0; i < gdbstub_regs->len; i++) { for (int i = 0; i < gdbstub_regs->len; i++) {
GDBRegDesc *grd = &g_array_index(gdbstub_regs, GDBRegDesc, i); GDBRegDesc *grd = &g_array_index(gdbstub_regs, GDBRegDesc, i);
qemu_plugin_reg_descriptor desc; qemu_plugin_reg_descriptor desc;
gint plugin_ro_bit = 0;
/* skip "un-named" regs */ /* skip "un-named" regs */
if (!grd->name) { if (!grd->name) {
@ -431,7 +432,6 @@ static GArray *create_register_handles(GArray *gdbstub_regs)
} }
/* Create a record for the plugin */ /* Create a record for the plugin */
desc.handle = GINT_TO_POINTER(grd->gdb_reg + 1);
desc.name = g_intern_string(grd->name); desc.name = g_intern_string(grd->name);
desc.is_readonly = false; desc.is_readonly = false;
if (g_strcmp0(desc.name, pc_str) == 0 if (g_strcmp0(desc.name, pc_str) == 0
@ -442,7 +442,9 @@ static GArray *create_register_handles(GArray *gdbstub_regs)
|| g_strcmp0(desc.name, rpc_str) == 0 || g_strcmp0(desc.name, rpc_str) == 0
) { ) {
desc.is_readonly = true; desc.is_readonly = true;
plugin_ro_bit = 1;
} }
desc.handle = GINT_TO_POINTER((grd->gdb_reg << 1) | plugin_ro_bit);
desc.feature = g_intern_string(grd->feature_name); desc.feature = g_intern_string(grd->feature_name);
g_array_append_val(find_data, desc); g_array_append_val(find_data, desc);
} }
@ -467,7 +469,7 @@ bool qemu_plugin_read_register(struct qemu_plugin_register *reg,
return false; return false;
} }
return (gdb_read_register(current_cpu, buf, GPOINTER_TO_INT(reg) - 1) > 0); return (gdb_read_register(current_cpu, buf, GPOINTER_TO_INT(reg) >> 1) > 0);
} }
bool qemu_plugin_write_register(struct qemu_plugin_register *reg, bool qemu_plugin_write_register(struct qemu_plugin_register *reg,
@ -475,13 +477,16 @@ bool qemu_plugin_write_register(struct qemu_plugin_register *reg,
{ {
g_assert(current_cpu); g_assert(current_cpu);
/* Read-only property is encoded in least significant bit */
g_assert((GPOINTER_TO_INT(reg) & 1) == 0);
if (buf->len == 0 || if (buf->len == 0 ||
(qemu_plugin_get_cb_flags() != QEMU_PLUGIN_CB_RW_REGS && (qemu_plugin_get_cb_flags() != QEMU_PLUGIN_CB_RW_REGS &&
qemu_plugin_get_cb_flags() != QEMU_PLUGIN_CB_RW_REGS_PC)) { qemu_plugin_get_cb_flags() != QEMU_PLUGIN_CB_RW_REGS_PC)) {
return false; return false;
} }
return (gdb_write_register(current_cpu, buf->data, GPOINTER_TO_INT(reg) - 1) > 0); return (gdb_write_register(current_cpu, buf->data, GPOINTER_TO_INT(reg) >> 1) > 0);
} }
void qemu_plugin_set_pc(uint64_t vaddr) void qemu_plugin_set_pc(uint64_t vaddr)

Loading…
Cancel
Save