mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 04:32:44 +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
	
	 Andreas Kling
						Andreas Kling