#include <linux/syscalls.h>
#include <linux/rmap.h>
#include <linux/acct.h>
+#include <linux/cn_proc.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
if (!S_ISREG(nd.dentry->d_inode->i_mode))
goto exit;
- error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC, &nd);
+ error = vfs_permission(&nd, MAY_READ | MAY_EXEC);
if (error)
goto exit;
struct page *page, unsigned long address)
{
struct mm_struct *mm = vma->vm_mm;
- pgd_t * pgd;
- pud_t * pud;
- pmd_t * pmd;
pte_t * pte;
spinlock_t *ptl;
goto out;
flush_dcache_page(page);
- pgd = pgd_offset(mm, address);
- pud = pud_alloc(mm, pgd, address);
- if (!pud)
- goto out;
- pmd = pmd_alloc(mm, pud, address);
- if (!pmd)
- goto out;
- pte = pte_alloc_map_lock(mm, pmd, address, &ptl);
+ pte = get_locked_pte(mm, address, &ptl);
if (!pte)
goto out;
if (!pte_none(*pte)) {
file = ERR_PTR(-EACCES);
if (!(nd.mnt->mnt_flags & MNT_NOEXEC) &&
S_ISREG(inode->i_mode)) {
- int err = permission(inode, MAY_EXEC, &nd);
+ int err = vfs_permission(&nd, MAY_EXEC);
if (!err && !(inode->i_mode & 0111))
err = -EACCES;
file = ERR_PTR(err);
struct signal_struct *sig = tsk->signal;
struct sighand_struct *newsighand, *oldsighand = tsk->sighand;
spinlock_t *lock = &oldsighand->siglock;
+ struct task_struct *leader = NULL;
int count;
/*
/*
* Account for the thread group leader hanging around:
*/
- count = 2;
- if (thread_group_leader(current))
- count = 1;
- else {
+ count = 1;
+ if (!thread_group_leader(current)) {
+ count = 2;
/*
* The SIGALRM timer survives the exec, but needs to point
* at us as the new group leader now. We have a race with
* before we can safely let the old group leader die.
*/
sig->real_timer.data = (unsigned long)current;
+ spin_unlock_irq(lock);
if (del_timer_sync(&sig->real_timer))
add_timer(&sig->real_timer);
+ spin_lock_irq(lock);
}
while (atomic_read(&sig->count) > count) {
sig->group_exit_task = current;
}
sig->group_exit_task = NULL;
sig->notify_count = 0;
- sig->real_timer.data = (unsigned long)current;
spin_unlock_irq(lock);
/*
* and to assume its PID:
*/
if (!thread_group_leader(current)) {
- struct task_struct *leader = current->group_leader, *parent;
+ struct task_struct *parent;
struct dentry *proc_dentry1, *proc_dentry2;
- unsigned long exit_state, ptrace;
+ unsigned long ptrace;
/*
* Wait for the thread group leader to be a zombie.
* It should already be zombie at this point, most
* of the time.
*/
+ leader = current->group_leader;
while (leader->exit_state != EXIT_ZOMBIE)
yield();
list_del(¤t->tasks);
list_add_tail(¤t->tasks, &init_task.tasks);
current->exit_signal = SIGCHLD;
- exit_state = leader->exit_state;
+
+ BUG_ON(leader->exit_state != EXIT_ZOMBIE);
+ leader->exit_state = EXIT_DEAD;
write_unlock_irq(&tasklist_lock);
spin_unlock(&leader->proc_lock);
spin_unlock(¤t->proc_lock);
proc_pid_flush(proc_dentry1);
proc_pid_flush(proc_dentry2);
-
- BUG_ON(exit_state != EXIT_ZOMBIE);
- release_task(leader);
}
/*
sig->flags = 0;
no_thread_group:
- BUG_ON(atomic_read(&sig->count) != 1);
exit_itimers(sig);
+ if (leader)
+ release_task(leader);
+
+ BUG_ON(atomic_read(&sig->count) != 1);
if (atomic_read(&oldsighand->count) == 1) {
/*
flush_thread();
if (bprm->e_uid != current->euid || bprm->e_gid != current->egid ||
- permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL) ||
+ file_permission(bprm->file, MAY_READ) ||
(bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) {
suid_keys(current);
current->mm->dumpable = suid_dumpable;
fput(bprm->file);
bprm->file = NULL;
current->did_exec = 1;
+ proc_exec_connector(current);
return retval;
}
read_lock(&binfmt_lock);
static void coredump_wait(struct mm_struct *mm)
{
DECLARE_COMPLETION(startup_done);
+ int core_waiters;
- mm->core_waiters++; /* let other threads block */
mm->core_startup_done = &startup_done;
- /* give other threads a chance to run: */
- yield();
-
zap_threads(mm);
- if (--mm->core_waiters) {
- up_write(&mm->mmap_sem);
+ core_waiters = mm->core_waiters;
+ up_write(&mm->mmap_sem);
+
+ if (core_waiters)
wait_for_completion(&startup_done);
- } else
- up_write(&mm->mmap_sem);
BUG_ON(mm->core_waiters);
}
current->fsuid = 0; /* Dump root private */
}
mm->dumpable = 0;
- init_completion(&mm->core_done);
+
+ retval = -EAGAIN;
spin_lock_irq(¤t->sighand->siglock);
- current->signal->flags = SIGNAL_GROUP_EXIT;
- current->signal->group_exit_code = exit_code;
+ if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) {
+ current->signal->flags = SIGNAL_GROUP_EXIT;
+ current->signal->group_exit_code = exit_code;
+ retval = 0;
+ }
spin_unlock_irq(¤t->sighand->siglock);
+ if (retval) {
+ up_write(&mm->mmap_sem);
+ goto fail;
+ }
+
+ init_completion(&mm->core_done);
coredump_wait(mm);
/*
goto close_fail;
if (!file->f_op->write)
goto close_fail;
- if (do_truncate(file->f_dentry, 0) != 0)
+ if (do_truncate(file->f_dentry, 0, file) != 0)
goto close_fail;
retval = binfmt->core_dump(signr, regs, file);