diff options
Diffstat (limited to 'kernel_api/sys_mman_emulation.cc')
-rw-r--r-- | kernel_api/sys_mman_emulation.cc | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/kernel_api/sys_mman_emulation.cc b/kernel_api/sys_mman_emulation.cc index 61ad88e6..63249efd 100644 --- a/kernel_api/sys_mman_emulation.cc +++ b/kernel_api/sys_mman_emulation.cc @@ -20,6 +20,8 @@ #include <cerrno> +#include "berberis/base/mmap.h" +#include "berberis/base/prctl_helpers.h" #include "berberis/base/tracing.h" #include "berberis/guest_os_primitives/guest_map_shadow.h" #include "berberis/guest_state/guest_addr.h" @@ -36,10 +38,23 @@ int ToHostProt(int guest_prot) { return guest_prot; } +// Clobbers errno. void UpdateGuestProt(int guest_prot, void* addr, size_t length) { GuestAddr guest_addr = ToGuestAddr(addr); GuestMapShadow* shadow = GuestMapShadow::GetInstance(); if (guest_prot & PROT_EXEC) { + // Since we strip guest executable bit from host mappings kernel may merge r-- and r-x guest + // mappings together, which is difficult to split back when emulating /proc/self/maps. Setting + // region name helps to prevent regions merging. It helps even if it's a file backed mapping, + // even though filename isn't visibly changed in /proc/self/maps in this case. + // Note that this name can be overridden by the app, which is fine as long as it's + // unique for this mapping. We do not remove this name if executable bit is + // removed which also should be fine since it's just a hint. + int res = SetVmaAnonName(addr, AlignUpPageSize(length), "[guest exec mapping hint]"); + if (res == -1) { + TRACE("PR_SET_VMA_ANON_NAME failed with errno=%s", std::strerror(errno)); + } + shadow->SetExecutable(guest_addr, length); } else { shadow->ClearExecutable(guest_addr, length); |