authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2022-12-22 13:41:05+00:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-20 03:33:35+02:00
logd3599ec73cc07692c2579a8cf7151c918eea525f
tree1977456fd9b813cb60e7b3ea12842435f725144d
parenta9eb463202f46f6190f57c3b9a5c4913d6c5d6c5

std: implement os.mprotect on Windows


4 files changed, 60 insertions(+), 6 deletions(-)

lib/std/c/windows.zig+12
...@@ -94,6 +94,18 @@ pub const SEEK = struct {...@@ -94,6 +94,18 @@ pub const SEEK = struct {
94 pub const END = 2;94 pub const END = 2;
95};95};
9696
97/// Basic memory protection flags
98pub const PROT = struct {
99 /// page can not be accessed
100 pub const NONE = 0x0;
101 /// page can be read
102 pub const READ = 0x1;
103 /// page can be written
104 pub const WRITE = 0x2;
105 /// page can be executed
106 pub const EXEC = 0x4;
107};
108
97pub const E = enum(u16) {109pub const E = enum(u16) {
98 /// No error occurred.110 /// No error occurred.
99 SUCCESS = 0,111 SUCCESS = 0,
lib/std/os.zig+24-6
...@@ -4226,12 +4226,30 @@ pub const MProtectError = error{...@@ -4226,12 +4226,30 @@ pub const MProtectError = error{
4226/// `memory.len` must be page-aligned.4226/// `memory.len` must be page-aligned.
4227pub fn mprotect(memory: []align(mem.page_size) u8, protection: u32) MProtectError!void {4227pub fn mprotect(memory: []align(mem.page_size) u8, protection: u32) MProtectError!void {
4228 assert(mem.isAligned(memory.len, mem.page_size));4228 assert(mem.isAligned(memory.len, mem.page_size));
4229 switch (errno(system.mprotect(memory.ptr, memory.len, protection))) {4229 if (builtin.os.tag == .windows) {
4230 .SUCCESS => return,4230 const win_prot: windows.DWORD = switch (@truncate(u3, protection)) {
4231 .INVAL => unreachable,4231 0b000 => windows.PAGE_NOACCESS,
4232 .ACCES => return error.AccessDenied,4232 0b001 => windows.PAGE_READONLY,
4233 .NOMEM => return error.OutOfMemory,4233 0b010 => unreachable, // +w -r not allowed
4234 else => |err| return unexpectedErrno(err),4234 0b011 => windows.PAGE_READWRITE,
4235 0b100 => windows.PAGE_EXECUTE,
4236 0b101 => windows.PAGE_EXECUTE_READ,
4237 0b110 => unreachable, // +w -r not allowed
4238 0b111 => windows.PAGE_EXECUTE_READWRITE,
4239 };
4240 var old: windows.DWORD = undefined;
4241 windows.VirtualProtect(memory.ptr, memory.len, win_prot, &old) catch |err| switch (err) {
4242 error.InvalidAddress => return error.AccessDenied,
4243 error.Unexpected => return error.Unexpected,
4244 };
4245 } else {
4246 switch (errno(system.mprotect(memory.ptr, memory.len, protection))) {
4247 .SUCCESS => return,
4248 .INVAL => unreachable,
4249 .ACCES => return error.AccessDenied,
4250 .NOMEM => return error.OutOfMemory,
4251 else => |err| return unexpectedErrno(err),
4252 }
4235 }4253 }
4236}4254}
42374255
lib/std/os/windows.zig+16
...@@ -1499,6 +1499,22 @@ pub fn VirtualFree(lpAddress: ?LPVOID, dwSize: usize, dwFreeType: DWORD) void {...@@ -1499,6 +1499,22 @@ pub fn VirtualFree(lpAddress: ?LPVOID, dwSize: usize, dwFreeType: DWORD) void {
1499 assert(kernel32.VirtualFree(lpAddress, dwSize, dwFreeType) != 0);1499 assert(kernel32.VirtualFree(lpAddress, dwSize, dwFreeType) != 0);
1500}1500}
15011501
1502pub const VirtualProtectError = error{
1503 InvalidAddress,
1504 Unexpected,
1505};
1506
1507pub fn VirtualProtect(lpAddress: ?LPVOID, dwSize: SIZE_T, flNewProtect: DWORD, lpflOldProtect: *DWORD) VirtualProtectError!void {
1508 // ntdll takes an extra level of indirection here
1509 var addr = lpAddress;
1510 var size = dwSize;
1511 switch (ntdll.NtProtectVirtualMemory(self_process_handle, &addr, &size, flNewProtect, lpflOldProtect)) {
1512 .SUCCESS => {},
1513 .INVALID_ADDRESS => return error.InvalidAddress,
1514 else => |st| return unexpectedStatus(st),
1515 }
1516}
1517
1502pub const VirtualQueryError = error{Unexpected};1518pub const VirtualQueryError = error{Unexpected};
15031519
1504pub fn VirtualQuery(lpAddress: ?LPVOID, lpBuffer: PMEMORY_BASIC_INFORMATION, dwLength: SIZE_T) VirtualQueryError!SIZE_T {1520pub fn VirtualQuery(lpAddress: ?LPVOID, lpBuffer: PMEMORY_BASIC_INFORMATION, dwLength: SIZE_T) VirtualQueryError!SIZE_T {
lib/std/os/windows/ntdll.zig+8
...@@ -291,3 +291,11 @@ pub extern "ntdll" fn RtlQueryRegistryValues(...@@ -291,3 +291,11 @@ pub extern "ntdll" fn RtlQueryRegistryValues(
291 Context: ?*anyopaque,291 Context: ?*anyopaque,
292 Environment: ?*anyopaque,292 Environment: ?*anyopaque,
293) callconv(WINAPI) NTSTATUS;293) callconv(WINAPI) NTSTATUS;
294
295pub extern "ntdll" fn NtProtectVirtualMemory(
296 ProcessHandle: HANDLE,
297 BaseAddress: *PVOID,
298 NumberOfBytesToProtect: *ULONG,
299 NewAccessProtection: ULONG,
300 OldAccessProtection: *ULONG,
301) callconv(WINAPI) NTSTATUS;