diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 235 |
1 files changed, 145 insertions, 90 deletions
@@ -25,10 +25,11 @@ | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/file.h> | 26 | #include <linux/file.h> |
27 | #include <linux/fdtable.h> | 27 | #include <linux/fdtable.h> |
28 | #include <linux/mman.h> | 28 | #include <linux/mm.h> |
29 | #include <linux/stat.h> | 29 | #include <linux/stat.h> |
30 | #include <linux/fcntl.h> | 30 | #include <linux/fcntl.h> |
31 | #include <linux/smp_lock.h> | 31 | #include <linux/smp_lock.h> |
32 | #include <linux/swap.h> | ||
32 | #include <linux/string.h> | 33 | #include <linux/string.h> |
33 | #include <linux/init.h> | 34 | #include <linux/init.h> |
34 | #include <linux/pagemap.h> | 35 | #include <linux/pagemap.h> |
@@ -37,20 +38,18 @@ | |||
37 | #include <linux/key.h> | 38 | #include <linux/key.h> |
38 | #include <linux/personality.h> | 39 | #include <linux/personality.h> |
39 | #include <linux/binfmts.h> | 40 | #include <linux/binfmts.h> |
40 | #include <linux/swap.h> | ||
41 | #include <linux/utsname.h> | 41 | #include <linux/utsname.h> |
42 | #include <linux/pid_namespace.h> | 42 | #include <linux/pid_namespace.h> |
43 | #include <linux/module.h> | 43 | #include <linux/module.h> |
44 | #include <linux/namei.h> | 44 | #include <linux/namei.h> |
45 | #include <linux/proc_fs.h> | 45 | #include <linux/proc_fs.h> |
46 | #include <linux/ptrace.h> | ||
47 | #include <linux/mount.h> | 46 | #include <linux/mount.h> |
48 | #include <linux/security.h> | 47 | #include <linux/security.h> |
49 | #include <linux/syscalls.h> | 48 | #include <linux/syscalls.h> |
50 | #include <linux/rmap.h> | ||
51 | #include <linux/tsacct_kern.h> | 49 | #include <linux/tsacct_kern.h> |
52 | #include <linux/cn_proc.h> | 50 | #include <linux/cn_proc.h> |
53 | #include <linux/audit.h> | 51 | #include <linux/audit.h> |
52 | #include <linux/tracehook.h> | ||
54 | 53 | ||
55 | #include <asm/uaccess.h> | 54 | #include <asm/uaccess.h> |
56 | #include <asm/mmu_context.h> | 55 | #include <asm/mmu_context.h> |
@@ -108,11 +107,17 @@ static inline void put_binfmt(struct linux_binfmt * fmt) | |||
108 | */ | 107 | */ |
109 | asmlinkage long sys_uselib(const char __user * library) | 108 | asmlinkage long sys_uselib(const char __user * library) |
110 | { | 109 | { |
111 | struct file * file; | 110 | struct file *file; |
112 | struct nameidata nd; | 111 | struct nameidata nd; |
113 | int error; | 112 | char *tmp = getname(library); |
114 | 113 | int error = PTR_ERR(tmp); | |
115 | error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC); | 114 | |
115 | if (!IS_ERR(tmp)) { | ||
116 | error = path_lookup_open(AT_FDCWD, tmp, | ||
117 | LOOKUP_FOLLOW, &nd, | ||
118 | FMODE_READ|FMODE_EXEC); | ||
119 | putname(tmp); | ||
120 | } | ||
116 | if (error) | 121 | if (error) |
117 | goto out; | 122 | goto out; |
118 | 123 | ||
@@ -120,7 +125,11 @@ asmlinkage long sys_uselib(const char __user * library) | |||
120 | if (!S_ISREG(nd.path.dentry->d_inode->i_mode)) | 125 | if (!S_ISREG(nd.path.dentry->d_inode->i_mode)) |
121 | goto exit; | 126 | goto exit; |
122 | 127 | ||
123 | error = vfs_permission(&nd, MAY_READ | MAY_EXEC); | 128 | error = -EACCES; |
129 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) | ||
130 | goto exit; | ||
131 | |||
132 | error = vfs_permission(&nd, MAY_READ | MAY_EXEC | MAY_OPEN); | ||
124 | if (error) | 133 | if (error) |
125 | goto exit; | 134 | goto exit; |
126 | 135 | ||
@@ -541,7 +550,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) | |||
541 | /* | 550 | /* |
542 | * when the old and new regions overlap clear from new_end. | 551 | * when the old and new regions overlap clear from new_end. |
543 | */ | 552 | */ |
544 | free_pgd_range(&tlb, new_end, old_end, new_end, | 553 | free_pgd_range(tlb, new_end, old_end, new_end, |
545 | vma->vm_next ? vma->vm_next->vm_start : 0); | 554 | vma->vm_next ? vma->vm_next->vm_start : 0); |
546 | } else { | 555 | } else { |
547 | /* | 556 | /* |
@@ -550,7 +559,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) | |||
550 | * have constraints on va-space that make this illegal (IA64) - | 559 | * have constraints on va-space that make this illegal (IA64) - |
551 | * for the others its just a little faster. | 560 | * for the others its just a little faster. |
552 | */ | 561 | */ |
553 | free_pgd_range(&tlb, old_start, old_end, new_end, | 562 | free_pgd_range(tlb, old_start, old_end, new_end, |
554 | vma->vm_next ? vma->vm_next->vm_start : 0); | 563 | vma->vm_next ? vma->vm_next->vm_start : 0); |
555 | } | 564 | } |
556 | tlb_finish_mmu(tlb, new_end, old_end); | 565 | tlb_finish_mmu(tlb, new_end, old_end); |
@@ -658,38 +667,43 @@ EXPORT_SYMBOL(setup_arg_pages); | |||
658 | struct file *open_exec(const char *name) | 667 | struct file *open_exec(const char *name) |
659 | { | 668 | { |
660 | struct nameidata nd; | 669 | struct nameidata nd; |
661 | int err; | ||
662 | struct file *file; | 670 | struct file *file; |
671 | int err; | ||
663 | 672 | ||
664 | err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC); | 673 | err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, |
665 | file = ERR_PTR(err); | 674 | FMODE_READ|FMODE_EXEC); |
666 | 675 | if (err) | |
667 | if (!err) { | 676 | goto out; |
668 | struct inode *inode = nd.path.dentry->d_inode; | 677 | |
669 | file = ERR_PTR(-EACCES); | 678 | err = -EACCES; |
670 | if (S_ISREG(inode->i_mode)) { | 679 | if (!S_ISREG(nd.path.dentry->d_inode->i_mode)) |
671 | int err = vfs_permission(&nd, MAY_EXEC); | 680 | goto out_path_put; |
672 | file = ERR_PTR(err); | 681 | |
673 | if (!err) { | 682 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) |
674 | file = nameidata_to_filp(&nd, | 683 | goto out_path_put; |
675 | O_RDONLY|O_LARGEFILE); | 684 | |
676 | if (!IS_ERR(file)) { | 685 | err = vfs_permission(&nd, MAY_EXEC | MAY_OPEN); |
677 | err = deny_write_access(file); | 686 | if (err) |
678 | if (err) { | 687 | goto out_path_put; |
679 | fput(file); | 688 | |
680 | file = ERR_PTR(err); | 689 | file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE); |
681 | } | 690 | if (IS_ERR(file)) |
682 | } | 691 | return file; |
683 | out: | 692 | |
684 | return file; | 693 | err = deny_write_access(file); |
685 | } | 694 | if (err) { |
686 | } | 695 | fput(file); |
687 | release_open_intent(&nd); | 696 | goto out; |
688 | path_put(&nd.path); | ||
689 | } | 697 | } |
690 | goto out; | ||
691 | } | ||
692 | 698 | ||
699 | return file; | ||
700 | |||
701 | out_path_put: | ||
702 | release_open_intent(&nd); | ||
703 | path_put(&nd.path); | ||
704 | out: | ||
705 | return ERR_PTR(err); | ||
706 | } | ||
693 | EXPORT_SYMBOL(open_exec); | 707 | EXPORT_SYMBOL(open_exec); |
694 | 708 | ||
695 | int kernel_read(struct file *file, unsigned long offset, | 709 | int kernel_read(struct file *file, unsigned long offset, |
@@ -724,12 +738,10 @@ static int exec_mmap(struct mm_struct *mm) | |||
724 | * Make sure that if there is a core dump in progress | 738 | * Make sure that if there is a core dump in progress |
725 | * for the old mm, we get out and die instead of going | 739 | * for the old mm, we get out and die instead of going |
726 | * through with the exec. We must hold mmap_sem around | 740 | * through with the exec. We must hold mmap_sem around |
727 | * checking core_waiters and changing tsk->mm. The | 741 | * checking core_state and changing tsk->mm. |
728 | * core-inducing thread will increment core_waiters for | ||
729 | * each thread whose ->mm == old_mm. | ||
730 | */ | 742 | */ |
731 | down_read(&old_mm->mmap_sem); | 743 | down_read(&old_mm->mmap_sem); |
732 | if (unlikely(old_mm->core_waiters)) { | 744 | if (unlikely(old_mm->core_state)) { |
733 | up_read(&old_mm->mmap_sem); | 745 | up_read(&old_mm->mmap_sem); |
734 | return -EINTR; | 746 | return -EINTR; |
735 | } | 747 | } |
@@ -1075,13 +1087,8 @@ EXPORT_SYMBOL(prepare_binprm); | |||
1075 | 1087 | ||
1076 | static int unsafe_exec(struct task_struct *p) | 1088 | static int unsafe_exec(struct task_struct *p) |
1077 | { | 1089 | { |
1078 | int unsafe = 0; | 1090 | int unsafe = tracehook_unsafe_exec(p); |
1079 | if (p->ptrace & PT_PTRACED) { | 1091 | |
1080 | if (p->ptrace & PT_PTRACE_CAP) | ||
1081 | unsafe |= LSM_UNSAFE_PTRACE_CAP; | ||
1082 | else | ||
1083 | unsafe |= LSM_UNSAFE_PTRACE; | ||
1084 | } | ||
1085 | if (atomic_read(&p->fs->count) > 1 || | 1092 | if (atomic_read(&p->fs->count) > 1 || |
1086 | atomic_read(&p->files->count) > 1 || | 1093 | atomic_read(&p->files->count) > 1 || |
1087 | atomic_read(&p->sighand->count) > 1) | 1094 | atomic_read(&p->sighand->count) > 1) |
@@ -1218,6 +1225,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) | |||
1218 | read_unlock(&binfmt_lock); | 1225 | read_unlock(&binfmt_lock); |
1219 | retval = fn(bprm, regs); | 1226 | retval = fn(bprm, regs); |
1220 | if (retval >= 0) { | 1227 | if (retval >= 0) { |
1228 | tracehook_report_exec(fmt, bprm, regs); | ||
1221 | put_binfmt(fmt); | 1229 | put_binfmt(fmt); |
1222 | allow_write_access(bprm->file); | 1230 | allow_write_access(bprm->file); |
1223 | if (bprm->file) | 1231 | if (bprm->file) |
@@ -1328,6 +1336,7 @@ int do_execve(char * filename, | |||
1328 | if (retval < 0) | 1336 | if (retval < 0) |
1329 | goto out; | 1337 | goto out; |
1330 | 1338 | ||
1339 | current->flags &= ~PF_KTHREAD; | ||
1331 | retval = search_binary_handler(bprm,regs); | 1340 | retval = search_binary_handler(bprm,regs); |
1332 | if (retval >= 0) { | 1341 | if (retval >= 0) { |
1333 | /* execve success */ | 1342 | /* execve success */ |
@@ -1382,17 +1391,14 @@ EXPORT_SYMBOL(set_binfmt); | |||
1382 | * name into corename, which must have space for at least | 1391 | * name into corename, which must have space for at least |
1383 | * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. | 1392 | * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. |
1384 | */ | 1393 | */ |
1385 | static int format_corename(char *corename, const char *pattern, long signr) | 1394 | static int format_corename(char *corename, int nr_threads, long signr) |
1386 | { | 1395 | { |
1387 | const char *pat_ptr = pattern; | 1396 | const char *pat_ptr = core_pattern; |
1397 | int ispipe = (*pat_ptr == '|'); | ||
1388 | char *out_ptr = corename; | 1398 | char *out_ptr = corename; |
1389 | char *const out_end = corename + CORENAME_MAX_SIZE; | 1399 | char *const out_end = corename + CORENAME_MAX_SIZE; |
1390 | int rc; | 1400 | int rc; |
1391 | int pid_in_pattern = 0; | 1401 | int pid_in_pattern = 0; |
1392 | int ispipe = 0; | ||
1393 | |||
1394 | if (*pattern == '|') | ||
1395 | ispipe = 1; | ||
1396 | 1402 | ||
1397 | /* Repeat as long as we have more pattern to process and more output | 1403 | /* Repeat as long as we have more pattern to process and more output |
1398 | space */ | 1404 | space */ |
@@ -1493,7 +1499,7 @@ static int format_corename(char *corename, const char *pattern, long signr) | |||
1493 | * and core_uses_pid is set, then .%pid will be appended to | 1499 | * and core_uses_pid is set, then .%pid will be appended to |
1494 | * the filename. Do not do this for piped commands. */ | 1500 | * the filename. Do not do this for piped commands. */ |
1495 | if (!ispipe && !pid_in_pattern | 1501 | if (!ispipe && !pid_in_pattern |
1496 | && (core_uses_pid || atomic_read(¤t->mm->mm_users) != 1)) { | 1502 | && (core_uses_pid || nr_threads)) { |
1497 | rc = snprintf(out_ptr, out_end - out_ptr, | 1503 | rc = snprintf(out_ptr, out_end - out_ptr, |
1498 | ".%d", task_tgid_vnr(current)); | 1504 | ".%d", task_tgid_vnr(current)); |
1499 | if (rc > out_end - out_ptr) | 1505 | if (rc > out_end - out_ptr) |
@@ -1505,9 +1511,10 @@ out: | |||
1505 | return ispipe; | 1511 | return ispipe; |
1506 | } | 1512 | } |
1507 | 1513 | ||
1508 | static void zap_process(struct task_struct *start) | 1514 | static int zap_process(struct task_struct *start) |
1509 | { | 1515 | { |
1510 | struct task_struct *t; | 1516 | struct task_struct *t; |
1517 | int nr = 0; | ||
1511 | 1518 | ||
1512 | start->signal->flags = SIGNAL_GROUP_EXIT; | 1519 | start->signal->flags = SIGNAL_GROUP_EXIT; |
1513 | start->signal->group_stop_count = 0; | 1520 | start->signal->group_stop_count = 0; |
@@ -1515,72 +1522,99 @@ static void zap_process(struct task_struct *start) | |||
1515 | t = start; | 1522 | t = start; |
1516 | do { | 1523 | do { |
1517 | if (t != current && t->mm) { | 1524 | if (t != current && t->mm) { |
1518 | t->mm->core_waiters++; | ||
1519 | sigaddset(&t->pending.signal, SIGKILL); | 1525 | sigaddset(&t->pending.signal, SIGKILL); |
1520 | signal_wake_up(t, 1); | 1526 | signal_wake_up(t, 1); |
1527 | nr++; | ||
1521 | } | 1528 | } |
1522 | } while ((t = next_thread(t)) != start); | 1529 | } while_each_thread(start, t); |
1530 | |||
1531 | return nr; | ||
1523 | } | 1532 | } |
1524 | 1533 | ||
1525 | static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm, | 1534 | static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm, |
1526 | int exit_code) | 1535 | struct core_state *core_state, int exit_code) |
1527 | { | 1536 | { |
1528 | struct task_struct *g, *p; | 1537 | struct task_struct *g, *p; |
1529 | unsigned long flags; | 1538 | unsigned long flags; |
1530 | int err = -EAGAIN; | 1539 | int nr = -EAGAIN; |
1531 | 1540 | ||
1532 | spin_lock_irq(&tsk->sighand->siglock); | 1541 | spin_lock_irq(&tsk->sighand->siglock); |
1533 | if (!signal_group_exit(tsk->signal)) { | 1542 | if (!signal_group_exit(tsk->signal)) { |
1543 | mm->core_state = core_state; | ||
1534 | tsk->signal->group_exit_code = exit_code; | 1544 | tsk->signal->group_exit_code = exit_code; |
1535 | zap_process(tsk); | 1545 | nr = zap_process(tsk); |
1536 | err = 0; | ||
1537 | } | 1546 | } |
1538 | spin_unlock_irq(&tsk->sighand->siglock); | 1547 | spin_unlock_irq(&tsk->sighand->siglock); |
1539 | if (err) | 1548 | if (unlikely(nr < 0)) |
1540 | return err; | 1549 | return nr; |
1541 | 1550 | ||
1542 | if (atomic_read(&mm->mm_users) == mm->core_waiters + 1) | 1551 | if (atomic_read(&mm->mm_users) == nr + 1) |
1543 | goto done; | 1552 | goto done; |
1544 | 1553 | /* | |
1554 | * We should find and kill all tasks which use this mm, and we should | ||
1555 | * count them correctly into ->nr_threads. We don't take tasklist | ||
1556 | * lock, but this is safe wrt: | ||
1557 | * | ||
1558 | * fork: | ||
1559 | * None of sub-threads can fork after zap_process(leader). All | ||
1560 | * processes which were created before this point should be | ||
1561 | * visible to zap_threads() because copy_process() adds the new | ||
1562 | * process to the tail of init_task.tasks list, and lock/unlock | ||
1563 | * of ->siglock provides a memory barrier. | ||
1564 | * | ||
1565 | * do_exit: | ||
1566 | * The caller holds mm->mmap_sem. This means that the task which | ||
1567 | * uses this mm can't pass exit_mm(), so it can't exit or clear | ||
1568 | * its ->mm. | ||
1569 | * | ||
1570 | * de_thread: | ||
1571 | * It does list_replace_rcu(&leader->tasks, ¤t->tasks), | ||
1572 | * we must see either old or new leader, this does not matter. | ||
1573 | * However, it can change p->sighand, so lock_task_sighand(p) | ||
1574 | * must be used. Since p->mm != NULL and we hold ->mmap_sem | ||
1575 | * it can't fail. | ||
1576 | * | ||
1577 | * Note also that "g" can be the old leader with ->mm == NULL | ||
1578 | * and already unhashed and thus removed from ->thread_group. | ||
1579 | * This is OK, __unhash_process()->list_del_rcu() does not | ||
1580 | * clear the ->next pointer, we will find the new leader via | ||
1581 | * next_thread(). | ||
1582 | */ | ||
1545 | rcu_read_lock(); | 1583 | rcu_read_lock(); |
1546 | for_each_process(g) { | 1584 | for_each_process(g) { |
1547 | if (g == tsk->group_leader) | 1585 | if (g == tsk->group_leader) |
1548 | continue; | 1586 | continue; |
1549 | 1587 | if (g->flags & PF_KTHREAD) | |
1588 | continue; | ||
1550 | p = g; | 1589 | p = g; |
1551 | do { | 1590 | do { |
1552 | if (p->mm) { | 1591 | if (p->mm) { |
1553 | if (p->mm == mm) { | 1592 | if (unlikely(p->mm == mm)) { |
1554 | /* | ||
1555 | * p->sighand can't disappear, but | ||
1556 | * may be changed by de_thread() | ||
1557 | */ | ||
1558 | lock_task_sighand(p, &flags); | 1593 | lock_task_sighand(p, &flags); |
1559 | zap_process(p); | 1594 | nr += zap_process(p); |
1560 | unlock_task_sighand(p, &flags); | 1595 | unlock_task_sighand(p, &flags); |
1561 | } | 1596 | } |
1562 | break; | 1597 | break; |
1563 | } | 1598 | } |
1564 | } while ((p = next_thread(p)) != g); | 1599 | } while_each_thread(g, p); |
1565 | } | 1600 | } |
1566 | rcu_read_unlock(); | 1601 | rcu_read_unlock(); |
1567 | done: | 1602 | done: |
1568 | return mm->core_waiters; | 1603 | atomic_set(&core_state->nr_threads, nr); |
1604 | return nr; | ||
1569 | } | 1605 | } |
1570 | 1606 | ||
1571 | static int coredump_wait(int exit_code) | 1607 | static int coredump_wait(int exit_code, struct core_state *core_state) |
1572 | { | 1608 | { |
1573 | struct task_struct *tsk = current; | 1609 | struct task_struct *tsk = current; |
1574 | struct mm_struct *mm = tsk->mm; | 1610 | struct mm_struct *mm = tsk->mm; |
1575 | struct completion startup_done; | ||
1576 | struct completion *vfork_done; | 1611 | struct completion *vfork_done; |
1577 | int core_waiters; | 1612 | int core_waiters; |
1578 | 1613 | ||
1579 | init_completion(&mm->core_done); | 1614 | init_completion(&core_state->startup); |
1580 | init_completion(&startup_done); | 1615 | core_state->dumper.task = tsk; |
1581 | mm->core_startup_done = &startup_done; | 1616 | core_state->dumper.next = NULL; |
1582 | 1617 | core_waiters = zap_threads(tsk, mm, core_state, exit_code); | |
1583 | core_waiters = zap_threads(tsk, mm, exit_code); | ||
1584 | up_write(&mm->mmap_sem); | 1618 | up_write(&mm->mmap_sem); |
1585 | 1619 | ||
1586 | if (unlikely(core_waiters < 0)) | 1620 | if (unlikely(core_waiters < 0)) |
@@ -1597,12 +1631,32 @@ static int coredump_wait(int exit_code) | |||
1597 | } | 1631 | } |
1598 | 1632 | ||
1599 | if (core_waiters) | 1633 | if (core_waiters) |
1600 | wait_for_completion(&startup_done); | 1634 | wait_for_completion(&core_state->startup); |
1601 | fail: | 1635 | fail: |
1602 | BUG_ON(mm->core_waiters); | ||
1603 | return core_waiters; | 1636 | return core_waiters; |
1604 | } | 1637 | } |
1605 | 1638 | ||
1639 | static void coredump_finish(struct mm_struct *mm) | ||
1640 | { | ||
1641 | struct core_thread *curr, *next; | ||
1642 | struct task_struct *task; | ||
1643 | |||
1644 | next = mm->core_state->dumper.next; | ||
1645 | while ((curr = next) != NULL) { | ||
1646 | next = curr->next; | ||
1647 | task = curr->task; | ||
1648 | /* | ||
1649 | * see exit_mm(), curr->task must not see | ||
1650 | * ->task == NULL before we read ->next. | ||
1651 | */ | ||
1652 | smp_mb(); | ||
1653 | curr->task = NULL; | ||
1654 | wake_up_process(task); | ||
1655 | } | ||
1656 | |||
1657 | mm->core_state = NULL; | ||
1658 | } | ||
1659 | |||
1606 | /* | 1660 | /* |
1607 | * set_dumpable converts traditional three-value dumpable to two flags and | 1661 | * set_dumpable converts traditional three-value dumpable to two flags and |
1608 | * stores them into mm->flags. It modifies lower two bits of mm->flags, but | 1662 | * stores them into mm->flags. It modifies lower two bits of mm->flags, but |
@@ -1654,6 +1708,7 @@ int get_dumpable(struct mm_struct *mm) | |||
1654 | 1708 | ||
1655 | int do_coredump(long signr, int exit_code, struct pt_regs * regs) | 1709 | int do_coredump(long signr, int exit_code, struct pt_regs * regs) |
1656 | { | 1710 | { |
1711 | struct core_state core_state; | ||
1657 | char corename[CORENAME_MAX_SIZE + 1]; | 1712 | char corename[CORENAME_MAX_SIZE + 1]; |
1658 | struct mm_struct *mm = current->mm; | 1713 | struct mm_struct *mm = current->mm; |
1659 | struct linux_binfmt * binfmt; | 1714 | struct linux_binfmt * binfmt; |
@@ -1677,7 +1732,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1677 | /* | 1732 | /* |
1678 | * If another thread got here first, or we are not dumpable, bail out. | 1733 | * If another thread got here first, or we are not dumpable, bail out. |
1679 | */ | 1734 | */ |
1680 | if (mm->core_waiters || !get_dumpable(mm)) { | 1735 | if (mm->core_state || !get_dumpable(mm)) { |
1681 | up_write(&mm->mmap_sem); | 1736 | up_write(&mm->mmap_sem); |
1682 | goto fail; | 1737 | goto fail; |
1683 | } | 1738 | } |
@@ -1692,7 +1747,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1692 | current->fsuid = 0; /* Dump root private */ | 1747 | current->fsuid = 0; /* Dump root private */ |
1693 | } | 1748 | } |
1694 | 1749 | ||
1695 | retval = coredump_wait(exit_code); | 1750 | retval = coredump_wait(exit_code, &core_state); |
1696 | if (retval < 0) | 1751 | if (retval < 0) |
1697 | goto fail; | 1752 | goto fail; |
1698 | 1753 | ||
@@ -1707,7 +1762,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1707 | * uses lock_kernel() | 1762 | * uses lock_kernel() |
1708 | */ | 1763 | */ |
1709 | lock_kernel(); | 1764 | lock_kernel(); |
1710 | ispipe = format_corename(corename, core_pattern, signr); | 1765 | ispipe = format_corename(corename, retval, signr); |
1711 | unlock_kernel(); | 1766 | unlock_kernel(); |
1712 | /* | 1767 | /* |
1713 | * Don't bother to check the RLIMIT_CORE value if core_pattern points | 1768 | * Don't bother to check the RLIMIT_CORE value if core_pattern points |
@@ -1786,7 +1841,7 @@ fail_unlock: | |||
1786 | argv_free(helper_argv); | 1841 | argv_free(helper_argv); |
1787 | 1842 | ||
1788 | current->fsuid = fsuid; | 1843 | current->fsuid = fsuid; |
1789 | complete_all(&mm->core_done); | 1844 | coredump_finish(mm); |
1790 | fail: | 1845 | fail: |
1791 | return retval; | 1846 | return retval; |
1792 | } | 1847 | } |