aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/exec.c10
-rw-r--r--include/linux/mm_types.h2
-rw-r--r--include/linux/sched.h1
-rw-r--r--kernel/exit.c2
-rw-r--r--kernel/fork.c13
5 files changed, 15 insertions, 13 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 6dc92c39dd9..d49be6bc179 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1397,10 +1397,12 @@ out_ret:
1397 1397
1398void set_binfmt(struct linux_binfmt *new) 1398void set_binfmt(struct linux_binfmt *new)
1399{ 1399{
1400 if (current->binfmt) 1400 struct mm_struct *mm = current->mm;
1401 module_put(current->binfmt->module); 1401
1402 if (mm->binfmt)
1403 module_put(mm->binfmt->module);
1402 1404
1403 current->binfmt = new; 1405 mm->binfmt = new;
1404 if (new) 1406 if (new)
1405 __module_get(new->module); 1407 __module_get(new->module);
1406} 1408}
@@ -1770,7 +1772,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
1770 1772
1771 audit_core_dumps(signr); 1773 audit_core_dumps(signr);
1772 1774
1773 binfmt = current->binfmt; 1775 binfmt = mm->binfmt;
1774 if (!binfmt || !binfmt->core_dump) 1776 if (!binfmt || !binfmt->core_dump)
1775 goto fail; 1777 goto fail;
1776 1778
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 6b7029ab9c8..21d6aa45206 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -240,6 +240,8 @@ struct mm_struct {
240 240
241 unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */ 241 unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
242 242
243 struct linux_binfmt *binfmt;
244
243 cpumask_t cpu_vm_mask; 245 cpumask_t cpu_vm_mask;
244 246
245 /* Architecture-specific MM context */ 247 /* Architecture-specific MM context */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 811cd96524d..8a16f6d11dc 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1271,7 +1271,6 @@ struct task_struct {
1271 struct mm_struct *mm, *active_mm; 1271 struct mm_struct *mm, *active_mm;
1272 1272
1273/* task state */ 1273/* task state */
1274 struct linux_binfmt *binfmt;
1275 int exit_state; 1274 int exit_state;
1276 int exit_code, exit_signal; 1275 int exit_code, exit_signal;
1277 int pdeath_signal; /* The signal sent when the parent dies */ 1276 int pdeath_signal; /* The signal sent when the parent dies */
diff --git a/kernel/exit.c b/kernel/exit.c
index 6c75ff83a8f..5859f598c95 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -976,8 +976,6 @@ NORET_TYPE void do_exit(long code)
976 disassociate_ctty(1); 976 disassociate_ctty(1);
977 977
978 module_put(task_thread_info(tsk)->exec_domain->module); 978 module_put(task_thread_info(tsk)->exec_domain->module);
979 if (tsk->binfmt)
980 module_put(tsk->binfmt->module);
981 979
982 proc_exit_connector(tsk); 980 proc_exit_connector(tsk);
983 981
diff --git a/kernel/fork.c b/kernel/fork.c
index e49f181ba1c..266c6af6ef1 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -518,6 +518,8 @@ void mmput(struct mm_struct *mm)
518 spin_unlock(&mmlist_lock); 518 spin_unlock(&mmlist_lock);
519 } 519 }
520 put_swap_token(mm); 520 put_swap_token(mm);
521 if (mm->binfmt)
522 module_put(mm->binfmt->module);
521 mmdrop(mm); 523 mmdrop(mm);
522 } 524 }
523} 525}
@@ -643,9 +645,14 @@ struct mm_struct *dup_mm(struct task_struct *tsk)
643 mm->hiwater_rss = get_mm_rss(mm); 645 mm->hiwater_rss = get_mm_rss(mm);
644 mm->hiwater_vm = mm->total_vm; 646 mm->hiwater_vm = mm->total_vm;
645 647
648 if (mm->binfmt && !try_module_get(mm->binfmt->module))
649 goto free_pt;
650
646 return mm; 651 return mm;
647 652
648free_pt: 653free_pt:
654 /* don't put binfmt in mmput, we haven't got module yet */
655 mm->binfmt = NULL;
649 mmput(mm); 656 mmput(mm);
650 657
651fail_nomem: 658fail_nomem:
@@ -1037,9 +1044,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1037 if (!try_module_get(task_thread_info(p)->exec_domain->module)) 1044 if (!try_module_get(task_thread_info(p)->exec_domain->module))
1038 goto bad_fork_cleanup_count; 1045 goto bad_fork_cleanup_count;
1039 1046
1040 if (p->binfmt && !try_module_get(p->binfmt->module))
1041 goto bad_fork_cleanup_put_domain;
1042
1043 p->did_exec = 0; 1047 p->did_exec = 0;
1044 delayacct_tsk_init(p); /* Must remain after dup_task_struct() */ 1048 delayacct_tsk_init(p); /* Must remain after dup_task_struct() */
1045 copy_flags(clone_flags, p); 1049 copy_flags(clone_flags, p);
@@ -1327,9 +1331,6 @@ bad_fork_cleanup_cgroup:
1327#endif 1331#endif
1328 cgroup_exit(p, cgroup_callbacks_done); 1332 cgroup_exit(p, cgroup_callbacks_done);
1329 delayacct_tsk_free(p); 1333 delayacct_tsk_free(p);
1330 if (p->binfmt)
1331 module_put(p->binfmt->module);
1332bad_fork_cleanup_put_domain:
1333 module_put(task_thread_info(p)->exec_domain->module); 1334 module_put(task_thread_info(p)->exec_domain->module);
1334bad_fork_cleanup_count: 1335bad_fork_cleanup_count:
1335 atomic_dec(&p->cred->user->processes); 1336 atomic_dec(&p->cred->user->processes);