summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_exec.c')
-rw-r--r--sys/kern/kern_exec.c89
1 files changed, 85 insertions, 4 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 1e4d690..6cf77f7 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -389,6 +389,7 @@ do_execve(td, args, mac_p)
imgp->canarylen = 0;
imgp->pagesizes = 0;
imgp->pagesizeslen = 0;
+ imgp->stack_prot = 0;
#ifdef MAC
error = mac_execve_enter(imgp, mac_p);
@@ -996,6 +997,7 @@ exec_new_vmspace(imgp, sv)
int error;
struct proc *p = imgp->proc;
struct vmspace *vmspace = p->p_vmspace;
+ vm_object_t obj;
vm_offset_t sv_minuser, stack_addr;
vm_map_t map;
u_long ssiz;
@@ -1029,6 +1031,20 @@ exec_new_vmspace(imgp, sv)
map = &vmspace->vm_map;
}
+ /* Map a shared page */
+ obj = sv->sv_shared_page_obj;
+ if (obj != NULL) {
+ vm_object_reference(obj);
+ error = vm_map_fixed(map, obj, 0,
+ sv->sv_shared_page_base, sv->sv_shared_page_len,
+ VM_PROT_READ | VM_PROT_EXECUTE, VM_PROT_ALL,
+ MAP_COPY_ON_WRITE | MAP_ACC_NO_CHARGE);
+ if (error) {
+ vm_object_deallocate(obj);
+ return (error);
+ }
+ }
+
/* Allocate a new stack */
if (sv->sv_maxssiz != NULL)
ssiz = *sv->sv_maxssiz;
@@ -1036,7 +1052,9 @@ exec_new_vmspace(imgp, sv)
ssiz = maxssiz;
stack_addr = sv->sv_usrstack - ssiz;
error = vm_map_stack(map, stack_addr, (vm_size_t)ssiz,
- sv->sv_stackprot, VM_PROT_ALL, MAP_STACK_GROWS_DOWN);
+ obj != NULL && imgp->stack_prot != 0 ? imgp->stack_prot :
+ sv->sv_stackprot,
+ VM_PROT_ALL, MAP_STACK_GROWS_DOWN);
if (error)
return (error);
@@ -1208,8 +1226,10 @@ exec_copyout_strings(imgp)
p = imgp->proc;
szsigcode = 0;
arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings;
- if (p->p_sysent->sv_szsigcode != NULL)
- szsigcode = *(p->p_sysent->sv_szsigcode);
+ if (p->p_sysent->sv_sigcode_base == 0) {
+ if (p->p_sysent->sv_szsigcode != NULL)
+ szsigcode = *(p->p_sysent->sv_szsigcode);
+ }
destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
roundup(execpath_len, sizeof(char *)) -
roundup(sizeof(canary), sizeof(char *)) -
@@ -1219,7 +1239,7 @@ exec_copyout_strings(imgp)
/*
* install sigcode
*/
- if (szsigcode)
+ if (szsigcode != 0)
copyout(p->p_sysent->sv_sigcode, ((caddr_t)arginfo -
szsigcode), szsigcode);
@@ -1459,3 +1479,64 @@ exec_unregister(execsw_arg)
execsw = newexecsw;
return (0);
}
+
+static vm_object_t shared_page_obj;
+static int shared_page_free;
+
+int
+shared_page_fill(int size, int align, const char *data)
+{
+ vm_page_t m;
+ struct sf_buf *s;
+ vm_offset_t sk;
+ int res;
+
+ VM_OBJECT_LOCK(shared_page_obj);
+ m = vm_page_grab(shared_page_obj, 0, VM_ALLOC_RETRY);
+ res = roundup(shared_page_free, align);
+ if (res + size >= IDX_TO_OFF(shared_page_obj->size))
+ res = -1;
+ else {
+ VM_OBJECT_UNLOCK(shared_page_obj);
+ s = sf_buf_alloc(m, SFB_DEFAULT);
+ sk = sf_buf_kva(s);
+ bcopy(data, (void *)(sk + res), size);
+ shared_page_free = res + size;
+ sf_buf_free(s);
+ VM_OBJECT_LOCK(shared_page_obj);
+ }
+ vm_page_wakeup(m);
+ VM_OBJECT_UNLOCK(shared_page_obj);
+ return (res);
+}
+
+static void
+shared_page_init(void *dummy __unused)
+{
+ vm_page_t m;
+
+ shared_page_obj = vm_pager_allocate(OBJT_PHYS, 0, PAGE_SIZE,
+ VM_PROT_DEFAULT, 0, NULL);
+ VM_OBJECT_LOCK(shared_page_obj);
+ m = vm_page_grab(shared_page_obj, 0, VM_ALLOC_RETRY | VM_ALLOC_NOBUSY |
+ VM_ALLOC_ZERO);
+ m->valid = VM_PAGE_BITS_ALL;
+ VM_OBJECT_UNLOCK(shared_page_obj);
+}
+
+SYSINIT(shp, SI_SUB_EXEC, SI_ORDER_FIRST, (sysinit_cfunc_t)shared_page_init,
+ NULL);
+
+void
+exec_sysvec_init(void *param)
+{
+ struct sysentvec *sv;
+
+ sv = (struct sysentvec *)param;
+
+ if ((sv->sv_flags & SV_SHP) == 0)
+ return;
+ sv->sv_shared_page_obj = shared_page_obj;
+ sv->sv_sigcode_base = sv->sv_shared_page_base +
+ shared_page_fill(*(sv->sv_szsigcode), 16, sv->sv_sigcode);
+}
OpenPOWER on IntegriCloud