[PATCH v2] virtio-gpu-virgl: correct parent for blob memory region

Joelle van Dyne posted 1 patch 4 weeks, 1 day ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20251223184023.1913-1-j@getutm.app
Maintainers: "Alex Bennée" <alex.bennee@linaro.org>, Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>, Dmitry Osipenko <dmitry.osipenko@collabora.com>, "Michael S. Tsirkin" <mst@redhat.com>
There is a newer version of this series
hw/display/virtio-gpu-virgl.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
[PATCH v2] virtio-gpu-virgl: correct parent for blob memory region
Posted by Joelle van Dyne 4 weeks, 1 day ago
When `owner` == `mr`, `object_unparent` will crash:

object_unparent(mr) ->
object_property_del_child(mr, mr) ->
object_finalize_child_property(mr, name, mr) ->
object_unref(mr) ->
object_finalize(mr) ->
object_property_del_all(mr) ->
object_finalize_child_property(mr, name, mr) ->
object_unref(mr) ->
fail on g_assert(obj->ref > 0)

However, passing a different `owner` to `memory_region_init` is not
enough. `memory_region_ref` has an optimization where it takes a ref
only on the owner. It specifically warns against calling unparent on
the memory region. So we initialize the memory region first and then
patch in the owner with itself.

Signed-off-by: Joelle van Dyne <j@getutm.app>
---
 hw/display/virtio-gpu-virgl.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 18404be5892..70e0aff0ca3 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -123,7 +123,8 @@ virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,
     vmr->g = g;
 
     mr = &vmr->mr;
-    memory_region_init_ram_ptr(mr, OBJECT(mr), "blob", size, data);
+    memory_region_init_ram_ptr(mr, OBJECT(g), "blob", size, data);
+    mr->owner = OBJECT(mr);
     memory_region_add_subregion(&b->hostmem, offset, mr);
     memory_region_set_enabled(mr, true);
 
-- 
2.50.1 (Apple Git-155)
Re: [PATCH v2] virtio-gpu-virgl: correct parent for blob memory region
Posted by Akihiko Odaki 4 weeks ago
On 2025/12/24 3:40, Joelle van Dyne wrote:
> When `owner` == `mr`, `object_unparent` will crash:
> 
> object_unparent(mr) ->
> object_property_del_child(mr, mr) ->
> object_finalize_child_property(mr, name, mr) ->
> object_unref(mr) ->
> object_finalize(mr) ->
> object_property_del_all(mr) ->
> object_finalize_child_property(mr, name, mr) ->
> object_unref(mr) ->
> fail on g_assert(obj->ref > 0)
> 
> However, passing a different `owner` to `memory_region_init` is not
> enough. `memory_region_ref` has an optimization where it takes a ref
> only on the owner. It specifically warns against calling unparent on
> the memory region. So we initialize the memory region first and then
> patch in the owner with itself.

Patching outside system/memory.c can be fragile.

I think an object is being a child of itself, which doesn't make sense. 
This can be avoided by passing NULL as name. The object will be an 
orphan so it will have to be freed with object_unref() instead of 
object_unparent().

Regards,
Akihiko Odaki
Re: [PATCH v2] virtio-gpu-virgl: correct parent for blob memory region
Posted by Joelle van Dyne 4 weeks ago
On Tue, Dec 23, 2025 at 9:32 PM Akihiko Odaki
<odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
>
> On 2025/12/24 3:40, Joelle van Dyne wrote:
> > When `owner` == `mr`, `object_unparent` will crash:
> >
> > object_unparent(mr) ->
> > object_property_del_child(mr, mr) ->
> > object_finalize_child_property(mr, name, mr) ->
> > object_unref(mr) ->
> > object_finalize(mr) ->
> > object_property_del_all(mr) ->
> > object_finalize_child_property(mr, name, mr) ->
> > object_unref(mr) ->
> > fail on g_assert(obj->ref > 0)
> >
> > However, passing a different `owner` to `memory_region_init` is not
> > enough. `memory_region_ref` has an optimization where it takes a ref
> > only on the owner. It specifically warns against calling unparent on
> > the memory region. So we initialize the memory region first and then
> > patch in the owner with itself.
>
> Patching outside system/memory.c can be fragile.
>
> I think an object is being a child of itself, which doesn't make sense.
> This can be avoided by passing NULL as name. The object will be an
> orphan so it will have to be freed with object_unref() instead of
> object_unparent().
I didn't want to break anything unintentionally and wanted to be safe
by making the change as close to the original logic as possible
(having introduced a UAF in v1 after making a one line change). Maybe
Antonio or Robert can give more insight on the intention of using self
as owner and if making it an orphan is acceptable?

>
> Regards,
> Akihiko Odaki
Re: [PATCH v2] virtio-gpu-virgl: correct parent for blob memory region
Posted by Akihiko Odaki 4 weeks ago
On 2025/12/24 16:46, Joelle van Dyne wrote:
> On Tue, Dec 23, 2025 at 9:32 PM Akihiko Odaki
> <odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
>>
>> On 2025/12/24 3:40, Joelle van Dyne wrote:
>>> When `owner` == `mr`, `object_unparent` will crash:
>>>
>>> object_unparent(mr) ->
>>> object_property_del_child(mr, mr) ->
>>> object_finalize_child_property(mr, name, mr) ->
>>> object_unref(mr) ->
>>> object_finalize(mr) ->
>>> object_property_del_all(mr) ->
>>> object_finalize_child_property(mr, name, mr) ->
>>> object_unref(mr) ->
>>> fail on g_assert(obj->ref > 0)
>>>
>>> However, passing a different `owner` to `memory_region_init` is not
>>> enough. `memory_region_ref` has an optimization where it takes a ref
>>> only on the owner. It specifically warns against calling unparent on
>>> the memory region. So we initialize the memory region first and then
>>> patch in the owner with itself.
>>
>> Patching outside system/memory.c can be fragile.
>>
>> I think an object is being a child of itself, which doesn't make sense.
>> This can be avoided by passing NULL as name. The object will be an
>> orphan so it will have to be freed with object_unref() instead of
>> object_unparent().
> I didn't want to break anything unintentionally and wanted to be safe
> by making the change as close to the original logic as possible
> (having introduced a UAF in v1 after making a one line change). Maybe
> Antonio or Robert can give more insight on the intention of using self
> as owner and if making it an orphan is acceptable?

The intention here is that the reference counting of memory regions 
independent of the device. If you make the device owner, the reference 
counter of the device will be used for memory region (see
memory_region_ref()). But this memory region can go away while the 
device stays, so its reference counting needs to be done independently.

By making the memory region itself owner, the reference counter of the 
memory region itself will be used, just like normal objects.

So the owner needs to be the memory region itself. But it is not 
necessary to have the parent/child relationship, and passing NULL as 
name only removes the relationship.

Regards,
Akihiko Odaki