diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 39 |
1 files changed, 27 insertions, 12 deletions
@@ -127,7 +127,7 @@ asmlinkage long sys_uselib(const char __user * library) | |||
127 | struct nameidata nd; | 127 | struct nameidata nd; |
128 | int error; | 128 | int error; |
129 | 129 | ||
130 | error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ); | 130 | error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC); |
131 | if (error) | 131 | if (error) |
132 | goto out; | 132 | goto out; |
133 | 133 | ||
@@ -477,7 +477,7 @@ struct file *open_exec(const char *name) | |||
477 | int err; | 477 | int err; |
478 | struct file *file; | 478 | struct file *file; |
479 | 479 | ||
480 | err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ); | 480 | err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC); |
481 | file = ERR_PTR(err); | 481 | file = ERR_PTR(err); |
482 | 482 | ||
483 | if (!err) { | 483 | if (!err) { |
@@ -616,6 +616,15 @@ static int de_thread(struct task_struct *tsk) | |||
616 | kmem_cache_free(sighand_cachep, newsighand); | 616 | kmem_cache_free(sighand_cachep, newsighand); |
617 | return -EAGAIN; | 617 | return -EAGAIN; |
618 | } | 618 | } |
619 | |||
620 | /* | ||
621 | * child_reaper ignores SIGKILL, change it now. | ||
622 | * Reparenting needs write_lock on tasklist_lock, | ||
623 | * so it is safe to do it under read_lock. | ||
624 | */ | ||
625 | if (unlikely(current->group_leader == child_reaper)) | ||
626 | child_reaper = current; | ||
627 | |||
619 | zap_other_threads(current); | 628 | zap_other_threads(current); |
620 | read_unlock(&tasklist_lock); | 629 | read_unlock(&tasklist_lock); |
621 | 630 | ||
@@ -632,7 +641,7 @@ static int de_thread(struct task_struct *tsk) | |||
632 | * synchronize with any firing (by calling del_timer_sync) | 641 | * synchronize with any firing (by calling del_timer_sync) |
633 | * before we can safely let the old group leader die. | 642 | * before we can safely let the old group leader die. |
634 | */ | 643 | */ |
635 | sig->real_timer.data = current; | 644 | sig->tsk = current; |
636 | spin_unlock_irq(lock); | 645 | spin_unlock_irq(lock); |
637 | if (hrtimer_cancel(&sig->real_timer)) | 646 | if (hrtimer_cancel(&sig->real_timer)) |
638 | hrtimer_restart(&sig->real_timer); | 647 | hrtimer_restart(&sig->real_timer); |
@@ -699,22 +708,30 @@ static int de_thread(struct task_struct *tsk) | |||
699 | remove_parent(current); | 708 | remove_parent(current); |
700 | remove_parent(leader); | 709 | remove_parent(leader); |
701 | 710 | ||
702 | switch_exec_pids(leader, current); | 711 | |
712 | /* Become a process group leader with the old leader's pid. | ||
713 | * Note: The old leader also uses thispid until release_task | ||
714 | * is called. Odd but simple and correct. | ||
715 | */ | ||
716 | detach_pid(current, PIDTYPE_PID); | ||
717 | current->pid = leader->pid; | ||
718 | attach_pid(current, PIDTYPE_PID, current->pid); | ||
719 | attach_pid(current, PIDTYPE_PGID, current->signal->pgrp); | ||
720 | attach_pid(current, PIDTYPE_SID, current->signal->session); | ||
721 | list_add_tail(¤t->tasks, &init_task.tasks); | ||
703 | 722 | ||
704 | current->parent = current->real_parent = leader->real_parent; | 723 | current->parent = current->real_parent = leader->real_parent; |
705 | leader->parent = leader->real_parent = child_reaper; | 724 | leader->parent = leader->real_parent = child_reaper; |
706 | current->group_leader = current; | 725 | current->group_leader = current; |
707 | leader->group_leader = leader; | 726 | leader->group_leader = leader; |
708 | 727 | ||
709 | add_parent(current, current->parent); | 728 | add_parent(current); |
710 | add_parent(leader, leader->parent); | 729 | add_parent(leader); |
711 | if (ptrace) { | 730 | if (ptrace) { |
712 | current->ptrace = ptrace; | 731 | current->ptrace = ptrace; |
713 | __ptrace_link(current, parent); | 732 | __ptrace_link(current, parent); |
714 | } | 733 | } |
715 | 734 | ||
716 | list_del(¤t->tasks); | ||
717 | list_add_tail(¤t->tasks, &init_task.tasks); | ||
718 | current->exit_signal = SIGCHLD; | 735 | current->exit_signal = SIGCHLD; |
719 | 736 | ||
720 | BUG_ON(leader->exit_state != EXIT_ZOMBIE); | 737 | BUG_ON(leader->exit_state != EXIT_ZOMBIE); |
@@ -751,7 +768,6 @@ no_thread_group: | |||
751 | /* | 768 | /* |
752 | * Move our state over to newsighand and switch it in. | 769 | * Move our state over to newsighand and switch it in. |
753 | */ | 770 | */ |
754 | spin_lock_init(&newsighand->siglock); | ||
755 | atomic_set(&newsighand->count, 1); | 771 | atomic_set(&newsighand->count, 1); |
756 | memcpy(newsighand->action, oldsighand->action, | 772 | memcpy(newsighand->action, oldsighand->action, |
757 | sizeof(newsighand->action)); | 773 | sizeof(newsighand->action)); |
@@ -768,7 +784,7 @@ no_thread_group: | |||
768 | write_unlock_irq(&tasklist_lock); | 784 | write_unlock_irq(&tasklist_lock); |
769 | 785 | ||
770 | if (atomic_dec_and_test(&oldsighand->count)) | 786 | if (atomic_dec_and_test(&oldsighand->count)) |
771 | sighand_free(oldsighand); | 787 | kmem_cache_free(sighand_cachep, oldsighand); |
772 | } | 788 | } |
773 | 789 | ||
774 | BUG_ON(!thread_group_leader(current)); | 790 | BUG_ON(!thread_group_leader(current)); |
@@ -1143,10 +1159,9 @@ int do_execve(char * filename, | |||
1143 | int i; | 1159 | int i; |
1144 | 1160 | ||
1145 | retval = -ENOMEM; | 1161 | retval = -ENOMEM; |
1146 | bprm = kmalloc(sizeof(*bprm), GFP_KERNEL); | 1162 | bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); |
1147 | if (!bprm) | 1163 | if (!bprm) |
1148 | goto out_ret; | 1164 | goto out_ret; |
1149 | memset(bprm, 0, sizeof(*bprm)); | ||
1150 | 1165 | ||
1151 | file = open_exec(filename); | 1166 | file = open_exec(filename); |
1152 | retval = PTR_ERR(file); | 1167 | retval = PTR_ERR(file); |