[glibc/maskray/lld] hurd mmap: Reduce the requested max vmprot
Fangrui Song
maskray@sourceware.org
Mon Aug 16 17:14:54 GMT 2021
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=5a5358b749d0b153de6f6361342d06228d7270be
commit 5a5358b749d0b153de6f6361342d06228d7270be
Author: Sergey Bugaev <bugaevc@gmail.com>
Date: Wed Aug 11 18:34:53 2021 +0200
hurd mmap: Reduce the requested max vmprot
When the memory object is read-only, the kernel would be right in
refusing max vmprot containing VM_PROT_WRITE.
Reviewed-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Diff:
---
sysdeps/mach/hurd/mmap.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/sysdeps/mach/hurd/mmap.c b/sysdeps/mach/hurd/mmap.c
index 9fa265f752..c7413aff1a 100644
--- a/sysdeps/mach/hurd/mmap.c
+++ b/sysdeps/mach/hurd/mmap.c
@@ -34,7 +34,7 @@ void *
__mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
{
error_t err;
- vm_prot_t vmprot;
+ vm_prot_t vmprot, max_vmprot;
memory_object_t memobj;
vm_address_t mapaddr;
boolean_t copy;
@@ -62,6 +62,7 @@ __mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
case MAP_ANON:
memobj = MACH_PORT_NULL;
+ max_vmprot = VM_PROT_ALL;
break;
case MAP_FILE:
@@ -84,16 +85,23 @@ __mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
anonymous or not when selecting addresses. */
case PROT_NONE:
case PROT_READ:
+ max_vmprot = VM_PROT_READ|VM_PROT_EXECUTE;
+ if (wobj == robj)
+ max_vmprot |= VM_PROT_WRITE;
memobj = robj;
if (wobj != MACH_PORT_NULL)
__mach_port_deallocate (__mach_task_self (), wobj);
break;
case PROT_WRITE:
+ max_vmprot = VM_PROT_WRITE;
+ if (robj == wobj)
+ max_vmprot |= VM_PROT_READ|VM_PROT_EXECUTE;
memobj = wobj;
if (robj != MACH_PORT_NULL)
__mach_port_deallocate (__mach_task_self (), robj);
break;
case PROT_READ|PROT_WRITE:
+ max_vmprot = VM_PROT_ALL;
if (robj == wobj)
{
memobj = wobj;
@@ -122,11 +130,14 @@ __mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
/* XXX handle MAP_INHERIT */
+ if (copy)
+ max_vmprot = VM_PROT_ALL;
+
err = __vm_map (__mach_task_self (),
&mapaddr, (vm_size_t) len, (vm_address_t) 0,
mapaddr == 0,
memobj, (vm_offset_t) offset,
- copy, vmprot, VM_PROT_ALL,
+ copy, vmprot, max_vmprot,
copy ? VM_INHERIT_COPY : VM_INHERIT_SHARE);
if (flags & MAP_FIXED)
@@ -140,7 +151,7 @@ __mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
err = __vm_map (__mach_task_self (),
&mapaddr, (vm_size_t) len, (vm_address_t) 0,
0, memobj, (vm_offset_t) offset,
- copy, vmprot, VM_PROT_ALL,
+ copy, vmprot, max_vmprot,
copy ? VM_INHERIT_COPY : VM_INHERIT_SHARE);
}
}
@@ -150,13 +161,16 @@ __mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
err = __vm_map (__mach_task_self (),
&mapaddr, (vm_size_t) len, (vm_address_t) 0,
1, memobj, (vm_offset_t) offset,
- copy, vmprot, VM_PROT_ALL,
+ copy, vmprot, max_vmprot,
copy ? VM_INHERIT_COPY : VM_INHERIT_SHARE);
}
if (memobj != MACH_PORT_NULL)
__mach_port_deallocate (__mach_task_self (), memobj);
+ if (err == KERN_PROTECTION_FAILURE)
+ err = EACCES;
+
if (err)
return (void *) (long int) __hurd_fail (err);
More information about the Glibc-cvs
mailing list