Skip to content

Commit

Permalink
mem/virtual: specify max protection on mmap call in NetBSD and FreeBSD
Browse files Browse the repository at this point in the history
  • Loading branch information
laytan committed Feb 18, 2025
1 parent ae0f69f commit cae3f13
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 24 deletions.
20 changes: 20 additions & 0 deletions core/mem/virtual/virtual_darwin.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package mem_virtual

import "core:sys/posix"

_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
result := posix.mmap(nil, size, {}, {.ANONYMOUS, .PRIVATE})
if result == posix.MAP_FAILED {
assert_contextless(posix.errno() == .ENOMEM)
return nil, .Out_Of_Memory
}

return ([^]byte)(uintptr(result))[:size], nil
}

_decommit :: proc "contextless" (data: rawptr, size: uint) {
MADV_FREE :: 5

posix.mprotect(data, size, {})
posix.posix_madvise(data, size, transmute(posix.MAdvice)i32(MADV_FREE))
}
26 changes: 26 additions & 0 deletions core/mem/virtual/virtual_freebsd.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package mem_virtual

import "core:sys/posix"

_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {

PROT_MAX :: proc "contextless" (flags: posix.Prot_Flags) -> posix.Prot_Flags {
_PROT_MAX_SHIFT :: 16
return transmute(posix.Prot_Flags)(transmute(i32)flags << _PROT_MAX_SHIFT)
}

result := posix.mmap(nil, size, PROT_MAX({.READ, .WRITE, .EXEC}), {.ANONYMOUS, .PRIVATE})
if result == posix.MAP_FAILED {
assert_contextless(posix.errno() == .ENOMEM)
return nil, .Out_Of_Memory
}

return ([^]byte)(uintptr(result))[:size], nil
}

_decommit :: proc "contextless" (data: rawptr, size: uint) {
MADV_FREE :: 5

posix.mprotect(data, size, {})
posix.posix_madvise(data, size, transmute(posix.MAdvice)i32(MADV_FREE))
}
25 changes: 25 additions & 0 deletions core/mem/virtual/virtual_netbsd.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package mem_virtual

import "core:sys/posix"

_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {

PROT_MPROTECT :: proc "contextless" (flags: posix.Prot_Flags) -> posix.Prot_Flags {
return transmute(posix.Prot_Flags)(transmute(i32)flags << 3)
}

result := posix.mmap(nil, size, PROT_MPROTECT({.READ, .WRITE, .EXEC}), {.ANONYMOUS, .PRIVATE})
if result == posix.MAP_FAILED {
assert_contextless(posix.errno() == .ENOMEM)
return nil, .Out_Of_Memory
}

return ([^]byte)(uintptr(result))[:size], nil
}

_decommit :: proc "contextless" (data: rawptr, size: uint) {
MADV_FREE :: 6

posix.mprotect(data, size, {})
posix.posix_madvise(data, size, transmute(posix.MAdvice)i32(MADV_FREE))
}
20 changes: 20 additions & 0 deletions core/mem/virtual/virtual_openbsd.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package mem_virtual

import "core:sys/posix"

_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
result := posix.mmap(nil, size, {}, {.ANONYMOUS, .PRIVATE})
if result == posix.MAP_FAILED {
assert_contextless(posix.errno() == .ENOMEM)
return nil, .Out_Of_Memory
}

return ([^]byte)(uintptr(result))[:size], nil
}

_decommit :: proc "contextless" (data: rawptr, size: uint) {
MADV_FREE :: 6

posix.mprotect(data, size, {})
posix.posix_madvise(data, size, transmute(posix.MAdvice)i32(MADV_FREE))
}
4 changes: 3 additions & 1 deletion core/mem/virtual/virtual_platform.odin
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ platform_memory_alloc :: proc "contextless" (to_commit, to_reserve: uint) -> (bl
to_commit = clamp(to_commit, size_of(Platform_Memory_Block), total_to_reserved)

data := reserve(total_to_reserved) or_return
commit(raw_data(data), to_commit)

commit_err := commit(raw_data(data), to_commit)
assert_contextless(commit_err == nil)

block = (^Platform_Memory_Block)(raw_data(data))
block.committed = to_commit
Expand Down
28 changes: 5 additions & 23 deletions core/mem/virtual/virtual_posix.odin
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,18 @@ package mem_virtual

import "core:sys/posix"

// Define non-posix needed flags:
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD {
MADV_FREE :: 5 /* pages unneeded, discard contents */
} else when ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD {
MADV_FREE :: 6
}

_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
flags := posix.Map_Flags{ .ANONYMOUS, .PRIVATE }
result := posix.mmap(nil, size, {}, flags)
if result == posix.MAP_FAILED {
return nil, .Out_Of_Memory
}

return ([^]byte)(uintptr(result))[:size], nil
}

_commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error {
if posix.mprotect(data, size, { .READ, .WRITE }) != .OK {
return .Out_Of_Memory
#partial switch posix.errno() {
case .EACCES, .EPERM: return .Invalid_Pointer
case .ENOTSUP, .EINVAL: return .Invalid_Argument
case: return .Out_Of_Memory
}
}

return nil
}

_decommit :: proc "contextless" (data: rawptr, size: uint) {
posix.mprotect(data, size, {})
posix.posix_madvise(data, size, transmute(posix.MAdvice)i32(MADV_FREE))
}

_release :: proc "contextless" (data: rawptr, size: uint) {
posix.munmap(data, size)
}
Expand Down

0 comments on commit cae3f13

Please sign in to comment.