* [PATCH] ui/console: fix use-after-free in qemu_console_set_cursor
@ 2026-08-27 7:06 marcandre.lureau
2026-08-27 8:47 ` Daniel P. Berrangé
0 siblings, 1 reply; 6+ messages in thread
From: marcandre.lureau @ 2026-08-27 7:06 UTC (permalink / raw)
To: qemu-devel; +Cc: akihiko.odaki, Marc-André Lureau
From: Marc-André Lureau <marcandre.lureau@redhat.com>
When the new cursor is the same object as the one already held by
the console and the refcount is 1, cursor_unref frees it before
cursor_ref can increment the count.
Ref the incoming cursor before unreffing the old one so the
refcount goes 1-2-1 instead of 1-0 (freed) then use-after-free.
This is related to 385ac97f8fad ("ui: keep current cursor with
QemuConsole"), but could have happened earlier with VNC too.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
ui/console.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/ui/console.c b/ui/console.c
index a8a2a247d8f4..4db8f1cb431f 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -904,8 +904,9 @@ void qemu_console_set_cursor(QemuConsole *c, QEMUCursor *cursor)
DisplayState *s = c->ds;
DisplayChangeListener *dcl;
+ cursor_ref(cursor);
cursor_unref(con->cursor);
- con->cursor = cursor_ref(cursor);
+ con->cursor = cursor;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (c != dcl->con) {
continue;
--
2.55.0.543.g5ebe2ebe4ea8
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] ui/console: fix use-after-free in qemu_console_set_cursor
2026-08-27 7:06 [PATCH] ui/console: fix use-after-free in qemu_console_set_cursor marcandre.lureau
@ 2026-08-27 8:47 ` Daniel P. Berrangé
2026-08-27 9:58 ` Marc-André Lureau
0 siblings, 1 reply; 6+ messages in thread
From: Daniel P. Berrangé @ 2026-08-27 8:47 UTC (permalink / raw)
To: marcandre.lureau; +Cc: qemu-devel, akihiko.odaki
On Thu, Aug 27, 2026 at 11:06:47AM +0400, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> When the new cursor is the same object as the one already held by
> the console and the refcount is 1, cursor_unref frees it before
> cursor_ref can increment the count.
>
> Ref the incoming cursor before unreffing the old one so the
> refcount goes 1-2-1 instead of 1-0 (freed) then use-after-free.
I don't see where/how this can happen. The caller of
qemu_console_set_cursor should own its own reference
on 'cursor'. So on entry to this method, 'cursor'
should have a ref of 2 if it is the same as the
current con->cursor.
if anything the behaviour you describe sounds like a
bug in a caller not holding its own reference.
>
> This is related to 385ac97f8fad ("ui: keep current cursor with
> QemuConsole"), but could have happened earlier with VNC too.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> ui/console.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/ui/console.c b/ui/console.c
> index a8a2a247d8f4..4db8f1cb431f 100644
> --- a/ui/console.c
> +++ b/ui/console.c
> @@ -904,8 +904,9 @@ void qemu_console_set_cursor(QemuConsole *c, QEMUCursor *cursor)
> DisplayState *s = c->ds;
> DisplayChangeListener *dcl;
>
> + cursor_ref(cursor);
> cursor_unref(con->cursor);
> - con->cursor = cursor_ref(cursor);
> + con->cursor = cursor;
> QLIST_FOREACH(dcl, &s->listeners, next) {
> if (c != dcl->con) {
> continue;
> --
> 2.55.0.543.g5ebe2ebe4ea8
>
>
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] ui/console: fix use-after-free in qemu_console_set_cursor
2026-08-27 8:47 ` Daniel P. Berrangé
@ 2026-08-27 9:58 ` Marc-André Lureau
2026-08-27 10:30 ` Daniel P. Berrangé
0 siblings, 1 reply; 6+ messages in thread
From: Marc-André Lureau @ 2026-08-27 9:58 UTC (permalink / raw)
To: Daniel P. Berrangé; +Cc: qemu-devel, akihiko.odaki
Hi
On Thu, Aug 27, 2026 at 12:47 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> On Thu, Aug 27, 2026 at 11:06:47AM +0400, marcandre.lureau@redhat.com wrote:
> > From: Marc-André Lureau <marcandre.lureau@redhat.com>
> >
> > When the new cursor is the same object as the one already held by
> > the console and the refcount is 1, cursor_unref frees it before
> > cursor_ref can increment the count.
> >
> > Ref the incoming cursor before unreffing the old one so the
> > refcount goes 1-2-1 instead of 1-0 (freed) then use-after-free.
>
> I don't see where/how this can happen. The caller of
> qemu_console_set_cursor should own its own reference
> on 'cursor'. So on entry to this method, 'cursor'
> should have a ref of 2 if it is the same as the
> current con->cursor.
>
> if anything the behaviour you describe sounds like a
> bug in a caller not holding its own reference.
You are right, I thought virtio-gpu kept a weak pointer, but it should
have a strong ref, so we should never reach 0. I can't explain the
crash I observed then.
>
> >
> > This is related to 385ac97f8fad ("ui: keep current cursor with
> > QemuConsole"), but could have happened earlier with VNC too.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> > ui/console.c | 3 ++-
> > 1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/ui/console.c b/ui/console.c
> > index a8a2a247d8f4..4db8f1cb431f 100644
> > --- a/ui/console.c
> > +++ b/ui/console.c
> > @@ -904,8 +904,9 @@ void qemu_console_set_cursor(QemuConsole *c, QEMUCursor *cursor)
> > DisplayState *s = c->ds;
> > DisplayChangeListener *dcl;
> >
> > + cursor_ref(cursor);
> > cursor_unref(con->cursor);
> > - con->cursor = cursor_ref(cursor);
> > + con->cursor = cursor;
> > QLIST_FOREACH(dcl, &s->listeners, next) {
> > if (c != dcl->con) {
> > continue;
> > --
> > 2.55.0.543.g5ebe2ebe4ea8
> >
> >
>
> With regards,
> Daniel
> --
> |: https://berrange.com ~~ https://hachyderm.io/@berrange :|
> |: https://libvirt.org ~~ https://entangle-photo.org :|
> |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
>
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] ui/console: fix use-after-free in qemu_console_set_cursor
2026-08-27 9:58 ` Marc-André Lureau
@ 2026-08-27 10:30 ` Daniel P. Berrangé
2026-08-27 10:36 ` Marc-André Lureau
0 siblings, 1 reply; 6+ messages in thread
From: Daniel P. Berrangé @ 2026-08-27 10:30 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, akihiko.odaki
On Thu, Aug 27, 2026 at 01:58:14PM +0400, Marc-André Lureau wrote:
> Hi
>
> On Thu, Aug 27, 2026 at 12:47 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
> >
> > On Thu, Aug 27, 2026 at 11:06:47AM +0400, marcandre.lureau@redhat.com wrote:
> > > From: Marc-André Lureau <marcandre.lureau@redhat.com>
> > >
> > > When the new cursor is the same object as the one already held by
> > > the console and the refcount is 1, cursor_unref frees it before
> > > cursor_ref can increment the count.
> > >
> > > Ref the incoming cursor before unreffing the old one so the
> > > refcount goes 1-2-1 instead of 1-0 (freed) then use-after-free.
> >
> > I don't see where/how this can happen. The caller of
> > qemu_console_set_cursor should own its own reference
> > on 'cursor'. So on entry to this method, 'cursor'
> > should have a ref of 2 if it is the same as the
> > current con->cursor.
> >
> > if anything the behaviour you describe sounds like a
> > bug in a caller not holding its own reference.
>
> You are right, I thought virtio-gpu kept a weak pointer, but it should
> have a strong ref, so we should never reach 0. I can't explain the
> crash I observed then.
Is there a bug report for this or crash scenario info ?
Something wrong with the 'cursor' object stored in virtio_gpu_scanout ?
I notice in the VMState:
VMSTATE_UINT32(cursor.resource_id, struct virtio_gpu_scanout),
VMSTATE_UINT32(cursor.hot_x, struct virtio_gpu_scanout),
VMSTATE_UINT32(cursor.hot_y, struct virtio_gpu_scanout),
VMSTATE_UINT32(cursor.pos.x, struct virtio_gpu_scanout),
VMSTATE_UINT32(cursor.pos.y, struct virtio_gpu_scanout),
what is restoring the "refcount" to "1" when vmstate is loaded ?
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] ui/console: fix use-after-free in qemu_console_set_cursor
2026-08-27 10:30 ` Daniel P. Berrangé
@ 2026-08-27 10:36 ` Marc-André Lureau
2026-08-29 5:14 ` Akihiko Odaki
0 siblings, 1 reply; 6+ messages in thread
From: Marc-André Lureau @ 2026-08-27 10:36 UTC (permalink / raw)
To: Daniel P. Berrangé; +Cc: qemu-devel, akihiko.odaki
Hi
On Thu, Aug 27, 2026 at 2:31 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> On Thu, Aug 27, 2026 at 01:58:14PM +0400, Marc-André Lureau wrote:
> > Hi
> >
> > On Thu, Aug 27, 2026 at 12:47 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
> > >
> > > On Thu, Aug 27, 2026 at 11:06:47AM +0400, marcandre.lureau@redhat.com wrote:
> > > > From: Marc-André Lureau <marcandre.lureau@redhat.com>
> > > >
> > > > When the new cursor is the same object as the one already held by
> > > > the console and the refcount is 1, cursor_unref frees it before
> > > > cursor_ref can increment the count.
> > > >
> > > > Ref the incoming cursor before unreffing the old one so the
> > > > refcount goes 1-2-1 instead of 1-0 (freed) then use-after-free.
> > >
> > > I don't see where/how this can happen. The caller of
> > > qemu_console_set_cursor should own its own reference
> > > on 'cursor'. So on entry to this method, 'cursor'
> > > should have a ref of 2 if it is the same as the
> > > current con->cursor.
> > >
> > > if anything the behaviour you describe sounds like a
> > > bug in a caller not holding its own reference.
> >
> > You are right, I thought virtio-gpu kept a weak pointer, but it should
> > have a strong ref, so we should never reach 0. I can't explain the
> > crash I observed then.
>
> Is there a bug report for this or crash scenario info ?
No, I just had this report from ASAN when testing -display dbus with
virtio-gpu. Pretty regular test.
> Something wrong with the 'cursor' object stored in virtio_gpu_scanout ?
> I notice in the VMState:
>
> VMSTATE_UINT32(cursor.resource_id, struct virtio_gpu_scanout),
> VMSTATE_UINT32(cursor.hot_x, struct virtio_gpu_scanout),
> VMSTATE_UINT32(cursor.hot_y, struct virtio_gpu_scanout),
> VMSTATE_UINT32(cursor.pos.x, struct virtio_gpu_scanout),
> VMSTATE_UINT32(cursor.pos.y, struct virtio_gpu_scanout),
>
> what is restoring the "refcount" to "1" when vmstate is loaded ?
cursor != current_cursor (allocated with update_cursor on post_load)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] ui/console: fix use-after-free in qemu_console_set_cursor
2026-08-27 10:36 ` Marc-André Lureau
@ 2026-08-29 5:14 ` Akihiko Odaki
0 siblings, 0 replies; 6+ messages in thread
From: Akihiko Odaki @ 2026-08-29 5:14 UTC (permalink / raw)
To: Marc-André Lureau, Daniel P. Berrangé; +Cc: qemu-devel
On 2026/08/27 19:36, Marc-André Lureau wrote:
> Hi
>
> On Thu, Aug 27, 2026 at 2:31 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>>
>> On Thu, Aug 27, 2026 at 01:58:14PM +0400, Marc-André Lureau wrote:
>>> Hi
>>>
>>> On Thu, Aug 27, 2026 at 12:47 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>>>>
>>>> On Thu, Aug 27, 2026 at 11:06:47AM +0400, marcandre.lureau@redhat.com wrote:
>>>>> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>>>>>
>>>>> When the new cursor is the same object as the one already held by
>>>>> the console and the refcount is 1, cursor_unref frees it before
>>>>> cursor_ref can increment the count.
>>>>>
>>>>> Ref the incoming cursor before unreffing the old one so the
>>>>> refcount goes 1-2-1 instead of 1-0 (freed) then use-after-free.
>>>>
>>>> I don't see where/how this can happen. The caller of
>>>> qemu_console_set_cursor should own its own reference
>>>> on 'cursor'. So on entry to this method, 'cursor'
>>>> should have a ref of 2 if it is the same as the
>>>> current con->cursor.
>>>>
>>>> if anything the behaviour you describe sounds like a
>>>> bug in a caller not holding its own reference.
>>>
>>> You are right, I thought virtio-gpu kept a weak pointer, but it should
>>> have a strong ref, so we should never reach 0. I can't explain the
>>> crash I observed then.
>>
>> Is there a bug report for this or crash scenario info ?
>
> No, I just had this report from ASAN when testing -display dbus with
> virtio-gpu. Pretty regular test.
dbus_cursor_define() looks suspici
> @data is not modified by this function and must remain valid with an
> unchanging value until such a time as @notify is called with
> @user_data. ous; it exposes mutable cursor pixels through a
zero-copy GVariant and arranges for cursor_unref() to run when that
variant is destroyed.
The documentation of g_dbus_connection_add_filter() says "filters are
run in a dedicated message handling thread", but QEMUCursor::refcount
uses unsynchronized ++/--, which may explain your ASAN crash.
Meanwhile, virtio-gpu repeatedly mutates the same cursor, which violates
g_variant_new_from_data()’s requirement that its bytes remain unchanged
until notification. Its documentation says "if the contents of @data
change before that time then the result is undefined."
Regards,
Akihiko Odaki
>
>> Something wrong with the 'cursor' object stored in virtio_gpu_scanout ?
>> I notice in the VMState:
>>
>> VMSTATE_UINT32(cursor.resource_id, struct virtio_gpu_scanout),
>> VMSTATE_UINT32(cursor.hot_x, struct virtio_gpu_scanout),
>> VMSTATE_UINT32(cursor.hot_y, struct virtio_gpu_scanout),
>> VMSTATE_UINT32(cursor.pos.x, struct virtio_gpu_scanout),
>> VMSTATE_UINT32(cursor.pos.y, struct virtio_gpu_scanout),
>>
>> what is restoring the "refcount" to "1" when vmstate is loaded ?
>
> cursor != current_cursor (allocated with update_cursor on post_load)
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-08-29 5:15 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-27 7:06 [PATCH] ui/console: fix use-after-free in qemu_console_set_cursor marcandre.lureau
2026-08-27 8:47 ` Daniel P. Berrangé
2026-08-27 9:58 ` Marc-André Lureau
2026-08-27 10:30 ` Daniel P. Berrangé
2026-08-27 10:36 ` Marc-André Lureau
2026-08-29 5:14 ` Akihiko Odaki
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.