aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-01-10 20:42:53 -0500
committerIngo Molnar <mingo@elte.hu>2009-01-10 20:42:53 -0500
commit506c10f26c481b7f8ef27c1c79290f68989b2e9e (patch)
tree03de82e812f00957aa6276dac2fe51c3358e88d7 /fs/exec.c
parente1df957670aef74ffd9a4ad93e6d2c90bf6b4845 (diff)
parentc59765042f53a79a7a65585042ff463b69cb248c (diff)
Merge commit 'v2.6.29-rc1' into perfcounters/core
Conflicts: include/linux/kernel_stat.h
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c86
1 files changed, 24 insertions, 62 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 911dd0fd7e09..605be573fe87 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -52,17 +52,13 @@
52#include <linux/audit.h> 52#include <linux/audit.h>
53#include <linux/tracehook.h> 53#include <linux/tracehook.h>
54#include <linux/kmod.h> 54#include <linux/kmod.h>
55#include <linux/fsnotify.h>
55 56
56#include <asm/uaccess.h> 57#include <asm/uaccess.h>
57#include <asm/mmu_context.h> 58#include <asm/mmu_context.h>
58#include <asm/tlb.h> 59#include <asm/tlb.h>
59#include "internal.h" 60#include "internal.h"
60 61
61#ifdef __alpha__
62/* for /sbin/loader handling in search_binary_handler() */
63#include <linux/a.out.h>
64#endif
65
66int core_uses_pid; 62int core_uses_pid;
67char core_pattern[CORENAME_MAX_SIZE] = "core"; 63char core_pattern[CORENAME_MAX_SIZE] = "core";
68int suid_dumpable = 0; 64int suid_dumpable = 0;
@@ -128,7 +124,8 @@ asmlinkage long sys_uselib(const char __user * library)
128 if (nd.path.mnt->mnt_flags & MNT_NOEXEC) 124 if (nd.path.mnt->mnt_flags & MNT_NOEXEC)
129 goto exit; 125 goto exit;
130 126
131 error = vfs_permission(&nd, MAY_READ | MAY_EXEC | MAY_OPEN); 127 error = inode_permission(nd.path.dentry->d_inode,
128 MAY_READ | MAY_EXEC | MAY_OPEN);
132 if (error) 129 if (error)
133 goto exit; 130 goto exit;
134 131
@@ -137,6 +134,8 @@ asmlinkage long sys_uselib(const char __user * library)
137 if (IS_ERR(file)) 134 if (IS_ERR(file))
138 goto out; 135 goto out;
139 136
137 fsnotify_open(file->f_path.dentry);
138
140 error = -ENOEXEC; 139 error = -ENOEXEC;
141 if(file->f_op) { 140 if(file->f_op) {
142 struct linux_binfmt * fmt; 141 struct linux_binfmt * fmt;
@@ -234,13 +233,13 @@ static void flush_arg_page(struct linux_binprm *bprm, unsigned long pos,
234 233
235static int __bprm_mm_init(struct linux_binprm *bprm) 234static int __bprm_mm_init(struct linux_binprm *bprm)
236{ 235{
237 int err = -ENOMEM; 236 int err;
238 struct vm_area_struct *vma = NULL; 237 struct vm_area_struct *vma = NULL;
239 struct mm_struct *mm = bprm->mm; 238 struct mm_struct *mm = bprm->mm;
240 239
241 bprm->vma = vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); 240 bprm->vma = vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
242 if (!vma) 241 if (!vma)
243 goto err; 242 return -ENOMEM;
244 243
245 down_write(&mm->mmap_sem); 244 down_write(&mm->mmap_sem);
246 vma->vm_mm = mm; 245 vma->vm_mm = mm;
@@ -253,28 +252,20 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
253 */ 252 */
254 vma->vm_end = STACK_TOP_MAX; 253 vma->vm_end = STACK_TOP_MAX;
255 vma->vm_start = vma->vm_end - PAGE_SIZE; 254 vma->vm_start = vma->vm_end - PAGE_SIZE;
256
257 vma->vm_flags = VM_STACK_FLAGS; 255 vma->vm_flags = VM_STACK_FLAGS;
258 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); 256 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
259 err = insert_vm_struct(mm, vma); 257 err = insert_vm_struct(mm, vma);
260 if (err) { 258 if (err)
261 up_write(&mm->mmap_sem);
262 goto err; 259 goto err;
263 }
264 260
265 mm->stack_vm = mm->total_vm = 1; 261 mm->stack_vm = mm->total_vm = 1;
266 up_write(&mm->mmap_sem); 262 up_write(&mm->mmap_sem);
267
268 bprm->p = vma->vm_end - sizeof(void *); 263 bprm->p = vma->vm_end - sizeof(void *);
269
270 return 0; 264 return 0;
271
272err: 265err:
273 if (vma) { 266 up_write(&mm->mmap_sem);
274 bprm->vma = NULL; 267 bprm->vma = NULL;
275 kmem_cache_free(vm_area_cachep, vma); 268 kmem_cache_free(vm_area_cachep, vma);
276 }
277
278 return err; 269 return err;
279} 270}
280 271
@@ -681,7 +672,7 @@ struct file *open_exec(const char *name)
681 if (nd.path.mnt->mnt_flags & MNT_NOEXEC) 672 if (nd.path.mnt->mnt_flags & MNT_NOEXEC)
682 goto out_path_put; 673 goto out_path_put;
683 674
684 err = vfs_permission(&nd, MAY_EXEC | MAY_OPEN); 675 err = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_OPEN);
685 if (err) 676 if (err)
686 goto out_path_put; 677 goto out_path_put;
687 678
@@ -689,6 +680,8 @@ struct file *open_exec(const char *name)
689 if (IS_ERR(file)) 680 if (IS_ERR(file))
690 return file; 681 return file;
691 682
683 fsnotify_open(file->f_path.dentry);
684
692 err = deny_write_access(file); 685 err = deny_write_access(file);
693 if (err) { 686 if (err) {
694 fput(file); 687 fput(file);
@@ -774,7 +767,6 @@ static int de_thread(struct task_struct *tsk)
774 struct signal_struct *sig = tsk->signal; 767 struct signal_struct *sig = tsk->signal;
775 struct sighand_struct *oldsighand = tsk->sighand; 768 struct sighand_struct *oldsighand = tsk->sighand;
776 spinlock_t *lock = &oldsighand->siglock; 769 spinlock_t *lock = &oldsighand->siglock;
777 struct task_struct *leader = NULL;
778 int count; 770 int count;
779 771
780 if (thread_group_empty(tsk)) 772 if (thread_group_empty(tsk))
@@ -812,7 +804,7 @@ static int de_thread(struct task_struct *tsk)
812 * and to assume its PID: 804 * and to assume its PID:
813 */ 805 */
814 if (!thread_group_leader(tsk)) { 806 if (!thread_group_leader(tsk)) {
815 leader = tsk->group_leader; 807 struct task_struct *leader = tsk->group_leader;
816 808
817 sig->notify_count = -1; /* for exit_notify() */ 809 sig->notify_count = -1; /* for exit_notify() */
818 for (;;) { 810 for (;;) {
@@ -864,8 +856,9 @@ static int de_thread(struct task_struct *tsk)
864 856
865 BUG_ON(leader->exit_state != EXIT_ZOMBIE); 857 BUG_ON(leader->exit_state != EXIT_ZOMBIE);
866 leader->exit_state = EXIT_DEAD; 858 leader->exit_state = EXIT_DEAD;
867
868 write_unlock_irq(&tasklist_lock); 859 write_unlock_irq(&tasklist_lock);
860
861 release_task(leader);
869 } 862 }
870 863
871 sig->group_exit_task = NULL; 864 sig->group_exit_task = NULL;
@@ -874,8 +867,6 @@ static int de_thread(struct task_struct *tsk)
874no_thread_group: 867no_thread_group:
875 exit_itimers(sig); 868 exit_itimers(sig);
876 flush_itimer_signals(); 869 flush_itimer_signals();
877 if (leader)
878 release_task(leader);
879 870
880 if (atomic_read(&oldsighand->count) != 1) { 871 if (atomic_read(&oldsighand->count) != 1) {
881 struct sighand_struct *newsighand; 872 struct sighand_struct *newsighand;
@@ -1181,41 +1172,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
1181 unsigned int depth = bprm->recursion_depth; 1172 unsigned int depth = bprm->recursion_depth;
1182 int try,retval; 1173 int try,retval;
1183 struct linux_binfmt *fmt; 1174 struct linux_binfmt *fmt;
1184#ifdef __alpha__
1185 /* handle /sbin/loader.. */
1186 {
1187 struct exec * eh = (struct exec *) bprm->buf;
1188
1189 if (!bprm->loader && eh->fh.f_magic == 0x183 &&
1190 (eh->fh.f_flags & 0x3000) == 0x3000)
1191 {
1192 struct file * file;
1193 unsigned long loader;
1194 1175
1195 allow_write_access(bprm->file);
1196 fput(bprm->file);
1197 bprm->file = NULL;
1198
1199 loader = bprm->vma->vm_end - sizeof(void *);
1200
1201 file = open_exec("/sbin/loader");
1202 retval = PTR_ERR(file);
1203 if (IS_ERR(file))
1204 return retval;
1205
1206 /* Remember if the application is TASO. */
1207 bprm->taso = eh->ah.entry < 0x100000000UL;
1208
1209 bprm->file = file;
1210 bprm->loader = loader;
1211 retval = prepare_binprm(bprm);
1212 if (retval<0)
1213 return retval;
1214 /* should call search_binary_handler recursively here,
1215 but it does not matter */
1216 }
1217 }
1218#endif
1219 retval = security_bprm_check(bprm); 1176 retval = security_bprm_check(bprm);
1220 if (retval) 1177 if (retval)
1221 return retval; 1178 return retval;
@@ -1737,7 +1694,7 @@ int get_dumpable(struct mm_struct *mm)
1737 return (ret >= 2) ? 2 : ret; 1694 return (ret >= 2) ? 2 : ret;
1738} 1695}
1739 1696
1740int do_coredump(long signr, int exit_code, struct pt_regs * regs) 1697void do_coredump(long signr, int exit_code, struct pt_regs *regs)
1741{ 1698{
1742 struct core_state core_state; 1699 struct core_state core_state;
1743 char corename[CORENAME_MAX_SIZE + 1]; 1700 char corename[CORENAME_MAX_SIZE + 1];
@@ -1821,6 +1778,11 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
1821 1778
1822 if (ispipe) { 1779 if (ispipe) {
1823 helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); 1780 helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc);
1781 if (!helper_argv) {
1782 printk(KERN_WARNING "%s failed to allocate memory\n",
1783 __func__);
1784 goto fail_unlock;
1785 }
1824 /* Terminate the string before the first option */ 1786 /* Terminate the string before the first option */
1825 delimit = strchr(corename, ' '); 1787 delimit = strchr(corename, ' ');
1826 if (delimit) 1788 if (delimit)
@@ -1888,5 +1850,5 @@ fail_unlock:
1888 put_cred(cred); 1850 put_cred(cred);
1889 coredump_finish(mm); 1851 coredump_finish(mm);
1890fail: 1852fail:
1891 return retval; 1853 return;
1892} 1854}