diff mbox series

[v6,06/11] softmmu/memory: enable automatic deallocation of memory regions

Message ID 20231219075320.165227-7-ray.huang@amd.com (mailing list archive)
State New, archived
Headers show
Series Support blob memory and venus on qemu | expand

Commit Message

Huang Rui Dec. 19, 2023, 7:53 a.m. UTC
From: Xenia Ragiadakou <xenia.ragiadakou@amd.com>

When the memory region has a different life-cycle from that of her parent,
could be automatically released, once has been unparent and once all of her
references have gone away, via the object's free callback.

However, currently, the address space subsystem keeps references to the
memory region without first incrementing its object's reference count.
As a result, the automatic deallocation of the object, not taking into
account those references, results in use-after-free memory corruption.

More specifically, reference to the memory region is kept in flatview
ranges. If the reference count of the memory region is not incremented,
flatview_destroy(), that is asynchronous, may be called after memory
region's destruction. If the reference count of the memory region is
incremented, memory region's destruction will take place after
flatview_destroy() has released its references.

This patch increases the reference count of an owned memory region object
on each memory_region_ref() and decreases it on each memory_region_unref().

Signed-off-by: Xenia Ragiadakou <xenia.ragiadakou@amd.com>
Signed-off-by: Huang Rui <ray.huang@amd.com>
---

Changes in v6:
- remove in-code comment because it is confusing and explain the issue,
  that the patch attempts to fix, with more details in commit message

 system/memory.c | 2 ++
 1 file changed, 2 insertions(+)

Comments

Akihiko Odaki Dec. 21, 2023, 5:45 a.m. UTC | #1
On 2023/12/19 16:53, Huang Rui wrote:
> From: Xenia Ragiadakou <xenia.ragiadakou@amd.com>
> 
> When the memory region has a different life-cycle from that of her parent,
> could be automatically released, once has been unparent and once all of her
> references have gone away, via the object's free callback.
> 
> However, currently, the address space subsystem keeps references to the
> memory region without first incrementing its object's reference count.
> As a result, the automatic deallocation of the object, not taking into
> account those references, results in use-after-free memory corruption.
> 
> More specifically, reference to the memory region is kept in flatview
> ranges. If the reference count of the memory region is not incremented,
> flatview_destroy(), that is asynchronous, may be called after memory
> region's destruction. If the reference count of the memory region is
> incremented, memory region's destruction will take place after
> flatview_destroy() has released its references.
> 
> This patch increases the reference count of an owned memory region object
> on each memory_region_ref() and decreases it on each memory_region_unref().

Why not pass the memory region itself as the owner parameter of 
memory_region_init_ram_ptr()?
Xenia Ragiadakou Dec. 21, 2023, 7:35 a.m. UTC | #2
On 21/12/23 07:45, Akihiko Odaki wrote:
> On 2023/12/19 16:53, Huang Rui wrote:
>> From: Xenia Ragiadakou <xenia.ragiadakou@amd.com>
>>
>> When the memory region has a different life-cycle from that of her 
>> parent,
>> could be automatically released, once has been unparent and once all 
>> of her
>> references have gone away, via the object's free callback.
>>
>> However, currently, the address space subsystem keeps references to the
>> memory region without first incrementing its object's reference count.
>> As a result, the automatic deallocation of the object, not taking into
>> account those references, results in use-after-free memory corruption.
>>
>> More specifically, reference to the memory region is kept in flatview
>> ranges. If the reference count of the memory region is not incremented,
>> flatview_destroy(), that is asynchronous, may be called after memory
>> region's destruction. If the reference count of the memory region is
>> incremented, memory region's destruction will take place after
>> flatview_destroy() has released its references.
>>
>> This patch increases the reference count of an owned memory region object
>> on each memory_region_ref() and decreases it on each 
>> memory_region_unref().
> 
> Why not pass the memory region itself as the owner parameter of 
> memory_region_init_ram_ptr()?

Hmm, in that case, how will it be guaranteed that the VirtIOGPU won't 
disappear while the memory region is still in use?
Akihiko Odaki Dec. 21, 2023, 7:50 a.m. UTC | #3
On 2023/12/21 16:35, Xenia Ragiadakou wrote:
> 
> On 21/12/23 07:45, Akihiko Odaki wrote:
>> On 2023/12/19 16:53, Huang Rui wrote:
>>> From: Xenia Ragiadakou <xenia.ragiadakou@amd.com>
>>>
>>> When the memory region has a different life-cycle from that of her 
>>> parent,
>>> could be automatically released, once has been unparent and once all 
>>> of her
>>> references have gone away, via the object's free callback.
>>>
>>> However, currently, the address space subsystem keeps references to the
>>> memory region without first incrementing its object's reference count.
>>> As a result, the automatic deallocation of the object, not taking into
>>> account those references, results in use-after-free memory corruption.
>>>
>>> More specifically, reference to the memory region is kept in flatview
>>> ranges. If the reference count of the memory region is not incremented,
>>> flatview_destroy(), that is asynchronous, may be called after memory
>>> region's destruction. If the reference count of the memory region is
>>> incremented, memory region's destruction will take place after
>>> flatview_destroy() has released its references.
>>>
>>> This patch increases the reference count of an owned memory region 
>>> object
>>> on each memory_region_ref() and decreases it on each 
>>> memory_region_unref().
>>
>> Why not pass the memory region itself as the owner parameter of 
>> memory_region_init_ram_ptr()?
> 
> Hmm, in that case, how will it be guaranteed that the VirtIOGPU won't 
> disappear while the memory region is still in use?

You can object_ref() when you do memory_region_init_ram_ptr() and 
object_unref() when the memory region is being destroyed.
Xenia Ragiadakou Dec. 21, 2023, 8:32 a.m. UTC | #4
On 21/12/23 09:50, Akihiko Odaki wrote:
> On 2023/12/21 16:35, Xenia Ragiadakou wrote:
>>
>> On 21/12/23 07:45, Akihiko Odaki wrote:
>>> On 2023/12/19 16:53, Huang Rui wrote:
>>>> From: Xenia Ragiadakou <xenia.ragiadakou@amd.com>
>>>>
>>>> When the memory region has a different life-cycle from that of her 
>>>> parent,
>>>> could be automatically released, once has been unparent and once all 
>>>> of her
>>>> references have gone away, via the object's free callback.
>>>>
>>>> However, currently, the address space subsystem keeps references to the
>>>> memory region without first incrementing its object's reference count.
>>>> As a result, the automatic deallocation of the object, not taking into
>>>> account those references, results in use-after-free memory corruption.
>>>>
>>>> More specifically, reference to the memory region is kept in flatview
>>>> ranges. If the reference count of the memory region is not incremented,
>>>> flatview_destroy(), that is asynchronous, may be called after memory
>>>> region's destruction. If the reference count of the memory region is
>>>> incremented, memory region's destruction will take place after
>>>> flatview_destroy() has released its references.
>>>>
>>>> This patch increases the reference count of an owned memory region 
>>>> object
>>>> on each memory_region_ref() and decreases it on each 
>>>> memory_region_unref().
>>>
>>> Why not pass the memory region itself as the owner parameter of 
>>> memory_region_init_ram_ptr()?
>>
>> Hmm, in that case, how will it be guaranteed that the VirtIOGPU won't 
>> disappear while the memory region is still in use?
> 
> You can object_ref() when you do memory_region_init_ram_ptr() and 
> object_unref() when the memory region is being destroyed.

It is not very intuitive but I see your point. This change is quite 
intrusive and has little use. I think it can be worked around in the way 
you suggest.
diff mbox series

Patch

diff --git a/system/memory.c b/system/memory.c
index 304fa843ea..4d5e7e7a4c 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -1824,6 +1824,7 @@  void memory_region_ref(MemoryRegion *mr)
      * we do not ref/unref them because it slows down DMA sensibly.
      */
     if (mr && mr->owner) {
+        object_ref(OBJECT(mr));
         object_ref(mr->owner);
     }
 }
@@ -1832,6 +1833,7 @@  void memory_region_unref(MemoryRegion *mr)
 {
     if (mr && mr->owner) {
         object_unref(mr->owner);
+        object_unref(OBJECT(mr));
     }
 }