Currently, there is no way to atomically remap a memory range to the same physical pages as an existing one. A process wanting to do this must:
- Iterate through all areas in the range they want to remap using
area_for
andget_area_info
. - Map/reserve a memory region large enough to hold all concerned areas, including the unwanted head/tails.
- Iterate through all the related areas once again. For each area, calculate the target address in the newly reserved region, unmap it, and then call
clone_area
to the target address. - Unmap the unwanted head/tails, if any.
This process is vulnerable to race conditions when other threads call any kind of memory management syscalls, including resize_area
, delete_area
, unmap_memory
,… on the target.
I therefore propose a new syscall:
extern area_id _kern_remap_memory(const char *name, team_id targetTeam, void **address,
uint32 addressSpec, size_t size, uint32 protection,
bool unmapAddressRange,
team_id sourceTeam, void* sourceAddress);
To do this, the caller must have an euid
of 0 or the same euid
as the euid
of both targetTeam
and sourceTeam
.
This syscall, if added, would serve a variety of use cases, from remapping arbitrary ranges of memory with different protections, to quickly performing IPC through shared memory (this should be a more powerful version of clone_area
and _kern_transfer_area
combined).
It would not introduce any security issues since any malware with the privilege mentioned above can already use install_team_debugger
and access the victim’s address space as it please.
What do you think?