From ee4016155ed69e4c26370a43f8b3ae3c982efbc2 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Wed, 6 Jun 2012 00:50:13 +0200 Subject: [PATCH] vm: add third-party mmap() mode and PROCCTL these two functions will be used to support all exec() functionality going into a single library shared by RS and VFS and exec() knowledge leaving VM. . third-party mmap: allow certain processes (VFS, RS) to do mmap() on behalf of another process . PROCCTL: used to free and clear a process' address space --- commands/service/parse.c | 1 + etc/system.conf | 3 ++- include/minix/com.h | 9 ++++++++- include/minix/vm.h | 1 + include/sys/mman.h | 5 ++++- lib/libc/sys-minix/mmap.c | 15 +++++++++++++-- lib/libsys/Makefile | 1 + lib/libsys/vm_procctl.c | 22 ++++++++++++++++++++++ servers/vm/exit.c | 30 ++++++++++++++++++++++++++++++ servers/vm/main.c | 3 +++ servers/vm/mmap.c | 14 ++++++++++++-- servers/vm/proto.h | 1 + 12 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 lib/libsys/vm_procctl.c diff --git a/commands/service/parse.c b/commands/service/parse.c index 1fe637362..562fa2794 100644 --- a/commands/service/parse.c +++ b/commands/service/parse.c @@ -731,6 +731,7 @@ struct { "INFO", VM_INFO }, { "RS_UPDATE", VM_RS_UPDATE }, { "RS_MEMCTL", VM_RS_MEMCTL }, + { "PROCCTL", VM_PROCCTL }, { NULL, 0 }, }; diff --git a/etc/system.conf b/etc/system.conf index 6bd3b3b2b..a4e6d61a0 100644 --- a/etc/system.conf +++ b/etc/system.conf @@ -11,6 +11,7 @@ service rs RS_SET_PRIV # 37 RS_UPDATE # 41 RS_MEMCTL # 42 + PROCCTL ; io NONE; # No I/O range allowed irq NONE; # No IRQ allowed @@ -93,7 +94,7 @@ service vfs UMAP # 14 VIRCOPY # 15 ; - vm BASIC; # Only basic VM calls allowed + vm PROCCTL; io NONE; # No I/O range allowed irq NONE; # No IRQ allowed sigmgr rs; # Signal manager is RS diff --git a/include/minix/com.h b/include/minix/com.h index 68eff5e87..6348550f4 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -942,6 +942,7 @@ # define VMM_FLAGS m5_s2 # define VMM_FD m5_i1 # define VMM_OFFSET m5_i2 +# define VMM_FORWHOM m5_l3 # define VMM_RETADDR m5_l1 /* result */ #define VM_UMAP (VM_RQ_BASE+11) # define VMU_SEG m1_i1 @@ -1076,8 +1077,14 @@ #define VM_REMAP_RO (VM_RQ_BASE+44) /* same args as VM_REMAP */ +#define VM_PROCCTL (VM_RQ_BASE+45) +#define VMPCTL_PARAM m1_i1 +#define VMPCTL_WHO m1_i2 + +#define VMPPARAM_CLEAR 1 /* values for VMPCTL_PARAM */ + /* Total. */ -#define NR_VM_CALLS 45 +#define NR_VM_CALLS 46 #define VM_CALL_MASK_SIZE BITMAP_CHUNKS(NR_VM_CALLS) /* not handled as a normal VM call, thus at the end of the reserved rage */ diff --git a/include/minix/vm.h b/include/minix/vm.h index 626c5406a..3d46c5364 100644 --- a/include/minix/vm.h +++ b/include/minix/vm.h @@ -70,6 +70,7 @@ int vm_info_stats(struct vm_stats_info *vfi); int vm_info_usage(endpoint_t who, struct vm_usage_info *vui); int vm_info_region(endpoint_t who, struct vm_region_info *vri, int count, vir_bytes *next); +int vm_procctl(endpoint_t ep, int param); #endif /* _MINIX_VM_H */ diff --git a/include/sys/mman.h b/include/sys/mman.h index 406db8c9f..8ad43fb9b 100644 --- a/include/sys/mman.h +++ b/include/sys/mman.h @@ -4,6 +4,7 @@ #include #include +#include #ifdef _BSD_SIZE_T_ typedef _BSD_SIZE_T_ size_t; @@ -54,9 +55,10 @@ typedef __off_t off_t; /* file offset */ #define MAP_ALIGN64K 0x0040 /* physically aligned at 64kB */ #define MAP_LOWER1M 0x0080 /* physically below 16MB */ #define MAP_ALIGNMENT_64KB MAP_ALIGN64K -#define MAP_IPC_SHARED 0x0100 /* share changes */ +#define MAP_IPC_SHARED 0x0100 /* share changes */ #define MAP_FIXED 0x0200 /* require mapping to happen at hint */ +#define MAP_THIRDPARTY 0x0400 /* perform on behalf of any process */ /* * Error indicator returned by mmap(2) @@ -71,6 +73,7 @@ void * mmap(void *, size_t, int, int, int, off_t); int munmap(void *, size_t); #else void * minix_mmap(void *, size_t, int, int, int, off_t); +void * minix_mmap_for(endpoint_t, void *, size_t, int, int, int, off_t); int minix_munmap(void *, size_t); int minix_munmap_text(void *, size_t); void * vm_remap(int d, int s, void *da, void *sa, size_t si); diff --git a/lib/libc/sys-minix/mmap.c b/lib/libc/sys-minix/mmap.c index d15e3d1a7..0fb444345 100644 --- a/lib/libc/sys-minix/mmap.c +++ b/lib/libc/sys-minix/mmap.c @@ -21,8 +21,8 @@ __weak_alias(minix_munmap_text, _minix_munmap_text) #include #include -void *minix_mmap(void *addr, size_t len, int prot, int flags, - int fd, off_t offset) +void *minix_mmap_for(endpoint_t forwhom, + void *addr, size_t len, int prot, int flags, int fd, off_t offset) { message m; int r; @@ -33,6 +33,11 @@ void *minix_mmap(void *addr, size_t len, int prot, int flags, m.VMM_FLAGS = flags; m.VMM_FD = fd; m.VMM_OFFSET = offset; + m.VMM_FORWHOM = forwhom; + + if(forwhom != SELF) { + m.VMM_FLAGS |= MAP_THIRDPARTY; + } r = _syscall(VM_PROC_NR, VM_MMAP, &m); @@ -43,6 +48,12 @@ void *minix_mmap(void *addr, size_t len, int prot, int flags, return (void *) m.VMM_RETADDR; } +void *minix_mmap(void *addr, size_t len, int prot, int flags, + int fd, off_t offset) +{ + return minix_mmap_for(SELF, addr, len, prot, flags, fd, offset); +} + int minix_munmap(void *addr, size_t len) { message m; diff --git a/lib/libsys/Makefile b/lib/libsys/Makefile index 9201b0bcd..19f1f11fd 100644 --- a/lib/libsys/Makefile +++ b/lib/libsys/Makefile @@ -127,6 +127,7 @@ SRCS= \ vm_push_sig.c \ vm_umap.c \ vm_yield_get_block.c \ + vm_procctl.c \ vprintf.c \ .if ${MKCOVERAGE} != "no" diff --git a/lib/libsys/vm_procctl.c b/lib/libsys/vm_procctl.c new file mode 100644 index 000000000..a3081683c --- /dev/null +++ b/lib/libsys/vm_procctl.c @@ -0,0 +1,22 @@ + +#include "syslib.h" + +#include +#include + +/*===========================================================================* + * vm_exit * + *===========================================================================*/ +int vm_procctl(endpoint_t ep, int param) +{ + message m; + int result; + + memset(&m, 0, sizeof(m)); + + m.VMPCTL_WHO = ep; + m.VMPCTL_PARAM = param; + + result = _taskcall(VM_PROC_NR, VM_PROCCTL, &m); + return(result); +} diff --git a/servers/vm/exit.c b/servers/vm/exit.c index 04e37ceb2..202dc0ba4 100644 --- a/servers/vm/exit.c +++ b/servers/vm/exit.c @@ -114,3 +114,33 @@ int do_willexit(message *msg) return OK; } +int do_procctl(message *msg) +{ + endpoint_t proc; + struct vmproc *vmp; + + if(vm_isokendpt(msg->VMPCTL_WHO, &proc) != OK) { + printf("VM: bogus endpoint VM_PROCCTL %d\n", + msg->VMPCTL_WHO); + return EINVAL; + } + vmp = &vmproc[proc]; + + switch(msg->VMPCTL_PARAM) { + case VMPPARAM_CLEAR: + if(msg->m_source != RS_PROC_NR + && msg->m_source != VFS_PROC_NR) + return EPERM; + free_proc(vmp); + pt_new(&vmp->vm_pt); + vmp->vm_flags |= VMF_HASPT; + pt_bind(&vmp->vm_pt, vmp); + return OK; + default: + return EINVAL; + } + + + return OK; +} + diff --git a/servers/vm/main.c b/servers/vm/main.c index 3f86a8194..765852acb 100644 --- a/servers/vm/main.c +++ b/servers/vm/main.c @@ -357,6 +357,9 @@ static int sef_cb_init_fresh(int type, sef_init_info_t *info) CALLMAP(VM_RS_UPDATE, do_rs_update); CALLMAP(VM_RS_MEMCTL, do_rs_memctl); + /* Calls from RS/VFS */ + CALLMAP(VM_PROCCTL, do_procctl); + /* Generic calls. */ CALLMAP(VM_REMAP, do_remap); CALLMAP(VM_REMAP_RO, do_remap); diff --git a/servers/vm/mmap.c b/servers/vm/mmap.c index b74571613..8bf843754 100644 --- a/servers/vm/mmap.c +++ b/servers/vm/mmap.c @@ -43,8 +43,18 @@ int do_mmap(message *m) vir_bytes addr; struct vir_region *vr = NULL; - if((r=vm_isokendpt(m->m_source, &n)) != OK) { - panic("do_mmap: message from strange source: %d", m->m_source); + if(m->VMM_FLAGS & MAP_THIRDPARTY) { + /* exec()ers, i.e. RS & VFS, can mmap() on behalf of anyone. */ + if(m->m_source != VFS_PROC_NR && m->m_source != RS_PROC_NR) + return EPERM; + if((r=vm_isokendpt(m->VMM_FORWHOM, &n)) != OK) + return ESRCH; + } else { + /* regular mmap, i.e. for caller */ + if((r=vm_isokendpt(m->m_source, &n)) != OK) { + panic("do_mmap: message from strange source: %d", + m->m_source); + } } vmp = &vmproc[n]; diff --git a/servers/vm/proto.h b/servers/vm/proto.h index 3e1f9d445..3168ce9af 100644 --- a/servers/vm/proto.h +++ b/servers/vm/proto.h @@ -52,6 +52,7 @@ int swap_proc_dyn_data(struct vmproc *src_vmp, struct vmproc *dst_vmp); void clear_proc(struct vmproc *vmp); int do_exit(message *msg); int do_willexit(message *msg); +int do_procctl(message *msg); void free_proc(struct vmproc *vmp); /* fork.c */