On 2026/01/30 3:06, Paolo Bonzini wrote:
On 1/29/26 05:41, Akihiko Odaki wrote:
However, I see another problem in struct embedding; it breaks object_ref(). When embedding, the child object effectively takes the reference to the storage of the parent object, but this reference is not counted, so use-after-free can happen if someone takes a reference to the child object with object_ref(). That is why the wrapper of object_ref() in rust/qom/src/qom.rs needs to be marked unsafe. Memory regions workaround this with memory_region_ref(), but it's not perfect since it relies on object_ref() in the end.

Yes, and in Rust the idea was to have (in addition to Owned<T> which is for an allocated object) another smart pointer Child<'a, T>: an embedded object that is owned (the parent has a reference and a field of type Child releases that reference when the parent is finalized) but cannot be cloned.

For this reason I think object_initialize(), object_initialize_child(), and the like are better to be noted as deprecated in include/qom/object.h. Then memory_region_init() can be deprecated referring to them.

This would be huge and I don't think it's feasible.

It also only provides the appearance of safety.  If you have a backwards pointer (such as the memory region's owner), you still have either a leak or the risk of a use-after-free.

Now I'm starting to recover my memory on the situation of this matter. I have actually written patches to make struct embedding safe and also deal with memory region's owner. My tree that include them can be found at:
https://gitlab.com/akihiko.odaki/qemu/-/tree/51066314fcff96303c1ad5814c3d74027855a7cb

Making struct embedding safe is done by introducing another reference counter for storage. So the reference graph will be looked like the following:

Owner -+-> Owner's storage
MR ----+

Memory region's backward references to their owning devices are invalidated when unrealizing the devices. The reasoning here is that the corner cases where devices are accessed after unrealization are unlikely to be handled properly, so they are better to be forbidden.

Users other than memory regions may still have backward pointers that are not properly tracked, so the Rust wrapper of object_ref() is still marked unsafe.

Regards,
Akihiko Odaki

Reply via email to