diff options
Diffstat (limited to 'kernel/fork.c')
| -rw-r--r-- | kernel/fork.c | 147 | 
1 files changed, 91 insertions, 56 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index b373322ca497..b3f7a1bb5e55 100644 --- a/kernel/fork.c +++ b/kernel/fork.c  | |||
| @@ -84,7 +84,7 @@ static kmem_cache_t *task_struct_cachep; | |||
| 84 | #endif | 84 | #endif | 
| 85 | 85 | ||
| 86 | /* SLAB cache for signal_struct structures (tsk->signal) */ | 86 | /* SLAB cache for signal_struct structures (tsk->signal) */ | 
| 87 | kmem_cache_t *signal_cachep; | 87 | static kmem_cache_t *signal_cachep; | 
| 88 | 88 | ||
| 89 | /* SLAB cache for sighand_struct structures (tsk->sighand) */ | 89 | /* SLAB cache for sighand_struct structures (tsk->sighand) */ | 
| 90 | kmem_cache_t *sighand_cachep; | 90 | kmem_cache_t *sighand_cachep; | 
| @@ -181,6 +181,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) | |||
| 181 | /* One for us, one for whoever does the "release_task()" (usually parent) */ | 181 | /* One for us, one for whoever does the "release_task()" (usually parent) */ | 
| 182 | atomic_set(&tsk->usage,2); | 182 | atomic_set(&tsk->usage,2); | 
| 183 | atomic_set(&tsk->fs_excl, 0); | 183 | atomic_set(&tsk->fs_excl, 0); | 
| 184 | tsk->btrace_seq = 0; | ||
| 184 | return tsk; | 185 | return tsk; | 
| 185 | } | 186 | } | 
| 186 | 187 | ||
| @@ -607,12 +608,12 @@ static struct files_struct *alloc_files(void) | |||
| 607 | atomic_set(&newf->count, 1); | 608 | atomic_set(&newf->count, 1); | 
| 608 | 609 | ||
| 609 | spin_lock_init(&newf->file_lock); | 610 | spin_lock_init(&newf->file_lock); | 
| 611 | newf->next_fd = 0; | ||
| 610 | fdt = &newf->fdtab; | 612 | fdt = &newf->fdtab; | 
| 611 | fdt->next_fd = 0; | ||
| 612 | fdt->max_fds = NR_OPEN_DEFAULT; | 613 | fdt->max_fds = NR_OPEN_DEFAULT; | 
| 613 | fdt->max_fdset = __FD_SETSIZE; | 614 | fdt->max_fdset = EMBEDDED_FD_SET_SIZE; | 
| 614 | fdt->close_on_exec = &newf->close_on_exec_init; | 615 | fdt->close_on_exec = (fd_set *)&newf->close_on_exec_init; | 
| 615 | fdt->open_fds = &newf->open_fds_init; | 616 | fdt->open_fds = (fd_set *)&newf->open_fds_init; | 
| 616 | fdt->fd = &newf->fd_array[0]; | 617 | fdt->fd = &newf->fd_array[0]; | 
| 617 | INIT_RCU_HEAD(&fdt->rcu); | 618 | INIT_RCU_HEAD(&fdt->rcu); | 
| 618 | fdt->free_files = NULL; | 619 | fdt->free_files = NULL; | 
| @@ -768,8 +769,7 @@ int unshare_files(void) | |||
| 768 | struct files_struct *files = current->files; | 769 | struct files_struct *files = current->files; | 
| 769 | int rc; | 770 | int rc; | 
| 770 | 771 | ||
| 771 | if(!files) | 772 | BUG_ON(!files); | 
| 772 | BUG(); | ||
| 773 | 773 | ||
| 774 | /* This can race but the race causes us to copy when we don't | 774 | /* This can race but the race causes us to copy when we don't | 
| 775 | need to and drop the copy */ | 775 | need to and drop the copy */ | 
| @@ -786,14 +786,6 @@ int unshare_files(void) | |||
| 786 | 786 | ||
| 787 | EXPORT_SYMBOL(unshare_files); | 787 | EXPORT_SYMBOL(unshare_files); | 
| 788 | 788 | ||
| 789 | void sighand_free_cb(struct rcu_head *rhp) | ||
| 790 | { | ||
| 791 | struct sighand_struct *sp; | ||
| 792 | |||
| 793 | sp = container_of(rhp, struct sighand_struct, rcu); | ||
| 794 | kmem_cache_free(sighand_cachep, sp); | ||
| 795 | } | ||
| 796 | |||
| 797 | static inline int copy_sighand(unsigned long clone_flags, struct task_struct * tsk) | 789 | static inline int copy_sighand(unsigned long clone_flags, struct task_struct * tsk) | 
| 798 | { | 790 | { | 
| 799 | struct sighand_struct *sig; | 791 | struct sighand_struct *sig; | 
| @@ -806,12 +798,17 @@ static inline int copy_sighand(unsigned long clone_flags, struct task_struct * t | |||
| 806 | rcu_assign_pointer(tsk->sighand, sig); | 798 | rcu_assign_pointer(tsk->sighand, sig); | 
| 807 | if (!sig) | 799 | if (!sig) | 
| 808 | return -ENOMEM; | 800 | return -ENOMEM; | 
| 809 | spin_lock_init(&sig->siglock); | ||
| 810 | atomic_set(&sig->count, 1); | 801 | atomic_set(&sig->count, 1); | 
| 811 | memcpy(sig->action, current->sighand->action, sizeof(sig->action)); | 802 | memcpy(sig->action, current->sighand->action, sizeof(sig->action)); | 
| 812 | return 0; | 803 | return 0; | 
| 813 | } | 804 | } | 
| 814 | 805 | ||
| 806 | void __cleanup_sighand(struct sighand_struct *sighand) | ||
| 807 | { | ||
| 808 | if (atomic_dec_and_test(&sighand->count)) | ||
| 809 | kmem_cache_free(sighand_cachep, sighand); | ||
| 810 | } | ||
| 811 | |||
| 815 | static inline int copy_signal(unsigned long clone_flags, struct task_struct * tsk) | 812 | static inline int copy_signal(unsigned long clone_flags, struct task_struct * tsk) | 
| 816 | { | 813 | { | 
| 817 | struct signal_struct *sig; | 814 | struct signal_struct *sig; | 
| @@ -847,7 +844,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts | |||
| 847 | hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_REL); | 844 | hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_REL); | 
| 848 | sig->it_real_incr.tv64 = 0; | 845 | sig->it_real_incr.tv64 = 0; | 
| 849 | sig->real_timer.function = it_real_fn; | 846 | sig->real_timer.function = it_real_fn; | 
| 850 | sig->real_timer.data = tsk; | 847 | sig->tsk = tsk; | 
| 851 | 848 | ||
| 852 | sig->it_virt_expires = cputime_zero; | 849 | sig->it_virt_expires = cputime_zero; | 
| 853 | sig->it_virt_incr = cputime_zero; | 850 | sig->it_virt_incr = cputime_zero; | 
| @@ -881,6 +878,22 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts | |||
| 881 | return 0; | 878 | return 0; | 
| 882 | } | 879 | } | 
| 883 | 880 | ||
| 881 | void __cleanup_signal(struct signal_struct *sig) | ||
| 882 | { | ||
| 883 | exit_thread_group_keys(sig); | ||
| 884 | kmem_cache_free(signal_cachep, sig); | ||
| 885 | } | ||
| 886 | |||
| 887 | static inline void cleanup_signal(struct task_struct *tsk) | ||
| 888 | { | ||
| 889 | struct signal_struct *sig = tsk->signal; | ||
| 890 | |||
| 891 | atomic_dec(&sig->live); | ||
| 892 | |||
| 893 | if (atomic_dec_and_test(&sig->count)) | ||
| 894 | __cleanup_signal(sig); | ||
| 895 | } | ||
| 896 | |||
| 884 | static inline void copy_flags(unsigned long clone_flags, struct task_struct *p) | 897 | static inline void copy_flags(unsigned long clone_flags, struct task_struct *p) | 
| 885 | { | 898 | { | 
| 886 | unsigned long new_flags = p->flags; | 899 | unsigned long new_flags = p->flags; | 
| @@ -1020,6 +1033,7 @@ static task_t *copy_process(unsigned long clone_flags, | |||
| 1020 | p->mempolicy = NULL; | 1033 | p->mempolicy = NULL; | 
| 1021 | goto bad_fork_cleanup_cpuset; | 1034 | goto bad_fork_cleanup_cpuset; | 
| 1022 | } | 1035 | } | 
| 1036 | mpol_fix_fork_child_flag(p); | ||
| 1023 | #endif | 1037 | #endif | 
| 1024 | 1038 | ||
| 1025 | #ifdef CONFIG_DEBUG_MUTEXES | 1039 | #ifdef CONFIG_DEBUG_MUTEXES | 
| @@ -1060,7 +1074,10 @@ static task_t *copy_process(unsigned long clone_flags, | |||
| 1060 | * Clear TID on mm_release()? | 1074 | * Clear TID on mm_release()? | 
| 1061 | */ | 1075 | */ | 
| 1062 | p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL; | 1076 | p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL; | 
| 1063 | 1077 | p->robust_list = NULL; | |
| 1078 | #ifdef CONFIG_COMPAT | ||
| 1079 | p->compat_robust_list = NULL; | ||
| 1080 | #endif | ||
| 1064 | /* | 1081 | /* | 
| 1065 | * sigaltstack should be cleared when sharing the same VM | 1082 | * sigaltstack should be cleared when sharing the same VM | 
| 1066 | */ | 1083 | */ | 
| @@ -1091,6 +1108,7 @@ static task_t *copy_process(unsigned long clone_flags, | |||
| 1091 | * We dont wake it up yet. | 1108 | * We dont wake it up yet. | 
| 1092 | */ | 1109 | */ | 
| 1093 | p->group_leader = p; | 1110 | p->group_leader = p; | 
| 1111 | INIT_LIST_HEAD(&p->thread_group); | ||
| 1094 | INIT_LIST_HEAD(&p->ptrace_children); | 1112 | INIT_LIST_HEAD(&p->ptrace_children); | 
| 1095 | INIT_LIST_HEAD(&p->ptrace_list); | 1113 | INIT_LIST_HEAD(&p->ptrace_list); | 
| 1096 | 1114 | ||
| @@ -1114,16 +1132,6 @@ static task_t *copy_process(unsigned long clone_flags, | |||
| 1114 | !cpu_online(task_cpu(p)))) | 1132 | !cpu_online(task_cpu(p)))) | 
| 1115 | set_task_cpu(p, smp_processor_id()); | 1133 | set_task_cpu(p, smp_processor_id()); | 
| 1116 | 1134 | ||
| 1117 | /* | ||
| 1118 | * Check for pending SIGKILL! The new thread should not be allowed | ||
| 1119 | * to slip out of an OOM kill. (or normal SIGKILL.) | ||
| 1120 | */ | ||
| 1121 | if (sigismember(¤t->pending.signal, SIGKILL)) { | ||
| 1122 | write_unlock_irq(&tasklist_lock); | ||
| 1123 | retval = -EINTR; | ||
| 1124 | goto bad_fork_cleanup_namespace; | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | /* CLONE_PARENT re-uses the old parent */ | 1135 | /* CLONE_PARENT re-uses the old parent */ | 
| 1128 | if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) | 1136 | if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) | 
| 1129 | p->real_parent = current->real_parent; | 1137 | p->real_parent = current->real_parent; | 
| @@ -1132,6 +1140,23 @@ static task_t *copy_process(unsigned long clone_flags, | |||
| 1132 | p->parent = p->real_parent; | 1140 | p->parent = p->real_parent; | 
| 1133 | 1141 | ||
| 1134 | spin_lock(¤t->sighand->siglock); | 1142 | spin_lock(¤t->sighand->siglock); | 
| 1143 | |||
| 1144 | /* | ||
| 1145 | * Process group and session signals need to be delivered to just the | ||
| 1146 | * parent before the fork or both the parent and the child after the | ||
| 1147 | * fork. Restart if a signal comes in before we add the new process to | ||
| 1148 | * it's process group. | ||
| 1149 | * A fatal signal pending means that current will exit, so the new | ||
| 1150 | * thread can't slip out of an OOM kill (or normal SIGKILL). | ||
| 1151 | */ | ||
| 1152 | recalc_sigpending(); | ||
| 1153 | if (signal_pending(current)) { | ||
| 1154 | spin_unlock(¤t->sighand->siglock); | ||
| 1155 | write_unlock_irq(&tasklist_lock); | ||
| 1156 | retval = -ERESTARTNOINTR; | ||
| 1157 | goto bad_fork_cleanup_namespace; | ||
| 1158 | } | ||
| 1159 | |||
| 1135 | if (clone_flags & CLONE_THREAD) { | 1160 | if (clone_flags & CLONE_THREAD) { | 
| 1136 | /* | 1161 | /* | 
| 1137 | * Important: if an exit-all has been started then | 1162 | * Important: if an exit-all has been started then | 
| @@ -1144,17 +1169,9 @@ static task_t *copy_process(unsigned long clone_flags, | |||
| 1144 | retval = -EAGAIN; | 1169 | retval = -EAGAIN; | 
| 1145 | goto bad_fork_cleanup_namespace; | 1170 | goto bad_fork_cleanup_namespace; | 
| 1146 | } | 1171 | } | 
| 1147 | p->group_leader = current->group_leader; | ||
| 1148 | 1172 | ||
| 1149 | if (current->signal->group_stop_count > 0) { | 1173 | p->group_leader = current->group_leader; | 
| 1150 | /* | 1174 | list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group); | 
| 1151 | * There is an all-stop in progress for the group. | ||
| 1152 | * We ourselves will stop as soon as we check signals. | ||
| 1153 | * Make the new thread part of that group stop too. | ||
| 1154 | */ | ||
| 1155 | current->signal->group_stop_count++; | ||
| 1156 | set_tsk_thread_flag(p, TIF_SIGPENDING); | ||
| 1157 | } | ||
| 1158 | 1175 | ||
| 1159 | if (!cputime_eq(current->signal->it_virt_expires, | 1176 | if (!cputime_eq(current->signal->it_virt_expires, | 
| 1160 | cputime_zero) || | 1177 | cputime_zero) || | 
| @@ -1177,23 +1194,25 @@ static task_t *copy_process(unsigned long clone_flags, | |||
| 1177 | */ | 1194 | */ | 
| 1178 | p->ioprio = current->ioprio; | 1195 | p->ioprio = current->ioprio; | 
| 1179 | 1196 | ||
| 1180 | SET_LINKS(p); | 1197 | if (likely(p->pid)) { | 
| 1181 | if (unlikely(p->ptrace & PT_PTRACED)) | 1198 | add_parent(p); | 
| 1182 | __ptrace_link(p, current->parent); | 1199 | if (unlikely(p->ptrace & PT_PTRACED)) | 
| 1183 | 1200 | __ptrace_link(p, current->parent); | |
| 1184 | if (thread_group_leader(p)) { | 1201 | |
| 1185 | p->signal->tty = current->signal->tty; | 1202 | if (thread_group_leader(p)) { | 
| 1186 | p->signal->pgrp = process_group(current); | 1203 | p->signal->tty = current->signal->tty; | 
| 1187 | p->signal->session = current->signal->session; | 1204 | p->signal->pgrp = process_group(current); | 
| 1188 | attach_pid(p, PIDTYPE_PGID, process_group(p)); | 1205 | p->signal->session = current->signal->session; | 
| 1189 | attach_pid(p, PIDTYPE_SID, p->signal->session); | 1206 | attach_pid(p, PIDTYPE_PGID, process_group(p)); | 
| 1190 | if (p->pid) | 1207 | attach_pid(p, PIDTYPE_SID, p->signal->session); | 
| 1208 | |||
| 1209 | list_add_tail(&p->tasks, &init_task.tasks); | ||
| 1191 | __get_cpu_var(process_counts)++; | 1210 | __get_cpu_var(process_counts)++; | 
| 1211 | } | ||
| 1212 | attach_pid(p, PIDTYPE_PID, p->pid); | ||
| 1213 | nr_threads++; | ||
| 1192 | } | 1214 | } | 
| 1193 | attach_pid(p, PIDTYPE_TGID, p->tgid); | ||
| 1194 | attach_pid(p, PIDTYPE_PID, p->pid); | ||
| 1195 | 1215 | ||
| 1196 | nr_threads++; | ||
| 1197 | total_forks++; | 1216 | total_forks++; | 
| 1198 | spin_unlock(¤t->sighand->siglock); | 1217 | spin_unlock(¤t->sighand->siglock); | 
| 1199 | write_unlock_irq(&tasklist_lock); | 1218 | write_unlock_irq(&tasklist_lock); | 
| @@ -1208,9 +1227,9 @@ bad_fork_cleanup_mm: | |||
| 1208 | if (p->mm) | 1227 | if (p->mm) | 
| 1209 | mmput(p->mm); | 1228 | mmput(p->mm); | 
| 1210 | bad_fork_cleanup_signal: | 1229 | bad_fork_cleanup_signal: | 
| 1211 | exit_signal(p); | 1230 | cleanup_signal(p); | 
| 1212 | bad_fork_cleanup_sighand: | 1231 | bad_fork_cleanup_sighand: | 
| 1213 | exit_sighand(p); | 1232 | __cleanup_sighand(p->sighand); | 
| 1214 | bad_fork_cleanup_fs: | 1233 | bad_fork_cleanup_fs: | 
| 1215 | exit_fs(p); /* blocking */ | 1234 | exit_fs(p); /* blocking */ | 
| 1216 | bad_fork_cleanup_files: | 1235 | bad_fork_cleanup_files: | 
| @@ -1257,7 +1276,7 @@ task_t * __devinit fork_idle(int cpu) | |||
| 1257 | if (!task) | 1276 | if (!task) | 
| 1258 | return ERR_PTR(-ENOMEM); | 1277 | return ERR_PTR(-ENOMEM); | 
| 1259 | init_idle(task, cpu); | 1278 | init_idle(task, cpu); | 
| 1260 | unhash_process(task); | 1279 | |
| 1261 | return task; | 1280 | return task; | 
| 1262 | } | 1281 | } | 
| 1263 | 1282 | ||
| @@ -1349,11 +1368,21 @@ long do_fork(unsigned long clone_flags, | |||
| 1349 | #define ARCH_MIN_MMSTRUCT_ALIGN 0 | 1368 | #define ARCH_MIN_MMSTRUCT_ALIGN 0 | 
| 1350 | #endif | 1369 | #endif | 
| 1351 | 1370 | ||
| 1371 | static void sighand_ctor(void *data, kmem_cache_t *cachep, unsigned long flags) | ||
| 1372 | { | ||
| 1373 | struct sighand_struct *sighand = data; | ||
| 1374 | |||
| 1375 | if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) == | ||
| 1376 | SLAB_CTOR_CONSTRUCTOR) | ||
| 1377 | spin_lock_init(&sighand->siglock); | ||
| 1378 | } | ||
| 1379 | |||
| 1352 | void __init proc_caches_init(void) | 1380 | void __init proc_caches_init(void) | 
| 1353 | { | 1381 | { | 
| 1354 | sighand_cachep = kmem_cache_create("sighand_cache", | 1382 | sighand_cachep = kmem_cache_create("sighand_cache", | 
| 1355 | sizeof(struct sighand_struct), 0, | 1383 | sizeof(struct sighand_struct), 0, | 
| 1356 | SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); | 1384 | SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_DESTROY_BY_RCU, | 
| 1385 | sighand_ctor, NULL); | ||
| 1357 | signal_cachep = kmem_cache_create("signal_cache", | 1386 | signal_cachep = kmem_cache_create("signal_cache", | 
| 1358 | sizeof(struct signal_struct), 0, | 1387 | sizeof(struct signal_struct), 0, | 
| 1359 | SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); | 1388 | SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); | 
| @@ -1534,6 +1563,12 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) | |||
| 1534 | 1563 | ||
| 1535 | check_unshare_flags(&unshare_flags); | 1564 | check_unshare_flags(&unshare_flags); | 
| 1536 | 1565 | ||
| 1566 | /* Return -EINVAL for all unsupported flags */ | ||
| 1567 | err = -EINVAL; | ||
| 1568 | if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND| | ||
| 1569 | CLONE_VM|CLONE_FILES|CLONE_SYSVSEM)) | ||
| 1570 | goto bad_unshare_out; | ||
| 1571 | |||
| 1537 | if ((err = unshare_thread(unshare_flags))) | 1572 | if ((err = unshare_thread(unshare_flags))) | 
| 1538 | goto bad_unshare_out; | 1573 | goto bad_unshare_out; | 
| 1539 | if ((err = unshare_fs(unshare_flags, &new_fs))) | 1574 | if ((err = unshare_fs(unshare_flags, &new_fs))) | 
