linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / fs / exec.c
index 5d35813..6f54817 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -129,7 +129,7 @@ asmlinkage long sys_uselib(const char __user * library)
        struct nameidata nd;
        int error;
 
-       error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC);
+       error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ);
        if (error)
                goto out;
 
@@ -480,7 +480,7 @@ struct file *open_exec(const char *name)
        int err;
        struct file *file;
 
-       err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC);
+       err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ);
        file = ERR_PTR(err);
 
        if (!err) {
@@ -564,7 +564,7 @@ static int exec_mmap(struct mm_struct *mm)
        arch_pick_mmap_layout(mm);
        if (old_mm) {
                up_read(&old_mm->mmap_sem);
-               BUG_ON(active_mm != old_mm);
+               if (active_mm != old_mm) BUG();
                mmput(old_mm);
                return 0;
        }
@@ -619,15 +619,6 @@ static int de_thread(struct task_struct *tsk)
                kmem_cache_free(sighand_cachep, newsighand);
                return -EAGAIN;
        }
-
-       /*
-        * child_reaper ignores SIGKILL, change it now.
-        * Reparenting needs write_lock on tasklist_lock,
-        * so it is safe to do it under read_lock.
-        */
-       if (unlikely(current->group_leader == child_reaper))
-               child_reaper = current;
-
        zap_other_threads(current);
        read_unlock(&tasklist_lock);
 
@@ -644,7 +635,7 @@ static int de_thread(struct task_struct *tsk)
                 * synchronize with any firing (by calling del_timer_sync)
                 * before we can safely let the old group leader die.
                 */
-               sig->tsk = current;
+               sig->real_timer.data = current;
                spin_unlock_irq(lock);
                if (hrtimer_cancel(&sig->real_timer))
                        hrtimer_restart(&sig->real_timer);
@@ -668,7 +659,9 @@ static int de_thread(struct task_struct *tsk)
         * and to assume its PID:
         */
        if (!thread_group_leader(current)) {
+               struct task_struct *parent;
                struct dentry *proc_dentry1, *proc_dentry2;
+               unsigned long ptrace;
 
                /*
                 * Wait for the thread group leader to be a zombie.
@@ -679,18 +672,6 @@ static int de_thread(struct task_struct *tsk)
                while (leader->exit_state != EXIT_ZOMBIE)
                        yield();
 
-               /*
-                * The only record we have of the real-time age of a
-                * process, regardless of execs it's done, is start_time.
-                * All the past CPU time is accumulated in signal_struct
-                * from sister threads now dead.  But in this non-leader
-                * exec, nothing survives from the original leader thread,
-                * whose birth marks the true age of this process now.
-                * When we take on its identity by switching to its PID, we
-                * also take its birthdate (always earlier than our own).
-                */
-               current->start_time = leader->start_time;
-
                spin_lock(&leader->proc_lock);
                spin_lock(&current->proc_lock);
                proc_dentry1 = proc_pid_unhash(current);
@@ -705,26 +686,38 @@ static int de_thread(struct task_struct *tsk)
                 * two threads with a switched PID, and release
                 * the former thread group leader:
                 */
+               ptrace = leader->ptrace;
+               parent = leader->parent;
+               if (unlikely(ptrace) && unlikely(parent == current)) {
+                       /*
+                        * Joker was ptracing his own group leader,
+                        * and now he wants to be his own parent!
+                        * We can't have that.
+                        */
+                       ptrace = 0;
+               }
 
-               /* Become a process group leader with the old leader's pid.
-                * Note: The old leader also uses thispid until release_task
-                *       is called.  Odd but simple and correct.
-                */
-               detach_pid(current, PIDTYPE_PID);
-               current->pid = leader->pid;
-               attach_pid(current, PIDTYPE_PID,  current->pid);
-               attach_pid(current, PIDTYPE_PGID, current->signal->pgrp);
-               attach_pid(current, PIDTYPE_SID,  current->signal->session);
-               list_add_tail_rcu(&current->tasks, &init_task.tasks);
+               ptrace_unlink(current);
+               ptrace_unlink(leader);
+               remove_parent(current);
+               remove_parent(leader);
 
+               switch_exec_pids(leader, current);
+
+               current->parent = current->real_parent = leader->real_parent;
+               leader->parent = leader->real_parent = child_reaper;
                current->group_leader = current;
-               leader->group_leader = current;
+               leader->group_leader = leader;
 
-               /* Reduce leader to a thread */
-               detach_pid(leader, PIDTYPE_PGID);
-               detach_pid(leader, PIDTYPE_SID);
-               list_del_init(&leader->tasks);
+               add_parent(current, current->parent);
+               add_parent(leader, leader->parent);
+               if (ptrace) {
+                       current->ptrace = ptrace;
+                       __ptrace_link(current, parent);
+               }
 
+               list_del(&current->tasks);
+               list_add_tail(&current->tasks, &init_task.tasks);
                current->exit_signal = SIGCHLD;
 
                BUG_ON(leader->exit_state != EXIT_ZOMBIE);
@@ -761,6 +754,7 @@ no_thread_group:
                /*
                 * Move our state over to newsighand and switch it in.
                 */
+               spin_lock_init(&newsighand->siglock);
                atomic_set(&newsighand->count, 1);
                memcpy(newsighand->action, oldsighand->action,
                       sizeof(newsighand->action));
@@ -777,7 +771,7 @@ no_thread_group:
                write_unlock_irq(&tasklist_lock);
 
                if (atomic_dec_and_test(&oldsighand->count))
-                       kmem_cache_free(sighand_cachep, oldsighand);
+                       sighand_free(oldsighand);
        }
 
        BUG_ON(!thread_group_leader(current));
@@ -1152,9 +1146,10 @@ int do_execve(char * filename,
        int i;
 
        retval = -ENOMEM;
-       bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
+       bprm = kmalloc(sizeof(*bprm), GFP_KERNEL);
        if (!bprm)
                goto out_ret;
+       memset(bprm, 0, sizeof(*bprm));
 
        file = open_exec(filename);
        retval = PTR_ERR(file);
@@ -1454,8 +1449,6 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
        binfmt = current->binfmt;
        if (!binfmt || !binfmt->core_dump)
                goto fail;
-       if (current->tux_exit)
-               current->tux_exit();
        down_write(&mm->mmap_sem);
        if (!mm->dumpable) {
                up_write(&mm->mmap_sem);