summaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorSergey Bugaev <bugaevc@gmail.com>2021-08-11 18:34:53 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2021-08-11 18:39:51 +0200
commit5a5358b749d0b153de6f6361342d06228d7270be (patch)
treef3ef6c236f62f412bfff67af727383a5340b9dd1 /sysdeps
parent08fc6df294ab7e10e14492094a99b7861ad7d77e (diff)
downloadglibc-5a5358b749d0b153de6f6361342d06228d7270be.tar.gz
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>
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/mach/hurd/mmap.c22
1 files 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);