@samitouri / QOSamiQemu / commits / 55327b85ce

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>

Florian Hofhammer committed Mar 5, 2026 at 11:06 UTC 55327b85ce32c32572f244e61a6336d2320dc8d7
1 file changed +8 -3
plugins/api.c
+8 -3
@@ -424,6 +424,7 @@ static GArray *create_register_handles(GArray *gdbstub_regs)
424 for (int i = 0; i < gdbstub_regs->len; i++) {
425 GDBRegDesc *grd = &g_array_index(gdbstub_regs, GDBRegDesc, i);
426 qemu_plugin_reg_descriptor desc;
427 + gint plugin_ro_bit = 0;
428
429 /* skip "un-named" regs */
430 if (!grd->name) {
@@ -431,7 +432,6 @@ static GArray *create_register_handles(GArray *gdbstub_regs)
432 }
433
434 /* Create a record for the plugin */
434 - desc.handle = GINT_TO_POINTER(grd->gdb_reg + 1);
435 desc.name = g_intern_string(grd->name);
436 desc.is_readonly = false;
437 if (g_strcmp0(desc.name, pc_str) == 0
@@ -442,7 +442,9 @@ static GArray *create_register_handles(GArray *gdbstub_regs)
442 || g_strcmp0(desc.name, rpc_str) == 0
443 ) {
444 desc.is_readonly = true;
445 + plugin_ro_bit = 1;
446 }
447 + desc.handle = GINT_TO_POINTER((grd->gdb_reg << 1) | plugin_ro_bit);
448 desc.feature = g_intern_string(grd->feature_name);
449 g_array_append_val(find_data, desc);
450 }
@@ -467,7 +469,7 @@ bool qemu_plugin_read_register(struct qemu_plugin_register *reg,
469 return false;
470 }
471
470 - return (gdb_read_register(current_cpu, buf, GPOINTER_TO_INT(reg) - 1) > 0);
472 + return (gdb_read_register(current_cpu, buf, GPOINTER_TO_INT(reg) >> 1) > 0);
473 }
474
475 bool qemu_plugin_write_register(struct qemu_plugin_register *reg,
@@ -475,13 +477,16 @@ bool qemu_plugin_write_register(struct qemu_plugin_register *reg,
477 {
478 g_assert(current_cpu);
479
480 + /* Read-only property is encoded in least significant bit */
481 + g_assert((GPOINTER_TO_INT(reg) & 1) == 0);
482 +
483 if (buf->len == 0 ||
484 (qemu_plugin_get_cb_flags() != QEMU_PLUGIN_CB_RW_REGS &&
485 qemu_plugin_get_cb_flags() != QEMU_PLUGIN_CB_RW_REGS_PC)) {
486 return false;
487 }
488
484 - return (gdb_write_register(current_cpu, buf->data, GPOINTER_TO_INT(reg) - 1) > 0);
489 + return (gdb_write_register(current_cpu, buf->data, GPOINTER_TO_INT(reg) >> 1) > 0);
490 }
491
492 void qemu_plugin_set_pc(uint64_t vaddr)