summaryrefslogtreecommitdiff
path: root/tmpfs
diff options
context:
space:
mode:
authorSergey Bugaev <bugaevc@gmail.com>2021-05-21 13:21:15 +0300
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2022-08-10 22:04:35 +0200
commit7c3323a25bc1d5844feb7f9ed241fdbdb4819739 (patch)
tree26348f5485ccba70458b69be6662680236a0b162 /tmpfs
parent1ed64a8674d3359822831d4ac9a016c04d3e8b14 (diff)
tmpfs: Return read-only memory objects when appropriate
Diffstat (limited to 'tmpfs')
-rw-r--r--tmpfs/node.c37
-rw-r--r--tmpfs/tmpfs.h2
2 files changed, 32 insertions, 7 deletions
diff --git a/tmpfs/node.c b/tmpfs/node.c
index 02d213ed..1a73a164 100644
--- a/tmpfs/node.c
+++ b/tmpfs/node.c
@@ -21,6 +21,7 @@
#include <stddef.h>
#include <stdlib.h>
#include <fcntl.h>
+#include <mach/mach4.h>
#include <hurd/hurd_types.h>
#include <hurd/store.h>
#include "default_pager_U.h"
@@ -72,9 +73,11 @@ diskfs_free_node (struct node *np, mode_t mode)
switch (np->dn->type)
{
case DT_REG:
+ /* XXX GNU Mach will terminate the object, and thus existing mappings
+ * will get SIGBUS. */
+ if (np->dn->u.reg.ro_memobj != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), np->dn->u.reg.ro_memobj);
if (np->dn->u.reg.memobj != MACH_PORT_NULL) {
- /* XXX GNU Mach will terminate the object, and thus existing mappings
- * will get SIGBUS. */
vm_deallocate (mach_task_self (), np->dn->u.reg.memref, 4096);
mach_port_deallocate (mach_task_self (), np->dn->u.reg.memobj);
}
@@ -520,6 +523,7 @@ mach_port_t
diskfs_get_filemap (struct node *np, vm_prot_t prot)
{
error_t err;
+ mach_port_t right;
if (np->dn->type != DT_REG)
{
@@ -561,14 +565,35 @@ diskfs_get_filemap (struct node *np, vm_prot_t prot)
assert_perror_backtrace (err);
}
- /* XXX always writable */
+ if (prot & VM_PROT_WRITE)
+ right = np->dn->u.reg.memobj;
+ else if (np->dn->u.reg.ro_memobj == MACH_PORT_NULL)
+ {
+ vm_offset_t offset = 0;
+ vm_offset_t start = 0;
+ vm_size_t len = ~0;
+ err = memory_object_create_proxy (mach_task_self (),
+ VM_PROT_READ | VM_PROT_EXECUTE,
+ &np->dn->u.reg.memobj, 1,
+ &offset, 1, &start, 1, &len, 1,
+ &np->dn->u.reg.ro_memobj);
+ if (err)
+ {
+ errno = err;
+ return MACH_PORT_NULL;
+ }
+
+ right = np->dn->u.reg.ro_memobj;
+ }
+ else
+ right = np->dn->u.reg.ro_memobj;
/* Add a reference for each call, the caller will deallocate it. */
- err = mach_port_mod_refs (mach_task_self (), np->dn->u.reg.memobj,
- MACH_PORT_RIGHT_SEND, +1);
+ err = mach_port_mod_refs (mach_task_self (), right,
+ MACH_PORT_RIGHT_SEND, +1);
assert_perror_backtrace (err);
- return np->dn->u.reg.memobj;
+ return right;
}
/* The user must define this function. Return a `struct pager *' suitable
diff --git a/tmpfs/tmpfs.h b/tmpfs/tmpfs.h
index ad472009..40554557 100644
--- a/tmpfs/tmpfs.h
+++ b/tmpfs/tmpfs.h
@@ -46,7 +46,7 @@ struct disknode
char *lnk; /* malloc'd symlink target */
struct
{
- mach_port_t memobj;
+ mach_port_t memobj, ro_memobj;
vm_address_t memref;
unsigned int allocpages; /* largest size while memobj was live */
} reg;