aboutsummaryrefslogtreecommitdiff
path: root/kernel/fork.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/fork.c')
-rw-r--r--kernel/fork.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index a8eab86de7f..9bd7b65ee41 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1062,6 +1062,12 @@ static task_t *copy_process(unsigned long clone_flags,
p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL;
/*
+ * sigaltstack should be cleared when sharing the same VM
+ */
+ if ((clone_flags & (CLONE_VM|CLONE_VFORK)) == CLONE_VM)
+ p->sas_ss_sp = p->sas_ss_size = 0;
+
+ /*
* Syscall tracing should be turned off in the child regardless
* of CLONE_PTRACE.
*/
@@ -1472,9 +1478,7 @@ static int unshare_vm(unsigned long unshare_flags, struct mm_struct **new_mmp)
if ((unshare_flags & CLONE_VM) &&
(mm && atomic_read(&mm->mm_users) > 1)) {
- *new_mmp = dup_mm(current);
- if (!*new_mmp)
- return -ENOMEM;
+ return -EINVAL;
}
return 0;
@@ -1530,6 +1534,12 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
check_unshare_flags(&unshare_flags);
+ /* Return -EINVAL for all unsupported flags */
+ err = -EINVAL;
+ if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
+ CLONE_VM|CLONE_FILES|CLONE_SYSVSEM))
+ goto bad_unshare_out;
+
if ((err = unshare_thread(unshare_flags)))
goto bad_unshare_out;
if ((err = unshare_fs(unshare_flags, &new_fs)))
@@ -1563,7 +1573,7 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
if (new_sigh) {
sigh = current->sighand;
- current->sighand = new_sigh;
+ rcu_assign_pointer(current->sighand, new_sigh);
new_sigh = sigh;
}