diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 165 |
1 files changed, 80 insertions, 85 deletions
@@ -29,6 +29,7 @@ | |||
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/string.h> | ||
32 | #include <linux/init.h> | 33 | #include <linux/init.h> |
33 | #include <linux/pagemap.h> | 34 | #include <linux/pagemap.h> |
34 | #include <linux/highmem.h> | 35 | #include <linux/highmem.h> |
@@ -63,52 +64,28 @@ int core_uses_pid; | |||
63 | char core_pattern[CORENAME_MAX_SIZE] = "core"; | 64 | char core_pattern[CORENAME_MAX_SIZE] = "core"; |
64 | int suid_dumpable = 0; | 65 | int suid_dumpable = 0; |
65 | 66 | ||
66 | EXPORT_SYMBOL(suid_dumpable); | ||
67 | /* The maximal length of core_pattern is also specified in sysctl.c */ | 67 | /* The maximal length of core_pattern is also specified in sysctl.c */ |
68 | 68 | ||
69 | static struct linux_binfmt *formats; | 69 | static LIST_HEAD(formats); |
70 | static DEFINE_RWLOCK(binfmt_lock); | 70 | static DEFINE_RWLOCK(binfmt_lock); |
71 | 71 | ||
72 | int register_binfmt(struct linux_binfmt * fmt) | 72 | int register_binfmt(struct linux_binfmt * fmt) |
73 | { | 73 | { |
74 | struct linux_binfmt ** tmp = &formats; | ||
75 | |||
76 | if (!fmt) | 74 | if (!fmt) |
77 | return -EINVAL; | 75 | return -EINVAL; |
78 | if (fmt->next) | ||
79 | return -EBUSY; | ||
80 | write_lock(&binfmt_lock); | 76 | write_lock(&binfmt_lock); |
81 | while (*tmp) { | 77 | list_add(&fmt->lh, &formats); |
82 | if (fmt == *tmp) { | ||
83 | write_unlock(&binfmt_lock); | ||
84 | return -EBUSY; | ||
85 | } | ||
86 | tmp = &(*tmp)->next; | ||
87 | } | ||
88 | fmt->next = formats; | ||
89 | formats = fmt; | ||
90 | write_unlock(&binfmt_lock); | 78 | write_unlock(&binfmt_lock); |
91 | return 0; | 79 | return 0; |
92 | } | 80 | } |
93 | 81 | ||
94 | EXPORT_SYMBOL(register_binfmt); | 82 | EXPORT_SYMBOL(register_binfmt); |
95 | 83 | ||
96 | int unregister_binfmt(struct linux_binfmt * fmt) | 84 | void unregister_binfmt(struct linux_binfmt * fmt) |
97 | { | 85 | { |
98 | struct linux_binfmt ** tmp = &formats; | ||
99 | |||
100 | write_lock(&binfmt_lock); | 86 | write_lock(&binfmt_lock); |
101 | while (*tmp) { | 87 | list_del(&fmt->lh); |
102 | if (fmt == *tmp) { | ||
103 | *tmp = fmt->next; | ||
104 | fmt->next = NULL; | ||
105 | write_unlock(&binfmt_lock); | ||
106 | return 0; | ||
107 | } | ||
108 | tmp = &(*tmp)->next; | ||
109 | } | ||
110 | write_unlock(&binfmt_lock); | 88 | write_unlock(&binfmt_lock); |
111 | return -EINVAL; | ||
112 | } | 89 | } |
113 | 90 | ||
114 | EXPORT_SYMBOL(unregister_binfmt); | 91 | EXPORT_SYMBOL(unregister_binfmt); |
@@ -134,9 +111,6 @@ asmlinkage long sys_uselib(const char __user * library) | |||
134 | if (error) | 111 | if (error) |
135 | goto out; | 112 | goto out; |
136 | 113 | ||
137 | error = -EACCES; | ||
138 | if (nd.mnt->mnt_flags & MNT_NOEXEC) | ||
139 | goto exit; | ||
140 | error = -EINVAL; | 114 | error = -EINVAL; |
141 | if (!S_ISREG(nd.dentry->d_inode->i_mode)) | 115 | if (!S_ISREG(nd.dentry->d_inode->i_mode)) |
142 | goto exit; | 116 | goto exit; |
@@ -155,7 +129,7 @@ asmlinkage long sys_uselib(const char __user * library) | |||
155 | struct linux_binfmt * fmt; | 129 | struct linux_binfmt * fmt; |
156 | 130 | ||
157 | read_lock(&binfmt_lock); | 131 | read_lock(&binfmt_lock); |
158 | for (fmt = formats ; fmt ; fmt = fmt->next) { | 132 | list_for_each_entry(fmt, &formats, lh) { |
159 | if (!fmt->load_shlib) | 133 | if (!fmt->load_shlib) |
160 | continue; | 134 | continue; |
161 | if (!try_module_get(fmt->module)) | 135 | if (!try_module_get(fmt->module)) |
@@ -680,8 +654,7 @@ struct file *open_exec(const char *name) | |||
680 | if (!err) { | 654 | if (!err) { |
681 | struct inode *inode = nd.dentry->d_inode; | 655 | struct inode *inode = nd.dentry->d_inode; |
682 | file = ERR_PTR(-EACCES); | 656 | file = ERR_PTR(-EACCES); |
683 | if (!(nd.mnt->mnt_flags & MNT_NOEXEC) && | 657 | if (S_ISREG(inode->i_mode)) { |
684 | S_ISREG(inode->i_mode)) { | ||
685 | int err = vfs_permission(&nd, MAY_EXEC); | 658 | int err = vfs_permission(&nd, MAY_EXEC); |
686 | file = ERR_PTR(err); | 659 | file = ERR_PTR(err); |
687 | if (!err) { | 660 | if (!err) { |
@@ -773,24 +746,11 @@ static int exec_mmap(struct mm_struct *mm) | |||
773 | static int de_thread(struct task_struct *tsk) | 746 | static int de_thread(struct task_struct *tsk) |
774 | { | 747 | { |
775 | struct signal_struct *sig = tsk->signal; | 748 | struct signal_struct *sig = tsk->signal; |
776 | struct sighand_struct *newsighand, *oldsighand = tsk->sighand; | 749 | struct sighand_struct *oldsighand = tsk->sighand; |
777 | spinlock_t *lock = &oldsighand->siglock; | 750 | spinlock_t *lock = &oldsighand->siglock; |
778 | struct task_struct *leader = NULL; | 751 | struct task_struct *leader = NULL; |
779 | int count; | 752 | int count; |
780 | 753 | ||
781 | /* | ||
782 | * If we don't share sighandlers, then we aren't sharing anything | ||
783 | * and we can just re-use it all. | ||
784 | */ | ||
785 | if (atomic_read(&oldsighand->count) <= 1) { | ||
786 | exit_itimers(sig); | ||
787 | return 0; | ||
788 | } | ||
789 | |||
790 | newsighand = kmem_cache_alloc(sighand_cachep, GFP_KERNEL); | ||
791 | if (!newsighand) | ||
792 | return -ENOMEM; | ||
793 | |||
794 | if (thread_group_empty(tsk)) | 754 | if (thread_group_empty(tsk)) |
795 | goto no_thread_group; | 755 | goto no_thread_group; |
796 | 756 | ||
@@ -807,7 +767,6 @@ static int de_thread(struct task_struct *tsk) | |||
807 | */ | 767 | */ |
808 | spin_unlock_irq(lock); | 768 | spin_unlock_irq(lock); |
809 | read_unlock(&tasklist_lock); | 769 | read_unlock(&tasklist_lock); |
810 | kmem_cache_free(sighand_cachep, newsighand); | ||
811 | return -EAGAIN; | 770 | return -EAGAIN; |
812 | } | 771 | } |
813 | 772 | ||
@@ -841,16 +800,15 @@ static int de_thread(struct task_struct *tsk) | |||
841 | hrtimer_restart(&sig->real_timer); | 800 | hrtimer_restart(&sig->real_timer); |
842 | spin_lock_irq(lock); | 801 | spin_lock_irq(lock); |
843 | } | 802 | } |
803 | |||
804 | sig->notify_count = count; | ||
805 | sig->group_exit_task = tsk; | ||
844 | while (atomic_read(&sig->count) > count) { | 806 | while (atomic_read(&sig->count) > count) { |
845 | sig->group_exit_task = tsk; | ||
846 | sig->notify_count = count; | ||
847 | __set_current_state(TASK_UNINTERRUPTIBLE); | 807 | __set_current_state(TASK_UNINTERRUPTIBLE); |
848 | spin_unlock_irq(lock); | 808 | spin_unlock_irq(lock); |
849 | schedule(); | 809 | schedule(); |
850 | spin_lock_irq(lock); | 810 | spin_lock_irq(lock); |
851 | } | 811 | } |
852 | sig->group_exit_task = NULL; | ||
853 | sig->notify_count = 0; | ||
854 | spin_unlock_irq(lock); | 812 | spin_unlock_irq(lock); |
855 | 813 | ||
856 | /* | 814 | /* |
@@ -859,14 +817,17 @@ static int de_thread(struct task_struct *tsk) | |||
859 | * and to assume its PID: | 817 | * and to assume its PID: |
860 | */ | 818 | */ |
861 | if (!thread_group_leader(tsk)) { | 819 | if (!thread_group_leader(tsk)) { |
862 | /* | ||
863 | * Wait for the thread group leader to be a zombie. | ||
864 | * It should already be zombie at this point, most | ||
865 | * of the time. | ||
866 | */ | ||
867 | leader = tsk->group_leader; | 820 | leader = tsk->group_leader; |
868 | while (leader->exit_state != EXIT_ZOMBIE) | 821 | |
869 | yield(); | 822 | sig->notify_count = -1; |
823 | for (;;) { | ||
824 | write_lock_irq(&tasklist_lock); | ||
825 | if (likely(leader->exit_state)) | ||
826 | break; | ||
827 | __set_current_state(TASK_UNINTERRUPTIBLE); | ||
828 | write_unlock_irq(&tasklist_lock); | ||
829 | schedule(); | ||
830 | } | ||
870 | 831 | ||
871 | /* | 832 | /* |
872 | * The only record we have of the real-time age of a | 833 | * The only record we have of the real-time age of a |
@@ -880,8 +841,6 @@ static int de_thread(struct task_struct *tsk) | |||
880 | */ | 841 | */ |
881 | tsk->start_time = leader->start_time; | 842 | tsk->start_time = leader->start_time; |
882 | 843 | ||
883 | write_lock_irq(&tasklist_lock); | ||
884 | |||
885 | BUG_ON(leader->tgid != tsk->tgid); | 844 | BUG_ON(leader->tgid != tsk->tgid); |
886 | BUG_ON(tsk->pid == tsk->tgid); | 845 | BUG_ON(tsk->pid == tsk->tgid); |
887 | /* | 846 | /* |
@@ -914,6 +873,8 @@ static int de_thread(struct task_struct *tsk) | |||
914 | write_unlock_irq(&tasklist_lock); | 873 | write_unlock_irq(&tasklist_lock); |
915 | } | 874 | } |
916 | 875 | ||
876 | sig->group_exit_task = NULL; | ||
877 | sig->notify_count = 0; | ||
917 | /* | 878 | /* |
918 | * There may be one thread left which is just exiting, | 879 | * There may be one thread left which is just exiting, |
919 | * but it's safe to stop telling the group to kill themselves. | 880 | * but it's safe to stop telling the group to kill themselves. |
@@ -925,29 +886,23 @@ no_thread_group: | |||
925 | if (leader) | 886 | if (leader) |
926 | release_task(leader); | 887 | release_task(leader); |
927 | 888 | ||
928 | if (atomic_read(&oldsighand->count) == 1) { | 889 | if (atomic_read(&oldsighand->count) != 1) { |
929 | /* | 890 | struct sighand_struct *newsighand; |
930 | * Now that we nuked the rest of the thread group, | ||
931 | * it turns out we are not sharing sighand any more either. | ||
932 | * So we can just keep it. | ||
933 | */ | ||
934 | kmem_cache_free(sighand_cachep, newsighand); | ||
935 | } else { | ||
936 | /* | 891 | /* |
937 | * Move our state over to newsighand and switch it in. | 892 | * This ->sighand is shared with the CLONE_SIGHAND |
893 | * but not CLONE_THREAD task, switch to the new one. | ||
938 | */ | 894 | */ |
895 | newsighand = kmem_cache_alloc(sighand_cachep, GFP_KERNEL); | ||
896 | if (!newsighand) | ||
897 | return -ENOMEM; | ||
898 | |||
939 | atomic_set(&newsighand->count, 1); | 899 | atomic_set(&newsighand->count, 1); |
940 | memcpy(newsighand->action, oldsighand->action, | 900 | memcpy(newsighand->action, oldsighand->action, |
941 | sizeof(newsighand->action)); | 901 | sizeof(newsighand->action)); |
942 | 902 | ||
943 | write_lock_irq(&tasklist_lock); | 903 | write_lock_irq(&tasklist_lock); |
944 | spin_lock(&oldsighand->siglock); | 904 | spin_lock(&oldsighand->siglock); |
945 | spin_lock_nested(&newsighand->siglock, SINGLE_DEPTH_NESTING); | ||
946 | |||
947 | rcu_assign_pointer(tsk->sighand, newsighand); | 905 | rcu_assign_pointer(tsk->sighand, newsighand); |
948 | recalc_sigpending(); | ||
949 | |||
950 | spin_unlock(&newsighand->siglock); | ||
951 | spin_unlock(&oldsighand->siglock); | 906 | spin_unlock(&oldsighand->siglock); |
952 | write_unlock_irq(&tasklist_lock); | 907 | write_unlock_irq(&tasklist_lock); |
953 | 908 | ||
@@ -957,12 +912,11 @@ no_thread_group: | |||
957 | BUG_ON(!thread_group_leader(tsk)); | 912 | BUG_ON(!thread_group_leader(tsk)); |
958 | return 0; | 913 | return 0; |
959 | } | 914 | } |
960 | 915 | ||
961 | /* | 916 | /* |
962 | * These functions flushes out all traces of the currently running executable | 917 | * These functions flushes out all traces of the currently running executable |
963 | * so that a new one can be started | 918 | * so that a new one can be started |
964 | */ | 919 | */ |
965 | |||
966 | static void flush_old_files(struct files_struct * files) | 920 | static void flush_old_files(struct files_struct * files) |
967 | { | 921 | { |
968 | long j = -1; | 922 | long j = -1; |
@@ -1284,7 +1238,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) | |||
1284 | retval = -ENOENT; | 1238 | retval = -ENOENT; |
1285 | for (try=0; try<2; try++) { | 1239 | for (try=0; try<2; try++) { |
1286 | read_lock(&binfmt_lock); | 1240 | read_lock(&binfmt_lock); |
1287 | for (fmt = formats ; fmt ; fmt = fmt->next) { | 1241 | list_for_each_entry(fmt, &formats, lh) { |
1288 | int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary; | 1242 | int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary; |
1289 | if (!fn) | 1243 | if (!fn) |
1290 | continue; | 1244 | continue; |
@@ -1537,6 +1491,14 @@ static int format_corename(char *corename, const char *pattern, long signr) | |||
1537 | goto out; | 1491 | goto out; |
1538 | out_ptr += rc; | 1492 | out_ptr += rc; |
1539 | break; | 1493 | break; |
1494 | /* core limit size */ | ||
1495 | case 'c': | ||
1496 | rc = snprintf(out_ptr, out_end - out_ptr, | ||
1497 | "%lu", current->signal->rlim[RLIMIT_CORE].rlim_cur); | ||
1498 | if (rc > out_end - out_ptr) | ||
1499 | goto out; | ||
1500 | out_ptr += rc; | ||
1501 | break; | ||
1540 | default: | 1502 | default: |
1541 | break; | 1503 | break; |
1542 | } | 1504 | } |
@@ -1699,7 +1661,6 @@ void set_dumpable(struct mm_struct *mm, int value) | |||
1699 | break; | 1661 | break; |
1700 | } | 1662 | } |
1701 | } | 1663 | } |
1702 | EXPORT_SYMBOL_GPL(set_dumpable); | ||
1703 | 1664 | ||
1704 | int get_dumpable(struct mm_struct *mm) | 1665 | int get_dumpable(struct mm_struct *mm) |
1705 | { | 1666 | { |
@@ -1720,6 +1681,10 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1720 | int fsuid = current->fsuid; | 1681 | int fsuid = current->fsuid; |
1721 | int flag = 0; | 1682 | int flag = 0; |
1722 | int ispipe = 0; | 1683 | int ispipe = 0; |
1684 | unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; | ||
1685 | char **helper_argv = NULL; | ||
1686 | int helper_argc = 0; | ||
1687 | char *delimit; | ||
1723 | 1688 | ||
1724 | audit_core_dumps(signr); | 1689 | audit_core_dumps(signr); |
1725 | 1690 | ||
@@ -1753,9 +1718,6 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1753 | */ | 1718 | */ |
1754 | clear_thread_flag(TIF_SIGPENDING); | 1719 | clear_thread_flag(TIF_SIGPENDING); |
1755 | 1720 | ||
1756 | if (current->signal->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump) | ||
1757 | goto fail_unlock; | ||
1758 | |||
1759 | /* | 1721 | /* |
1760 | * lock_kernel() because format_corename() is controlled by sysctl, which | 1722 | * lock_kernel() because format_corename() is controlled by sysctl, which |
1761 | * uses lock_kernel() | 1723 | * uses lock_kernel() |
@@ -1763,9 +1725,39 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1763 | lock_kernel(); | 1725 | lock_kernel(); |
1764 | ispipe = format_corename(corename, core_pattern, signr); | 1726 | ispipe = format_corename(corename, core_pattern, signr); |
1765 | unlock_kernel(); | 1727 | unlock_kernel(); |
1728 | /* | ||
1729 | * Don't bother to check the RLIMIT_CORE value if core_pattern points | ||
1730 | * to a pipe. Since we're not writing directly to the filesystem | ||
1731 | * RLIMIT_CORE doesn't really apply, as no actual core file will be | ||
1732 | * created unless the pipe reader choses to write out the core file | ||
1733 | * at which point file size limits and permissions will be imposed | ||
1734 | * as it does with any other process | ||
1735 | */ | ||
1736 | if ((!ispipe) && (core_limit < binfmt->min_coredump)) | ||
1737 | goto fail_unlock; | ||
1738 | |||
1766 | if (ispipe) { | 1739 | if (ispipe) { |
1740 | helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); | ||
1741 | /* Terminate the string before the first option */ | ||
1742 | delimit = strchr(corename, ' '); | ||
1743 | if (delimit) | ||
1744 | *delimit = '\0'; | ||
1745 | delimit = strrchr(helper_argv[0], '/'); | ||
1746 | if (delimit) | ||
1747 | delimit++; | ||
1748 | else | ||
1749 | delimit = helper_argv[0]; | ||
1750 | if (!strcmp(delimit, current->comm)) { | ||
1751 | printk(KERN_NOTICE "Recursive core dump detected, " | ||
1752 | "aborting\n"); | ||
1753 | goto fail_unlock; | ||
1754 | } | ||
1755 | |||
1756 | core_limit = RLIM_INFINITY; | ||
1757 | |||
1767 | /* SIGPIPE can happen, but it's just never processed */ | 1758 | /* SIGPIPE can happen, but it's just never processed */ |
1768 | if(call_usermodehelper_pipe(corename+1, NULL, NULL, &file)) { | 1759 | if (call_usermodehelper_pipe(corename+1, helper_argv, NULL, |
1760 | &file)) { | ||
1769 | printk(KERN_INFO "Core dump to %s pipe failed\n", | 1761 | printk(KERN_INFO "Core dump to %s pipe failed\n", |
1770 | corename); | 1762 | corename); |
1771 | goto fail_unlock; | 1763 | goto fail_unlock; |
@@ -1793,13 +1785,16 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1793 | if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0) | 1785 | if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0) |
1794 | goto close_fail; | 1786 | goto close_fail; |
1795 | 1787 | ||
1796 | retval = binfmt->core_dump(signr, regs, file); | 1788 | retval = binfmt->core_dump(signr, regs, file, core_limit); |
1797 | 1789 | ||
1798 | if (retval) | 1790 | if (retval) |
1799 | current->signal->group_exit_code |= 0x80; | 1791 | current->signal->group_exit_code |= 0x80; |
1800 | close_fail: | 1792 | close_fail: |
1801 | filp_close(file, NULL); | 1793 | filp_close(file, NULL); |
1802 | fail_unlock: | 1794 | fail_unlock: |
1795 | if (helper_argv) | ||
1796 | argv_free(helper_argv); | ||
1797 | |||
1803 | current->fsuid = fsuid; | 1798 | current->fsuid = fsuid; |
1804 | complete_all(&mm->core_done); | 1799 | complete_all(&mm->core_done); |
1805 | fail: | 1800 | fail: |