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:
parent
c1360ef22e
commit
30dbe9c78a
6 changed files with 71 additions and 1 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(¶ms, 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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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, ¶ms);
|
||||
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);
|
||||
|
|
|
@ -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*);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue