qemu-user MAP_SHARED TB invalidation
Like the QEMU's TCG JIT, the .NET's CoreCLR JIT implements the RX/WX page splitting. With .NET 8 it's on by default, and this is causing a rich variety of hard-to-debug crashes when running .NET apps with qemu-user. export DOTNET_EnableWriteXorExecute=0
makes the crashes go away.
Here is a minimal testcase demonstrating the problem: iii-i/qemu@5d15a972
It boils down to TCG not being notified of the updates made to the RW mapping.
One possible solution would be to explicitly track aliased mappings.
Alias information can be used by page_protect()
as follows:
- Look up the associated mapping in an
IntervalTree
. The lookup result should contain a file object. - Iterate over all mappings associated with the file object using an intrusive list.
- Protect page aliases, if they are present, within each mapping.
Similarly, page_unprotect()
should loop over all aliases, adjusting flags and invalidating TBs.
Alias information should be updated on a successful mmap(MAP_SHARED)
/ munmap()
/ mremap()
.
File objects can be stored in a g_hash_table keyed by st_dev
+ st_ino
.
These can be found using either fstat()
(racy) or /proc/self/maps
(slow).
I vaguely remember that some virtual file systems provide bogus inodes. I would say we should ignore these.
File objects should be reference counted.
Once the reference count drops to 0, both file object and g_hash_table entry should be removed.
I'm not sure if putting this information into pageflags_root
would be a good idea.
Perhaps a separate IntervalTree
should be defined.
Everything goes under mmap_lock()
.
Is there an easier way?