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 495da2e9a8b4..4e8ca23c0ede 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -147,9 +147,8 @@ void __put_task_struct(struct task_struct *tsk) | |||
| 147 | WARN_ON(atomic_read(&tsk->usage)); | 147 | WARN_ON(atomic_read(&tsk->usage)); |
| 148 | WARN_ON(tsk == current); | 148 | WARN_ON(tsk == current); |
| 149 | 149 | ||
| 150 | security_task_free(tsk); | 150 | put_cred(tsk->real_cred); |
| 151 | free_uid(tsk->user); | 151 | put_cred(tsk->cred); |
| 152 | put_group_info(tsk->group_info); | ||
| 153 | delayacct_tsk_free(tsk); | 152 | delayacct_tsk_free(tsk); |
| 154 | 153 | ||
| 155 | if (!profile_handoff_task(tsk)) | 154 | if (!profile_handoff_task(tsk)) |
| @@ -818,12 +817,6 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | |||
| 818 | if (!sig) | 817 | if (!sig) |
| 819 | return -ENOMEM; | 818 | return -ENOMEM; |
| 820 | 819 | ||
| 821 | ret = copy_thread_group_keys(tsk); | ||
| 822 | if (ret < 0) { | ||
| 823 | kmem_cache_free(signal_cachep, sig); | ||
| 824 | return ret; | ||
| 825 | } | ||
| 826 | |||
| 827 | atomic_set(&sig->count, 1); | 820 | atomic_set(&sig->count, 1); |
| 828 | atomic_set(&sig->live, 1); | 821 | atomic_set(&sig->live, 1); |
| 829 | init_waitqueue_head(&sig->wait_chldexit); | 822 | init_waitqueue_head(&sig->wait_chldexit); |
| @@ -868,7 +861,6 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | |||
| 868 | void __cleanup_signal(struct signal_struct *sig) | 861 | void __cleanup_signal(struct signal_struct *sig) |
| 869 | { | 862 | { |
| 870 | thread_group_cputime_free(sig); | 863 | thread_group_cputime_free(sig); |
| 871 | exit_thread_group_keys(sig); | ||
| 872 | tty_kref_put(sig->tty); | 864 | tty_kref_put(sig->tty); |
| 873 | kmem_cache_free(signal_cachep, sig); | 865 | kmem_cache_free(signal_cachep, sig); |
| 874 | } | 866 | } |
| @@ -984,16 +976,16 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 984 | DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); | 976 | DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); |
| 985 | #endif | 977 | #endif |
| 986 | retval = -EAGAIN; | 978 | retval = -EAGAIN; |
| 987 | if (atomic_read(&p->user->processes) >= | 979 | if (atomic_read(&p->real_cred->user->processes) >= |
| 988 | p->signal->rlim[RLIMIT_NPROC].rlim_cur) { | 980 | p->signal->rlim[RLIMIT_NPROC].rlim_cur) { |
| 989 | if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) && | 981 | if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) && |
| 990 | p->user != current->nsproxy->user_ns->root_user) | 982 | p->real_cred->user != INIT_USER) |
| 991 | goto bad_fork_free; | 983 | goto bad_fork_free; |
| 992 | } | 984 | } |
| 993 | 985 | ||
| 994 | atomic_inc(&p->user->__count); | 986 | retval = copy_creds(p, clone_flags); |
| 995 | atomic_inc(&p->user->processes); | 987 | if (retval < 0) |
| 996 | get_group_info(p->group_info); | 988 | goto bad_fork_free; |
| 997 | 989 | ||
| 998 | /* | 990 | /* |
| 999 | * If multiple threads are within copy_process(), then this check | 991 | * If multiple threads are within copy_process(), then this check |
| @@ -1048,10 +1040,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1048 | do_posix_clock_monotonic_gettime(&p->start_time); | 1040 | do_posix_clock_monotonic_gettime(&p->start_time); |
| 1049 | p->real_start_time = p->start_time; | 1041 | p->real_start_time = p->start_time; |
| 1050 | monotonic_to_bootbased(&p->real_start_time); | 1042 | monotonic_to_bootbased(&p->real_start_time); |
| 1051 | #ifdef CONFIG_SECURITY | ||
| 1052 | p->security = NULL; | ||
| 1053 | #endif | ||
| 1054 | p->cap_bset = current->cap_bset; | ||
| 1055 | p->io_context = NULL; | 1043 | p->io_context = NULL; |
| 1056 | p->audit_context = NULL; | 1044 | p->audit_context = NULL; |
| 1057 | cgroup_fork(p); | 1045 | cgroup_fork(p); |
| @@ -1096,10 +1084,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1096 | /* Perform scheduler related setup. Assign this task to a CPU. */ | 1084 | /* Perform scheduler related setup. Assign this task to a CPU. */ |
| 1097 | sched_fork(p, clone_flags); | 1085 | sched_fork(p, clone_flags); |
| 1098 | 1086 | ||
| 1099 | if ((retval = security_task_alloc(p))) | ||
| 1100 | goto bad_fork_cleanup_policy; | ||
| 1101 | if ((retval = audit_alloc(p))) | 1087 | if ((retval = audit_alloc(p))) |
| 1102 | goto bad_fork_cleanup_security; | 1088 | goto bad_fork_cleanup_policy; |
| 1103 | /* copy all the process information */ | 1089 | /* copy all the process information */ |
| 1104 | if ((retval = copy_semundo(clone_flags, p))) | 1090 | if ((retval = copy_semundo(clone_flags, p))) |
| 1105 | goto bad_fork_cleanup_audit; | 1091 | goto bad_fork_cleanup_audit; |
| @@ -1113,10 +1099,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1113 | goto bad_fork_cleanup_sighand; | 1099 | goto bad_fork_cleanup_sighand; |
| 1114 | if ((retval = copy_mm(clone_flags, p))) | 1100 | if ((retval = copy_mm(clone_flags, p))) |
| 1115 | goto bad_fork_cleanup_signal; | 1101 | goto bad_fork_cleanup_signal; |
| 1116 | if ((retval = copy_keys(clone_flags, p))) | ||
| 1117 | goto bad_fork_cleanup_mm; | ||
| 1118 | if ((retval = copy_namespaces(clone_flags, p))) | 1102 | if ((retval = copy_namespaces(clone_flags, p))) |
| 1119 | goto bad_fork_cleanup_keys; | 1103 | goto bad_fork_cleanup_mm; |
| 1120 | if ((retval = copy_io(clone_flags, p))) | 1104 | if ((retval = copy_io(clone_flags, p))) |
| 1121 | goto bad_fork_cleanup_namespaces; | 1105 | goto bad_fork_cleanup_namespaces; |
| 1122 | retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); | 1106 | retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); |
| @@ -1281,8 +1265,6 @@ bad_fork_cleanup_io: | |||
| 1281 | put_io_context(p->io_context); | 1265 | put_io_context(p->io_context); |
| 1282 | bad_fork_cleanup_namespaces: | 1266 | bad_fork_cleanup_namespaces: |
| 1283 | exit_task_namespaces(p); | 1267 | exit_task_namespaces(p); |
| 1284 | bad_fork_cleanup_keys: | ||
| 1285 | exit_keys(p); | ||
| 1286 | bad_fork_cleanup_mm: | 1268 | bad_fork_cleanup_mm: |
| 1287 | if (p->mm) | 1269 | if (p->mm) |
| 1288 | mmput(p->mm); | 1270 | mmput(p->mm); |
| @@ -1298,8 +1280,6 @@ bad_fork_cleanup_semundo: | |||
| 1298 | exit_sem(p); | 1280 | exit_sem(p); |
| 1299 | bad_fork_cleanup_audit: | 1281 | bad_fork_cleanup_audit: |
| 1300 | audit_free(p); | 1282 | audit_free(p); |
| 1301 | bad_fork_cleanup_security: | ||
| 1302 | security_task_free(p); | ||
| 1303 | bad_fork_cleanup_policy: | 1283 | bad_fork_cleanup_policy: |
| 1304 | #ifdef CONFIG_NUMA | 1284 | #ifdef CONFIG_NUMA |
| 1305 | mpol_put(p->mempolicy); | 1285 | mpol_put(p->mempolicy); |
| @@ -1312,9 +1292,9 @@ bad_fork_cleanup_cgroup: | |||
| 1312 | bad_fork_cleanup_put_domain: | 1292 | bad_fork_cleanup_put_domain: |
| 1313 | module_put(task_thread_info(p)->exec_domain->module); | 1293 | module_put(task_thread_info(p)->exec_domain->module); |
| 1314 | bad_fork_cleanup_count: | 1294 | bad_fork_cleanup_count: |
| 1315 | put_group_info(p->group_info); | 1295 | atomic_dec(&p->cred->user->processes); |
| 1316 | atomic_dec(&p->user->processes); | 1296 | put_cred(p->real_cred); |
| 1317 | free_uid(p->user); | 1297 | put_cred(p->cred); |
| 1318 | bad_fork_free: | 1298 | bad_fork_free: |
| 1319 | free_task(p); | 1299 | free_task(p); |
| 1320 | fork_out: | 1300 | fork_out: |
| @@ -1358,6 +1338,21 @@ long do_fork(unsigned long clone_flags, | |||
| 1358 | long nr; | 1338 | long nr; |
| 1359 | 1339 | ||
| 1360 | /* | 1340 | /* |
| 1341 | * Do some preliminary argument and permissions checking before we | ||
| 1342 | * actually start allocating stuff | ||
| 1343 | */ | ||
| 1344 | if (clone_flags & CLONE_NEWUSER) { | ||
| 1345 | if (clone_flags & CLONE_THREAD) | ||
| 1346 | return -EINVAL; | ||
| 1347 | /* hopefully this check will go away when userns support is | ||
| 1348 | * complete | ||
| 1349 | */ | ||
| 1350 | if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SETUID) || | ||
| 1351 | !capable(CAP_SETGID)) | ||
| 1352 | return -EPERM; | ||
| 1353 | } | ||
| 1354 | |||
| 1355 | /* | ||
| 1361 | * We hope to recycle these flags after 2.6.26 | 1356 | * We hope to recycle these flags after 2.6.26 |
| 1362 | */ | 1357 | */ |
| 1363 | if (unlikely(clone_flags & CLONE_STOPPED)) { | 1358 | if (unlikely(clone_flags & CLONE_STOPPED)) { |
| @@ -1605,8 +1600,7 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) | |||
| 1605 | err = -EINVAL; | 1600 | err = -EINVAL; |
| 1606 | if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND| | 1601 | if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND| |
| 1607 | CLONE_VM|CLONE_FILES|CLONE_SYSVSEM| | 1602 | CLONE_VM|CLONE_FILES|CLONE_SYSVSEM| |
| 1608 | CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWUSER| | 1603 | CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET)) |
| 1609 | CLONE_NEWNET)) | ||
| 1610 | goto bad_unshare_out; | 1604 | goto bad_unshare_out; |
| 1611 | 1605 | ||
| 1612 | /* | 1606 | /* |
