feat(libkernel): implement POSIX mprotect
mprotect changes the protection of guest memory through the same path as sceKernelMprotect and reports failures through errno: EINVAL for a null or overflowing range or a range the allocation tracker rejects, ENOMEM when allocation fails. A zero length succeeds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
7a178e2276
commit
35ae8742a9
|
|
@ -78,4 +78,23 @@ int APS5_VABI munmap_nid_postfix(void* address, std::size_t length) noexcept {
|
|||
}
|
||||
}
|
||||
|
||||
int APS5_VABI mprotect_nid_postfix(void* address, std::size_t length, int protection) noexcept {
|
||||
const auto failed = [](int error) {
|
||||
SetError(error);
|
||||
return -1;
|
||||
};
|
||||
const auto start = reinterpret_cast<std::uintptr_t>(address);
|
||||
if (length == 0) return 0;
|
||||
if (start == 0 || length > std::numeric_limits<std::uintptr_t>::max() - start)
|
||||
return failed(GuestInvalid);
|
||||
try {
|
||||
if (DoMprotect(address, length, protection) != 0) return failed(GuestInvalid);
|
||||
return 0;
|
||||
} catch (const std::bad_alloc&) {
|
||||
return failed(GuestNoMemory);
|
||||
} catch (const std::exception&) {
|
||||
return failed(GuestInvalid);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
extern "C" {
|
||||
void* APS5_VABI mmap_nid_postfix(void*, std::size_t, int, int, int, std::int64_t) noexcept;
|
||||
int APS5_VABI munmap_nid_postfix(void*, std::size_t) noexcept;
|
||||
int APS5_VABI mprotect_nid_postfix(void*, std::size_t, int) noexcept;
|
||||
int* APS5_VABI __error_nid_postfix();
|
||||
int APS5_VABI sceKernelMapNamedFlexibleMemory(void**, std::size_t, int, int, const char*);
|
||||
int APS5_VABI sceKernelMapNamedFlexibleMemoryInternal(void**, std::size_t, int, int, const char*);
|
||||
|
|
@ -1099,6 +1100,20 @@ int main() {
|
|||
const auto range = mutation.Find(memory);
|
||||
Require(range.bytes == page * 3 && range.readable && range.writable);
|
||||
}
|
||||
Require(mprotect_nid_postfix(memory, 0, 1) == 0);
|
||||
Require(mprotect_nid_postfix(nullptr, page, 1) == -1 && *__error_nid_postfix() == 22);
|
||||
Require(mprotect_nid_postfix(memory + 1, 1, 1) == 0);
|
||||
{
|
||||
GuestAllocations::Mutation mutation;
|
||||
const auto range = mutation.Find(memory);
|
||||
Require(range.readable && !range.writable);
|
||||
}
|
||||
Require(memory[0] == 42);
|
||||
Require(mprotect_nid_postfix(memory, page, 3) == 0);
|
||||
{
|
||||
GuestAllocations::Mutation mutation;
|
||||
Require(mutation.Find(memory).writable);
|
||||
}
|
||||
Require(munmap_nid_postfix(memory + 1, page) == -1 && *__error_nid_postfix() == 22);
|
||||
Require(munmap_nid_postfix(memory, 0) == -1 && *__error_nid_postfix() == 22);
|
||||
Require(memory[0] == 42);
|
||||
|
|
|
|||
Loading…
Reference in New Issue