mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
std: implement os.mprotect on Windows
This commit is contained in:
parent
a9eb463202
commit
d3599ec73c
4 changed files with 60 additions and 6 deletions
|
|
@ -94,6 +94,18 @@ pub const SEEK = struct {
|
|||
pub const END = 2;
|
||||
};
|
||||
|
||||
/// Basic memory protection flags
|
||||
pub const PROT = struct {
|
||||
/// page can not be accessed
|
||||
pub const NONE = 0x0;
|
||||
/// page can be read
|
||||
pub const READ = 0x1;
|
||||
/// page can be written
|
||||
pub const WRITE = 0x2;
|
||||
/// page can be executed
|
||||
pub const EXEC = 0x4;
|
||||
};
|
||||
|
||||
pub const E = enum(u16) {
|
||||
/// No error occurred.
|
||||
SUCCESS = 0,
|
||||
|
|
|
|||
|
|
@ -4226,6 +4226,23 @@ pub const MProtectError = error{
|
|||
/// `memory.len` must be page-aligned.
|
||||
pub fn mprotect(memory: []align(mem.page_size) u8, protection: u32) MProtectError!void {
|
||||
assert(mem.isAligned(memory.len, mem.page_size));
|
||||
if (builtin.os.tag == .windows) {
|
||||
const win_prot: windows.DWORD = switch (@truncate(u3, protection)) {
|
||||
0b000 => windows.PAGE_NOACCESS,
|
||||
0b001 => windows.PAGE_READONLY,
|
||||
0b010 => unreachable, // +w -r not allowed
|
||||
0b011 => windows.PAGE_READWRITE,
|
||||
0b100 => windows.PAGE_EXECUTE,
|
||||
0b101 => windows.PAGE_EXECUTE_READ,
|
||||
0b110 => unreachable, // +w -r not allowed
|
||||
0b111 => windows.PAGE_EXECUTE_READWRITE,
|
||||
};
|
||||
var old: windows.DWORD = undefined;
|
||||
windows.VirtualProtect(memory.ptr, memory.len, win_prot, &old) catch |err| switch (err) {
|
||||
error.InvalidAddress => return error.AccessDenied,
|
||||
error.Unexpected => return error.Unexpected,
|
||||
};
|
||||
} else {
|
||||
switch (errno(system.mprotect(memory.ptr, memory.len, protection))) {
|
||||
.SUCCESS => return,
|
||||
.INVAL => unreachable,
|
||||
|
|
@ -4233,6 +4250,7 @@ pub fn mprotect(memory: []align(mem.page_size) u8, protection: u32) MProtectErro
|
|||
.NOMEM => return error.OutOfMemory,
|
||||
else => |err| return unexpectedErrno(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const ForkError = error{SystemResources} || UnexpectedError;
|
||||
|
|
|
|||
|
|
@ -1499,6 +1499,22 @@ pub fn VirtualFree(lpAddress: ?LPVOID, dwSize: usize, dwFreeType: DWORD) void {
|
|||
assert(kernel32.VirtualFree(lpAddress, dwSize, dwFreeType) != 0);
|
||||
}
|
||||
|
||||
pub const VirtualProtectError = error{
|
||||
InvalidAddress,
|
||||
Unexpected,
|
||||
};
|
||||
|
||||
pub fn VirtualProtect(lpAddress: ?LPVOID, dwSize: SIZE_T, flNewProtect: DWORD, lpflOldProtect: *DWORD) VirtualProtectError!void {
|
||||
// ntdll takes an extra level of indirection here
|
||||
var addr = lpAddress;
|
||||
var size = dwSize;
|
||||
switch (ntdll.NtProtectVirtualMemory(self_process_handle, &addr, &size, flNewProtect, lpflOldProtect)) {
|
||||
.SUCCESS => {},
|
||||
.INVALID_ADDRESS => return error.InvalidAddress,
|
||||
else => |st| return unexpectedStatus(st),
|
||||
}
|
||||
}
|
||||
|
||||
pub const VirtualQueryError = error{Unexpected};
|
||||
|
||||
pub fn VirtualQuery(lpAddress: ?LPVOID, lpBuffer: PMEMORY_BASIC_INFORMATION, dwLength: SIZE_T) VirtualQueryError!SIZE_T {
|
||||
|
|
|
|||
|
|
@ -291,3 +291,11 @@ pub extern "ntdll" fn RtlQueryRegistryValues(
|
|||
Context: ?*anyopaque,
|
||||
Environment: ?*anyopaque,
|
||||
) callconv(WINAPI) NTSTATUS;
|
||||
|
||||
pub extern "ntdll" fn NtProtectVirtualMemory(
|
||||
ProcessHandle: HANDLE,
|
||||
BaseAddress: *PVOID,
|
||||
NumberOfBytesToProtect: *ULONG,
|
||||
NewAccessProtection: ULONG,
|
||||
OldAccessProtection: *ULONG,
|
||||
) callconv(WINAPI) NTSTATUS;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue