X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=fs%2Fexec.c;h=070ddf13cb719d62ead6233961c2bb9716beed02;hb=5c8e191e8437616a498a8e1cc0af3dd0d32bbff2;hp=6450157062eae04ab81df85be78cba0fbbd5bc93;hpb=74aadce986052f20088c2678f589ea0e8d3a4b59;p=linux-2.6-omap-h63xx.git diff --git a/fs/exec.c b/fs/exec.c index 6450157062e..070ddf13cb7 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -64,7 +64,6 @@ int core_uses_pid; char core_pattern[CORENAME_MAX_SIZE] = "core"; int suid_dumpable = 0; -EXPORT_SYMBOL(suid_dumpable); /* The maximal length of core_pattern is also specified in sysctl.c */ static LIST_HEAD(formats); @@ -112,9 +111,6 @@ asmlinkage long sys_uselib(const char __user * library) if (error) goto out; - error = -EACCES; - if (nd.mnt->mnt_flags & MNT_NOEXEC) - goto exit; error = -EINVAL; if (!S_ISREG(nd.dentry->d_inode->i_mode)) goto exit; @@ -658,8 +654,7 @@ struct file *open_exec(const char *name) if (!err) { struct inode *inode = nd.dentry->d_inode; file = ERR_PTR(-EACCES); - if (!(nd.mnt->mnt_flags & MNT_NOEXEC) && - S_ISREG(inode->i_mode)) { + if (S_ISREG(inode->i_mode)) { int err = vfs_permission(&nd, MAY_EXEC); file = ERR_PTR(err); if (!err) { @@ -751,24 +746,11 @@ static int exec_mmap(struct mm_struct *mm) static int de_thread(struct task_struct *tsk) { struct signal_struct *sig = tsk->signal; - struct sighand_struct *newsighand, *oldsighand = tsk->sighand; + struct sighand_struct *oldsighand = tsk->sighand; spinlock_t *lock = &oldsighand->siglock; struct task_struct *leader = NULL; int count; - /* - * If we don't share sighandlers, then we aren't sharing anything - * and we can just re-use it all. - */ - if (atomic_read(&oldsighand->count) <= 1) { - exit_itimers(sig); - return 0; - } - - newsighand = kmem_cache_alloc(sighand_cachep, GFP_KERNEL); - if (!newsighand) - return -ENOMEM; - if (thread_group_empty(tsk)) goto no_thread_group; @@ -785,7 +767,6 @@ static int de_thread(struct task_struct *tsk) */ spin_unlock_irq(lock); read_unlock(&tasklist_lock); - kmem_cache_free(sighand_cachep, newsighand); return -EAGAIN; } @@ -819,16 +800,15 @@ static int de_thread(struct task_struct *tsk) hrtimer_restart(&sig->real_timer); spin_lock_irq(lock); } + + sig->notify_count = count; + sig->group_exit_task = tsk; while (atomic_read(&sig->count) > count) { - sig->group_exit_task = tsk; - sig->notify_count = count; __set_current_state(TASK_UNINTERRUPTIBLE); spin_unlock_irq(lock); schedule(); spin_lock_irq(lock); } - sig->group_exit_task = NULL; - sig->notify_count = 0; spin_unlock_irq(lock); /* @@ -837,14 +817,17 @@ static int de_thread(struct task_struct *tsk) * and to assume its PID: */ if (!thread_group_leader(tsk)) { - /* - * Wait for the thread group leader to be a zombie. - * It should already be zombie at this point, most - * of the time. - */ leader = tsk->group_leader; - while (leader->exit_state != EXIT_ZOMBIE) - yield(); + + sig->notify_count = -1; + for (;;) { + write_lock_irq(&tasklist_lock); + if (likely(leader->exit_state)) + break; + __set_current_state(TASK_UNINTERRUPTIBLE); + write_unlock_irq(&tasklist_lock); + schedule(); + } /* * The only record we have of the real-time age of a @@ -858,8 +841,6 @@ static int de_thread(struct task_struct *tsk) */ tsk->start_time = leader->start_time; - write_lock_irq(&tasklist_lock); - BUG_ON(leader->tgid != tsk->tgid); BUG_ON(tsk->pid == tsk->tgid); /* @@ -892,6 +873,8 @@ static int de_thread(struct task_struct *tsk) write_unlock_irq(&tasklist_lock); } + sig->group_exit_task = NULL; + sig->notify_count = 0; /* * There may be one thread left which is just exiting, * but it's safe to stop telling the group to kill themselves. @@ -903,29 +886,23 @@ no_thread_group: if (leader) release_task(leader); - if (atomic_read(&oldsighand->count) == 1) { + if (atomic_read(&oldsighand->count) != 1) { + struct sighand_struct *newsighand; /* - * Now that we nuked the rest of the thread group, - * it turns out we are not sharing sighand any more either. - * So we can just keep it. - */ - kmem_cache_free(sighand_cachep, newsighand); - } else { - /* - * Move our state over to newsighand and switch it in. + * This ->sighand is shared with the CLONE_SIGHAND + * but not CLONE_THREAD task, switch to the new one. */ + newsighand = kmem_cache_alloc(sighand_cachep, GFP_KERNEL); + if (!newsighand) + return -ENOMEM; + atomic_set(&newsighand->count, 1); memcpy(newsighand->action, oldsighand->action, sizeof(newsighand->action)); write_lock_irq(&tasklist_lock); spin_lock(&oldsighand->siglock); - spin_lock_nested(&newsighand->siglock, SINGLE_DEPTH_NESTING); - rcu_assign_pointer(tsk->sighand, newsighand); - recalc_sigpending(); - - spin_unlock(&newsighand->siglock); spin_unlock(&oldsighand->siglock); write_unlock_irq(&tasklist_lock); @@ -935,12 +912,11 @@ no_thread_group: BUG_ON(!thread_group_leader(tsk)); return 0; } - + /* * These functions flushes out all traces of the currently running executable * so that a new one can be started */ - static void flush_old_files(struct files_struct * files) { long j = -1; @@ -1685,7 +1661,6 @@ void set_dumpable(struct mm_struct *mm, int value) break; } } -EXPORT_SYMBOL_GPL(set_dumpable); int get_dumpable(struct mm_struct *mm) { @@ -1762,14 +1737,27 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) goto fail_unlock; if (ispipe) { - core_limit = RLIM_INFINITY; helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); /* Terminate the string before the first option */ delimit = strchr(corename, ' '); if (delimit) *delimit = '\0'; + delimit = strrchr(helper_argv[0], '/'); + if (delimit) + delimit++; + else + delimit = helper_argv[0]; + if (!strcmp(delimit, current->comm)) { + printk(KERN_NOTICE "Recursive core dump detected, " + "aborting\n"); + goto fail_unlock; + } + + core_limit = RLIM_INFINITY; + /* SIGPIPE can happen, but it's just never processed */ - if(call_usermodehelper_pipe(corename+1, helper_argv, NULL, &file)) { + if (call_usermodehelper_pipe(corename+1, helper_argv, NULL, + &file)) { printk(KERN_INFO "Core dump to %s pipe failed\n", corename); goto fail_unlock;