diff options
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 42 |
1 files changed, 23 insertions, 19 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 1d68f1255dd8..6715ebc3761d 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -61,6 +61,7 @@ | |||
61 | #include <linux/proc_fs.h> | 61 | #include <linux/proc_fs.h> |
62 | #include <linux/blkdev.h> | 62 | #include <linux/blkdev.h> |
63 | #include <trace/sched.h> | 63 | #include <trace/sched.h> |
64 | #include <linux/magic.h> | ||
64 | 65 | ||
65 | #include <asm/pgtable.h> | 66 | #include <asm/pgtable.h> |
66 | #include <asm/pgalloc.h> | 67 | #include <asm/pgalloc.h> |
@@ -212,6 +213,8 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) | |||
212 | { | 213 | { |
213 | struct task_struct *tsk; | 214 | struct task_struct *tsk; |
214 | struct thread_info *ti; | 215 | struct thread_info *ti; |
216 | unsigned long *stackend; | ||
217 | |||
215 | int err; | 218 | int err; |
216 | 219 | ||
217 | prepare_to_copy(orig); | 220 | prepare_to_copy(orig); |
@@ -237,6 +240,8 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) | |||
237 | goto out; | 240 | goto out; |
238 | 241 | ||
239 | setup_thread_stack(tsk, orig); | 242 | setup_thread_stack(tsk, orig); |
243 | stackend = end_of_stack(tsk); | ||
244 | *stackend = STACK_END_MAGIC; /* for overflow detection */ | ||
240 | 245 | ||
241 | #ifdef CONFIG_CC_STACKPROTECTOR | 246 | #ifdef CONFIG_CC_STACKPROTECTOR |
242 | tsk->stack_canary = get_random_int(); | 247 | tsk->stack_canary = get_random_int(); |
@@ -817,17 +822,17 @@ static void posix_cpu_timers_init_group(struct signal_struct *sig) | |||
817 | static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | 822 | static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) |
818 | { | 823 | { |
819 | struct signal_struct *sig; | 824 | struct signal_struct *sig; |
820 | int ret; | ||
821 | 825 | ||
822 | if (clone_flags & CLONE_THREAD) { | 826 | if (clone_flags & CLONE_THREAD) { |
823 | ret = thread_group_cputime_clone_thread(current); | 827 | atomic_inc(¤t->signal->count); |
824 | if (likely(!ret)) { | 828 | atomic_inc(¤t->signal->live); |
825 | atomic_inc(¤t->signal->count); | 829 | return 0; |
826 | atomic_inc(¤t->signal->live); | ||
827 | } | ||
828 | return ret; | ||
829 | } | 830 | } |
830 | sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL); | 831 | sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL); |
832 | |||
833 | if (sig) | ||
834 | posix_cpu_timers_init_group(sig); | ||
835 | |||
831 | tsk->signal = sig; | 836 | tsk->signal = sig; |
832 | if (!sig) | 837 | if (!sig) |
833 | return -ENOMEM; | 838 | return -ENOMEM; |
@@ -851,21 +856,20 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | |||
851 | sig->tty_old_pgrp = NULL; | 856 | sig->tty_old_pgrp = NULL; |
852 | sig->tty = NULL; | 857 | sig->tty = NULL; |
853 | 858 | ||
854 | sig->cutime = sig->cstime = cputime_zero; | 859 | sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero; |
855 | sig->gtime = cputime_zero; | 860 | sig->gtime = cputime_zero; |
856 | sig->cgtime = cputime_zero; | 861 | sig->cgtime = cputime_zero; |
857 | sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0; | 862 | sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0; |
858 | sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0; | 863 | sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0; |
859 | sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0; | 864 | sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0; |
860 | task_io_accounting_init(&sig->ioac); | 865 | task_io_accounting_init(&sig->ioac); |
866 | sig->sum_sched_runtime = 0; | ||
861 | taskstats_tgid_init(sig); | 867 | taskstats_tgid_init(sig); |
862 | 868 | ||
863 | task_lock(current->group_leader); | 869 | task_lock(current->group_leader); |
864 | memcpy(sig->rlim, current->signal->rlim, sizeof sig->rlim); | 870 | memcpy(sig->rlim, current->signal->rlim, sizeof sig->rlim); |
865 | task_unlock(current->group_leader); | 871 | task_unlock(current->group_leader); |
866 | 872 | ||
867 | posix_cpu_timers_init_group(sig); | ||
868 | |||
869 | acct_init_pacct(&sig->pacct); | 873 | acct_init_pacct(&sig->pacct); |
870 | 874 | ||
871 | tty_audit_fork(sig); | 875 | tty_audit_fork(sig); |
@@ -901,7 +905,7 @@ static void copy_flags(unsigned long clone_flags, struct task_struct *p) | |||
901 | clear_freeze_flag(p); | 905 | clear_freeze_flag(p); |
902 | } | 906 | } |
903 | 907 | ||
904 | asmlinkage long sys_set_tid_address(int __user *tidptr) | 908 | SYSCALL_DEFINE1(set_tid_address, int __user *, tidptr) |
905 | { | 909 | { |
906 | current->clear_child_tid = tidptr; | 910 | current->clear_child_tid = tidptr; |
907 | 911 | ||
@@ -1007,6 +1011,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1007 | * triggers too late. This doesn't hurt, the check is only there | 1011 | * triggers too late. This doesn't hurt, the check is only there |
1008 | * to stop root fork bombs. | 1012 | * to stop root fork bombs. |
1009 | */ | 1013 | */ |
1014 | retval = -EAGAIN; | ||
1010 | if (nr_threads >= max_threads) | 1015 | if (nr_threads >= max_threads) |
1011 | goto bad_fork_cleanup_count; | 1016 | goto bad_fork_cleanup_count; |
1012 | 1017 | ||
@@ -1095,7 +1100,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1095 | #ifdef CONFIG_DEBUG_MUTEXES | 1100 | #ifdef CONFIG_DEBUG_MUTEXES |
1096 | p->blocked_on = NULL; /* not blocked yet */ | 1101 | p->blocked_on = NULL; /* not blocked yet */ |
1097 | #endif | 1102 | #endif |
1098 | if (unlikely(ptrace_reparented(current))) | 1103 | if (unlikely(current->ptrace)) |
1099 | ptrace_fork(p, clone_flags); | 1104 | ptrace_fork(p, clone_flags); |
1100 | 1105 | ||
1101 | /* Perform scheduler related setup. Assign this task to a CPU. */ | 1106 | /* Perform scheduler related setup. Assign this task to a CPU. */ |
@@ -1179,10 +1184,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1179 | #endif | 1184 | #endif |
1180 | clear_all_latency_tracing(p); | 1185 | clear_all_latency_tracing(p); |
1181 | 1186 | ||
1182 | /* Our parent execution domain becomes current domain | ||
1183 | These must match for thread signalling to apply */ | ||
1184 | p->parent_exec_id = p->self_exec_id; | ||
1185 | |||
1186 | /* ok, now we should be set up.. */ | 1187 | /* ok, now we should be set up.. */ |
1187 | p->exit_signal = (clone_flags & CLONE_THREAD) ? -1 : (clone_flags & CSIGNAL); | 1188 | p->exit_signal = (clone_flags & CLONE_THREAD) ? -1 : (clone_flags & CSIGNAL); |
1188 | p->pdeath_signal = 0; | 1189 | p->pdeath_signal = 0; |
@@ -1220,10 +1221,13 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1220 | set_task_cpu(p, smp_processor_id()); | 1221 | set_task_cpu(p, smp_processor_id()); |
1221 | 1222 | ||
1222 | /* CLONE_PARENT re-uses the old parent */ | 1223 | /* CLONE_PARENT re-uses the old parent */ |
1223 | if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) | 1224 | if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) { |
1224 | p->real_parent = current->real_parent; | 1225 | p->real_parent = current->real_parent; |
1225 | else | 1226 | p->parent_exec_id = current->parent_exec_id; |
1227 | } else { | ||
1226 | p->real_parent = current; | 1228 | p->real_parent = current; |
1229 | p->parent_exec_id = current->self_exec_id; | ||
1230 | } | ||
1227 | 1231 | ||
1228 | spin_lock(¤t->sighand->siglock); | 1232 | spin_lock(¤t->sighand->siglock); |
1229 | 1233 | ||
@@ -1603,7 +1607,7 @@ static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp | |||
1603 | * constructed. Here we are modifying the current, active, | 1607 | * constructed. Here we are modifying the current, active, |
1604 | * task_struct. | 1608 | * task_struct. |
1605 | */ | 1609 | */ |
1606 | asmlinkage long sys_unshare(unsigned long unshare_flags) | 1610 | SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) |
1607 | { | 1611 | { |
1608 | int err = 0; | 1612 | int err = 0; |
1609 | struct fs_struct *fs, *new_fs = NULL; | 1613 | struct fs_struct *fs, *new_fs = NULL; |