1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-28 17:25:06 +00:00

Kernel+LibC: Add a very limited sys$mremap() implementation

This syscall can currently only remap a shared file-backed mapping into
a private file-backed mapping.
This commit is contained in:
Andreas Kling 2020-12-29 02:11:47 +01:00
parent c1360ef22e
commit 30dbe9c78a
6 changed files with 71 additions and 1 deletions

View file

@ -195,7 +195,8 @@ namespace Kernel {
S(disown) \
S(adjtime) \
S(allocate_tls) \
S(prctl)
S(prctl) \
S(mremap)
namespace Syscall {
@ -256,6 +257,13 @@ struct SC_mmap_params {
StringArgument name;
};
struct SC_mremap_params {
uintptr_t old_address;
size_t old_size;
size_t new_size;
int32_t flags;
};
struct SC_open_params {
int dirfd;
StringArgument path;

View file

@ -251,6 +251,7 @@ public:
int sys$sigreturn(RegisterState& registers);
pid_t sys$waitid(Userspace<const Syscall::SC_waitid_params*>);
void* sys$mmap(Userspace<const Syscall::SC_mmap_params*>);
void* sys$mremap(Userspace<const Syscall::SC_mremap_params*>);
int sys$munmap(void*, size_t size);
int sys$set_mmap_name(Userspace<const Syscall::SC_set_mmap_name_params*>);
int sys$mprotect(void*, size_t, int prot);

View file

@ -28,6 +28,7 @@
#include <Kernel/FileSystem/FileDescription.h>
#include <Kernel/Process.h>
#include <Kernel/VM/PageDirectory.h>
#include <Kernel/VM/PrivateInodeVMObject.h>
#include <Kernel/VM/PurgeableVMObject.h>
#include <Kernel/VM/Region.h>
#include <Kernel/VM/SharedInodeVMObject.h>
@ -422,6 +423,42 @@ int Process::sys$munmap(void* addr, size_t size)
return -EINVAL;
}
void* Process::sys$mremap(Userspace<const Syscall::SC_mremap_params*> user_params)
{
REQUIRE_PROMISE(stdio);
Syscall::SC_mremap_params params;
if (!copy_from_user(&params, user_params))
return (void*)-EFAULT;
auto* old_region = find_region_from_range(Range { VirtualAddress(params.old_address), params.old_size });
if (!old_region)
return (void*)-EINVAL;
if (!old_region->is_mmap())
return (void*)-EPERM;
if (old_region->vmobject().is_shared_inode() && params.flags & MAP_PRIVATE && !(params.flags & MAP_ANONYMOUS) && !(params.flags & MAP_PURGEABLE)) {
auto range = old_region->range();
auto old_name = old_region->name();
auto old_prot = region_access_flags_to_prot(old_region->access());
NonnullRefPtr inode = static_cast<SharedInodeVMObject&>(old_region->vmobject()).inode();
deallocate_region(*old_region);
auto new_vmobject = PrivateInodeVMObject::create_with_inode(inode);
auto* new_region = allocate_region_with_vmobject(range.base(), range.size(), new_vmobject, 0, old_name, old_prot);
new_region->set_mmap(true);
if (!new_region)
return (void*)-ENOMEM;
return new_region->vaddr().as_ptr();
}
dbgln("sys$mremap: Unimplemented remap request (flags={})", params.flags);
return (void*)-ENOTIMPL;
}
void* Process::sys$allocate_tls(size_t size)
{
REQUIRE_PROMISE(stdio);

View file

@ -238,4 +238,16 @@ inline unsigned prot_to_region_access_flags(int prot)
return access;
}
inline int region_access_flags_to_prot(unsigned access)
{
int prot = 0;
if (access & Region::Access::Read)
prot |= PROT_READ;
if (access & Region::Access::Write)
prot |= PROT_WRITE;
if (access & Region::Access::Execute)
prot |= PROT_EXEC;
return prot;
}
}

View file

@ -53,6 +53,17 @@ void* mmap_with_name(void* addr, size_t size, int prot, int flags, int fd, off_t
return serenity_mmap(addr, size, prot, flags, fd, offset, PAGE_SIZE, name);
}
void* mremap(void* old_address, size_t old_size, size_t new_size, int flags)
{
Syscall::SC_mremap_params params { (uintptr_t)old_address, old_size, new_size, flags };
ssize_t rc = syscall(SC_mremap, &params);
if (rc < 0 && -rc < EMAXERRNO) {
errno = -rc;
return MAP_FAILED;
}
return (void*)rc;
}
int munmap(void* addr, size_t size)
{
int rc = syscall(SC_munmap, addr, size);

View file

@ -56,6 +56,7 @@ __BEGIN_DECLS
void* mmap(void* addr, size_t, int prot, int flags, int fd, off_t);
void* mmap_with_name(void* addr, size_t, int prot, int flags, int fd, off_t, const char* name);
void* serenity_mmap(void* addr, size_t, int prot, int flags, int fd, off_t, size_t alignment, const char* name);
void* mremap(void* old_address, size_t old_size, size_t new_size, int flags);
int munmap(void*, size_t);
int mprotect(void*, size_t, int prot);
int set_mmap_name(void*, size_t, const char*);