From f1d12c330eab79aa9403cdd11fbc44a8be41247f Mon Sep 17 00:00:00 2001 From: Bananymous Date: Mon, 10 Nov 2025 03:52:33 +0200 Subject: [PATCH] Kernel/LibC: Implement MMAP_FIXED_NOREPLACE This is a handy thing from linux Also fix MMAP_FIXED validation and error reporting --- kernel/include/kernel/Memory/MemoryRegion.h | 1 + kernel/kernel/Memory/MemoryRegion.cpp | 5 ++ kernel/kernel/Process.cpp | 17 ++++--- userspace/libraries/LibC/include/sys/mman.h | 55 +++++++++++---------- 4 files changed, 45 insertions(+), 33 deletions(-) diff --git a/kernel/include/kernel/Memory/MemoryRegion.h b/kernel/include/kernel/Memory/MemoryRegion.h index 59a9782e..20df478c 100644 --- a/kernel/include/kernel/Memory/MemoryRegion.h +++ b/kernel/include/kernel/Memory/MemoryRegion.h @@ -33,6 +33,7 @@ namespace Kernel bool contains(vaddr_t address) const; bool contains_fully(vaddr_t address, size_t size) const; bool overlaps(vaddr_t address, size_t size) const; + bool is_contained_by(vaddr_t address, size_t size) const; bool writable() const { return m_flags & PageTable::Flags::ReadWrite; } diff --git a/kernel/kernel/Memory/MemoryRegion.cpp b/kernel/kernel/Memory/MemoryRegion.cpp index 8741c6c1..3bcda4ea 100644 --- a/kernel/kernel/Memory/MemoryRegion.cpp +++ b/kernel/kernel/Memory/MemoryRegion.cpp @@ -50,6 +50,11 @@ namespace Kernel return true; } + bool MemoryRegion::is_contained_by(vaddr_t address, size_t size) const + { + return address <= m_vaddr && m_vaddr + m_size <= address + size; + } + BAN::ErrorOr MemoryRegion::mprotect(PageTable::flags_t new_page_flags) { if (m_flags == new_page_flags) diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index f16955d9..19c762b1 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -2221,28 +2221,33 @@ namespace Kernel LockGuard _(m_process_lock); AddressRange address_range { .start = 0x400000, .end = USERSPACE_END }; - if (args.flags & MAP_FIXED) + if (args.flags & (MAP_FIXED | MAP_FIXED_NOREPLACE)) { const vaddr_t vaddr = reinterpret_cast(args.addr); - if (vaddr % PAGE_SIZE) + if (vaddr == 0 || vaddr % PAGE_SIZE) return BAN::Error::from_errno(EINVAL); + if (!PageTable::is_valid_pointer(vaddr)) + return BAN::Error::from_errno(ENOMEM); + if (!PageTable::is_valid_pointer(vaddr + args.len)) + return BAN::Error::from_errno(ENOMEM); address_range = { .start = vaddr, .end = vaddr + args.len, }; - for (size_t i = 0; i < m_mapped_regions.size(); i++) + if (args.flags & MAP_FIXED_NOREPLACE) + ; + else for (size_t i = 0; i < m_mapped_regions.size(); i++) { if (!m_mapped_regions[i]->overlaps(vaddr, args.len)) continue; - if (!m_mapped_regions[i]->contains_fully(vaddr, args.len)) + if (!m_mapped_regions[i]->is_contained_by(vaddr, args.len)) derrorln("VERY BROKEN MAP_FIXED UNMAP"); m_mapped_regions[i]->wait_not_pinned(); m_mapped_regions.remove(i--); } } - - if (const vaddr_t vaddr = reinterpret_cast(args.addr); vaddr == 0) + else if (const vaddr_t vaddr = reinterpret_cast(args.addr); vaddr == 0) ; else if (vaddr % PAGE_SIZE) ; diff --git a/userspace/libraries/LibC/include/sys/mman.h b/userspace/libraries/LibC/include/sys/mman.h index 19420bee..b459b5a8 100644 --- a/userspace/libraries/LibC/include/sys/mman.h +++ b/userspace/libraries/LibC/include/sys/mman.h @@ -7,41 +7,42 @@ __BEGIN_DECLS -#define PROT_EXEC 0x01 -#define PROT_NONE 0x02 -#define PROT_READ 0x04 -#define PROT_WRITE 0x08 +#define PROT_EXEC 0x01 +#define PROT_NONE 0x02 +#define PROT_READ 0x04 +#define PROT_WRITE 0x08 -#define MAP_FIXED 0x01 -#define MAP_PRIVATE 0x02 -#define MAP_SHARED 0x04 -#define MAP_ANONYMOUS 0x08 -#define MAP_ANON MAP_ANONYMOUS +#define MAP_FIXED 0x01 +#define MAP_PRIVATE 0x02 +#define MAP_SHARED 0x04 +#define MAP_ANONYMOUS 0x08 +#define MAP_ANON MAP_ANONYMOUS +#define MAP_FIXED_NOREPLACE 0x10 -#define MS_ASYNC 0x01 -#define MS_INVALIDATE 0x02 -#define MS_SYNC 0x04 +#define MS_ASYNC 0x01 +#define MS_INVALIDATE 0x02 +#define MS_SYNC 0x04 -#define MCL_CURRENT 0x01 -#define MCL_FUTURE 0x01 +#define MCL_CURRENT 0x01 +#define MCL_FUTURE 0x01 #define MAP_FAILED ((void*)0) -#define POSIX_MADV_DONTNEED 1 -#define POSIX_MADV_NORMAL 2 -#define POSIX_MADV_RANDOM 3 -#define POSIX_MADV_SEQUENTIAL 4 -#define POSIX_MADV_WILLNEED 5 +#define POSIX_MADV_DONTNEED 1 +#define POSIX_MADV_NORMAL 2 +#define POSIX_MADV_RANDOM 3 +#define POSIX_MADV_SEQUENTIAL 4 +#define POSIX_MADV_WILLNEED 5 -#define MADV_DONTNEED POSIX_MADV_DONTNEED -#define MADV_NORMAL POSIX_MADV_NORMAL -#define MADV_RANDOM POSIX_MADV_RANDOM -#define MADV_SEQUENTIAL POSIX_MADV_SEQUENTIAL -#define MADV_WILLNEED POSIX_MADV_WILLNEED +#define MADV_DONTNEED POSIX_MADV_DONTNEED +#define MADV_NORMAL POSIX_MADV_NORMAL +#define MADV_RANDOM POSIX_MADV_RANDOM +#define MADV_SEQUENTIAL POSIX_MADV_SEQUENTIAL +#define MADV_WILLNEED POSIX_MADV_WILLNEED -#define POSIX_TYPED_MEM_ALLOCATE 0x01 -#define POSIX_TYPED_MEM_ALLOCATE_CONTIG 0x02 -#define POSIX_TYPED_MEM_MAP_ALLOCATABLE 0x04 +#define POSIX_TYPED_MEM_ALLOCATE 0x01 +#define POSIX_TYPED_MEM_ALLOCATE_CONTIG 0x02 +#define POSIX_TYPED_MEM_MAP_ALLOCATABLE 0x04 #define __need_mode_t #define __need_off_t