diff options
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 62 |
1 files changed, 28 insertions, 34 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 65ce60adc8e8..6144b36cd897 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -151,9 +151,8 @@ void __put_task_struct(struct task_struct *tsk) | |||
151 | WARN_ON(atomic_read(&tsk->usage)); | 151 | WARN_ON(atomic_read(&tsk->usage)); |
152 | WARN_ON(tsk == current); | 152 | WARN_ON(tsk == current); |
153 | 153 | ||
154 | security_task_free(tsk); | 154 | put_cred(tsk->real_cred); |
155 | free_uid(tsk->user); | 155 | put_cred(tsk->cred); |
156 | put_group_info(tsk->group_info); | ||
157 | delayacct_tsk_free(tsk); | 156 | delayacct_tsk_free(tsk); |
158 | 157 | ||
159 | if (!profile_handoff_task(tsk)) | 158 | if (!profile_handoff_task(tsk)) |
@@ -822,12 +821,6 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | |||
822 | if (!sig) | 821 | if (!sig) |
823 | return -ENOMEM; | 822 | return -ENOMEM; |
824 | 823 | ||
825 | ret = copy_thread_group_keys(tsk); | ||
826 | if (ret < 0) { | ||
827 | kmem_cache_free(signal_cachep, sig); | ||
828 | return ret; | ||
829 | } | ||
830 | |||
831 | atomic_set(&sig->count, 1); | 824 | atomic_set(&sig->count, 1); |
832 | atomic_set(&sig->live, 1); | 825 | atomic_set(&sig->live, 1); |
833 | init_waitqueue_head(&sig->wait_chldexit); | 826 | init_waitqueue_head(&sig->wait_chldexit); |
@@ -872,7 +865,6 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | |||
872 | void __cleanup_signal(struct signal_struct *sig) | 865 | void __cleanup_signal(struct signal_struct *sig) |
873 | { | 866 | { |
874 | thread_group_cputime_free(sig); | 867 | thread_group_cputime_free(sig); |
875 | exit_thread_group_keys(sig); | ||
876 | tty_kref_put(sig->tty); | 868 | tty_kref_put(sig->tty); |
877 | kmem_cache_free(signal_cachep, sig); | 869 | kmem_cache_free(signal_cachep, sig); |
878 | } | 870 | } |
@@ -988,16 +980,16 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
988 | DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); | 980 | DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); |
989 | #endif | 981 | #endif |
990 | retval = -EAGAIN; | 982 | retval = -EAGAIN; |
991 | if (atomic_read(&p->user->processes) >= | 983 | if (atomic_read(&p->real_cred->user->processes) >= |
992 | p->signal->rlim[RLIMIT_NPROC].rlim_cur) { | 984 | p->signal->rlim[RLIMIT_NPROC].rlim_cur) { |
993 | if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) && | 985 | if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) && |
994 | p->user != current->nsproxy->user_ns->root_user) | 986 | p->real_cred->user != INIT_USER) |
995 | goto bad_fork_free; | 987 | goto bad_fork_free; |
996 | } | 988 | } |
997 | 989 | ||
998 | atomic_inc(&p->user->__count); | 990 | retval = copy_creds(p, clone_flags); |
999 | atomic_inc(&p->user->processes); | 991 | if (retval < 0) |
1000 | get_group_info(p->group_info); | 992 | goto bad_fork_free; |
1001 | 993 | ||
1002 | /* | 994 | /* |
1003 | * If multiple threads are within copy_process(), then this check | 995 | * If multiple threads are within copy_process(), then this check |
@@ -1052,10 +1044,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1052 | do_posix_clock_monotonic_gettime(&p->start_time); | 1044 | do_posix_clock_monotonic_gettime(&p->start_time); |
1053 | p->real_start_time = p->start_time; | 1045 | p->real_start_time = p->start_time; |
1054 | monotonic_to_bootbased(&p->real_start_time); | 1046 | monotonic_to_bootbased(&p->real_start_time); |
1055 | #ifdef CONFIG_SECURITY | ||
1056 | p->security = NULL; | ||
1057 | #endif | ||
1058 | p->cap_bset = current->cap_bset; | ||
1059 | p->io_context = NULL; | 1047 | p->io_context = NULL; |
1060 | p->audit_context = NULL; | 1048 | p->audit_context = NULL; |
1061 | cgroup_fork(p); | 1049 | cgroup_fork(p); |
@@ -1102,10 +1090,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1102 | /* Perform scheduler related setup. Assign this task to a CPU. */ | 1090 | /* Perform scheduler related setup. Assign this task to a CPU. */ |
1103 | sched_fork(p, clone_flags); | 1091 | sched_fork(p, clone_flags); |
1104 | 1092 | ||
1105 | if ((retval = security_task_alloc(p))) | ||
1106 | goto bad_fork_cleanup_policy; | ||
1107 | if ((retval = audit_alloc(p))) | 1093 | if ((retval = audit_alloc(p))) |
1108 | goto bad_fork_cleanup_security; | 1094 | goto bad_fork_cleanup_policy; |
1109 | /* copy all the process information */ | 1095 | /* copy all the process information */ |
1110 | if ((retval = copy_semundo(clone_flags, p))) | 1096 | if ((retval = copy_semundo(clone_flags, p))) |
1111 | goto bad_fork_cleanup_audit; | 1097 | goto bad_fork_cleanup_audit; |
@@ -1119,10 +1105,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1119 | goto bad_fork_cleanup_sighand; | 1105 | goto bad_fork_cleanup_sighand; |
1120 | if ((retval = copy_mm(clone_flags, p))) | 1106 | if ((retval = copy_mm(clone_flags, p))) |
1121 | goto bad_fork_cleanup_signal; | 1107 | goto bad_fork_cleanup_signal; |
1122 | if ((retval = copy_keys(clone_flags, p))) | ||
1123 | goto bad_fork_cleanup_mm; | ||
1124 | if ((retval = copy_namespaces(clone_flags, p))) | 1108 | if ((retval = copy_namespaces(clone_flags, p))) |
1125 | goto bad_fork_cleanup_keys; | 1109 | goto bad_fork_cleanup_mm; |
1126 | if ((retval = copy_io(clone_flags, p))) | 1110 | if ((retval = copy_io(clone_flags, p))) |
1127 | goto bad_fork_cleanup_namespaces; | 1111 | goto bad_fork_cleanup_namespaces; |
1128 | retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); | 1112 | retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); |
@@ -1291,8 +1275,6 @@ bad_fork_cleanup_io: | |||
1291 | put_io_context(p->io_context); | 1275 | put_io_context(p->io_context); |
1292 | bad_fork_cleanup_namespaces: | 1276 | bad_fork_cleanup_namespaces: |
1293 | exit_task_namespaces(p); | 1277 | exit_task_namespaces(p); |
1294 | bad_fork_cleanup_keys: | ||
1295 | exit_keys(p); | ||
1296 | bad_fork_cleanup_mm: | 1278 | bad_fork_cleanup_mm: |
1297 | if (p->mm) | 1279 | if (p->mm) |
1298 | mmput(p->mm); | 1280 | mmput(p->mm); |
@@ -1308,8 +1290,6 @@ bad_fork_cleanup_semundo: | |||
1308 | exit_sem(p); | 1290 | exit_sem(p); |
1309 | bad_fork_cleanup_audit: | 1291 | bad_fork_cleanup_audit: |
1310 | audit_free(p); | 1292 | audit_free(p); |
1311 | bad_fork_cleanup_security: | ||
1312 | security_task_free(p); | ||
1313 | bad_fork_cleanup_policy: | 1293 | bad_fork_cleanup_policy: |
1314 | #ifdef CONFIG_NUMA | 1294 | #ifdef CONFIG_NUMA |
1315 | mpol_put(p->mempolicy); | 1295 | mpol_put(p->mempolicy); |
@@ -1322,9 +1302,9 @@ bad_fork_cleanup_cgroup: | |||
1322 | bad_fork_cleanup_put_domain: | 1302 | bad_fork_cleanup_put_domain: |
1323 | module_put(task_thread_info(p)->exec_domain->module); | 1303 | module_put(task_thread_info(p)->exec_domain->module); |
1324 | bad_fork_cleanup_count: | 1304 | bad_fork_cleanup_count: |
1325 | put_group_info(p->group_info); | 1305 | atomic_dec(&p->cred->user->processes); |
1326 | atomic_dec(&p->user->processes); | 1306 | put_cred(p->real_cred); |
1327 | free_uid(p->user); | 1307 | put_cred(p->cred); |
1328 | bad_fork_free: | 1308 | bad_fork_free: |
1329 | free_task(p); | 1309 | free_task(p); |
1330 | fork_out: | 1310 | fork_out: |
@@ -1368,6 +1348,21 @@ long do_fork(unsigned long clone_flags, | |||
1368 | long nr; | 1348 | long nr; |
1369 | 1349 | ||
1370 | /* | 1350 | /* |
1351 | * Do some preliminary argument and permissions checking before we | ||
1352 | * actually start allocating stuff | ||
1353 | */ | ||
1354 | if (clone_flags & CLONE_NEWUSER) { | ||
1355 | if (clone_flags & CLONE_THREAD) | ||
1356 | return -EINVAL; | ||
1357 | /* hopefully this check will go away when userns support is | ||
1358 | * complete | ||
1359 | */ | ||
1360 | if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SETUID) || | ||
1361 | !capable(CAP_SETGID)) | ||
1362 | return -EPERM; | ||
1363 | } | ||
1364 | |||
1365 | /* | ||
1371 | * We hope to recycle these flags after 2.6.26 | 1366 | * We hope to recycle these flags after 2.6.26 |
1372 | */ | 1367 | */ |
1373 | if (unlikely(clone_flags & CLONE_STOPPED)) { | 1368 | if (unlikely(clone_flags & CLONE_STOPPED)) { |
@@ -1615,8 +1610,7 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) | |||
1615 | err = -EINVAL; | 1610 | err = -EINVAL; |
1616 | if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND| | 1611 | if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND| |
1617 | CLONE_VM|CLONE_FILES|CLONE_SYSVSEM| | 1612 | CLONE_VM|CLONE_FILES|CLONE_SYSVSEM| |
1618 | CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWUSER| | 1613 | CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET)) |
1619 | CLONE_NEWNET)) | ||
1620 | goto bad_unshare_out; | 1614 | goto bad_unshare_out; |
1621 | 1615 | ||
1622 | /* | 1616 | /* |