From 9acfd167fa80e14b7beb1eb29830cb0c7d50e586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 10 Jan 2026 21:04:20 +0100 Subject: [PATCH 1/2] std.process: add PermissionDenied to ProtectMemoryError (for OpenBSD) See EPERM notes on https://man.openbsd.org/mprotect.2. --- lib/std/process.zig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/std/process.zig b/lib/std/process.zig index 3eaffc24fe..8a3d20f776 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -1004,6 +1004,10 @@ pub fn unlockMemoryAll() UnlockMemoryError!void { pub const ProtectMemoryError = error{ UnsupportedOperation, + /// OpenBSD will refuse to change memory protection if the specified region + /// contains any pages that have previously been marked immutable using the + /// `mimmutable` function. + PermissionDenied, /// The memory cannot be given the specified access. This can happen, for /// example, if you memory map a file to which you have read-only access, /// then use `protectMemory` to mark it writable. @@ -1052,6 +1056,7 @@ pub fn protectMemory( }; switch (posix.errno(posix.system.mprotect(memory.ptr, memory.len, flags))) { .SUCCESS => return, + .PERM => return error.PermissionDenied, .INVAL => |err| return std.Io.Threaded.errnoBug(err), .ACCES => return error.AccessDenied, .NOMEM => return error.OutOfMemory, From e8a6e58f9d02657415ea2bb65364f38c9c6558cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 11 Jan 2026 03:05:44 +0100 Subject: [PATCH 2/2] std.process: fix some page size assumptions in lockMemory/protectMemory tests Makes the tests work on hexagon and loongarch. --- lib/std/process.zig | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/std/process.zig b/lib/std/process.zig index 8a3d20f776..64badc1cba 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -1066,10 +1066,11 @@ pub fn protectMemory( return error.UnsupportedOperation; } +var test_page: [std.heap.page_size_max]u8 align(std.heap.page_size_max) = undefined; + test lockMemory { - var page: [std.heap.page_size_min]u8 align(std.heap.page_size_min) = undefined; - lockMemory(&page, .{}) catch return error.SkipZigTest; - unlockMemory(&page) catch return error.SkipZigTest; + lockMemory(&test_page, .{}) catch return error.SkipZigTest; + unlockMemory(&test_page) catch return error.SkipZigTest; } test lockMemoryAll { @@ -1078,8 +1079,6 @@ test lockMemoryAll { } test protectMemory { - if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; // TODO - var page: [std.heap.page_size_min]u8 align(std.heap.page_size_min) = undefined; - protectMemory(&page, .{}) catch return error.SkipZigTest; - protectMemory(&page, .{ .read = true, .write = true }) catch return error.SkipZigTest; + protectMemory(&test_page, .{}) catch return error.SkipZigTest; + protectMemory(&test_page, .{ .read = true, .write = true }) catch return error.SkipZigTest; }