diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 39 |
1 files changed, 27 insertions, 12 deletions
@@ -58,6 +58,9 @@ | |||
58 | 58 | ||
59 | int core_uses_pid; | 59 | int core_uses_pid; |
60 | char core_pattern[65] = "core"; | 60 | char core_pattern[65] = "core"; |
61 | int suid_dumpable = 0; | ||
62 | |||
63 | EXPORT_SYMBOL(suid_dumpable); | ||
61 | /* The maximal length of core_pattern is also specified in sysctl.c */ | 64 | /* The maximal length of core_pattern is also specified in sysctl.c */ |
62 | 65 | ||
63 | static struct linux_binfmt *formats; | 66 | static struct linux_binfmt *formats; |
@@ -649,6 +652,7 @@ static inline int de_thread(struct task_struct *tsk) | |||
649 | } | 652 | } |
650 | sig->group_exit_task = NULL; | 653 | sig->group_exit_task = NULL; |
651 | sig->notify_count = 0; | 654 | sig->notify_count = 0; |
655 | sig->real_timer.data = (unsigned long)current; | ||
652 | spin_unlock_irq(lock); | 656 | spin_unlock_irq(lock); |
653 | 657 | ||
654 | /* | 658 | /* |
@@ -675,10 +679,8 @@ static inline int de_thread(struct task_struct *tsk) | |||
675 | proc_dentry2 = proc_pid_unhash(leader); | 679 | proc_dentry2 = proc_pid_unhash(leader); |
676 | write_lock_irq(&tasklist_lock); | 680 | write_lock_irq(&tasklist_lock); |
677 | 681 | ||
678 | if (leader->tgid != current->tgid) | 682 | BUG_ON(leader->tgid != current->tgid); |
679 | BUG(); | 683 | BUG_ON(current->pid == current->tgid); |
680 | if (current->pid == current->tgid) | ||
681 | BUG(); | ||
682 | /* | 684 | /* |
683 | * An exec() starts a new thread group with the | 685 | * An exec() starts a new thread group with the |
684 | * TGID of the previous thread group. Rehash the | 686 | * TGID of the previous thread group. Rehash the |
@@ -726,8 +728,7 @@ static inline int de_thread(struct task_struct *tsk) | |||
726 | proc_pid_flush(proc_dentry1); | 728 | proc_pid_flush(proc_dentry1); |
727 | proc_pid_flush(proc_dentry2); | 729 | proc_pid_flush(proc_dentry2); |
728 | 730 | ||
729 | if (exit_state != EXIT_ZOMBIE) | 731 | BUG_ON(exit_state != EXIT_ZOMBIE); |
730 | BUG(); | ||
731 | release_task(leader); | 732 | release_task(leader); |
732 | } | 733 | } |
733 | 734 | ||
@@ -772,10 +773,8 @@ no_thread_group: | |||
772 | kmem_cache_free(sighand_cachep, oldsighand); | 773 | kmem_cache_free(sighand_cachep, oldsighand); |
773 | } | 774 | } |
774 | 775 | ||
775 | if (!thread_group_empty(current)) | 776 | BUG_ON(!thread_group_empty(current)); |
776 | BUG(); | 777 | BUG_ON(!thread_group_leader(current)); |
777 | if (!thread_group_leader(current)) | ||
778 | BUG(); | ||
779 | return 0; | 778 | return 0; |
780 | } | 779 | } |
781 | 780 | ||
@@ -868,6 +867,9 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
868 | 867 | ||
869 | if (current->euid == current->uid && current->egid == current->gid) | 868 | if (current->euid == current->uid && current->egid == current->gid) |
870 | current->mm->dumpable = 1; | 869 | current->mm->dumpable = 1; |
870 | else | ||
871 | current->mm->dumpable = suid_dumpable; | ||
872 | |||
871 | name = bprm->filename; | 873 | name = bprm->filename; |
872 | 874 | ||
873 | /* Copies the binary name from after last slash */ | 875 | /* Copies the binary name from after last slash */ |
@@ -888,7 +890,7 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
888 | permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL) || | 890 | permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL) || |
889 | (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) { | 891 | (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) { |
890 | suid_keys(current); | 892 | suid_keys(current); |
891 | current->mm->dumpable = 0; | 893 | current->mm->dumpable = suid_dumpable; |
892 | } | 894 | } |
893 | 895 | ||
894 | /* An exec changes our domain. We are no longer part of the thread | 896 | /* An exec changes our domain. We are no longer part of the thread |
@@ -1436,6 +1438,8 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1436 | struct inode * inode; | 1438 | struct inode * inode; |
1437 | struct file * file; | 1439 | struct file * file; |
1438 | int retval = 0; | 1440 | int retval = 0; |
1441 | int fsuid = current->fsuid; | ||
1442 | int flag = 0; | ||
1439 | 1443 | ||
1440 | binfmt = current->binfmt; | 1444 | binfmt = current->binfmt; |
1441 | if (!binfmt || !binfmt->core_dump) | 1445 | if (!binfmt || !binfmt->core_dump) |
@@ -1445,6 +1449,16 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1445 | up_write(&mm->mmap_sem); | 1449 | up_write(&mm->mmap_sem); |
1446 | goto fail; | 1450 | goto fail; |
1447 | } | 1451 | } |
1452 | |||
1453 | /* | ||
1454 | * We cannot trust fsuid as being the "true" uid of the | ||
1455 | * process nor do we know its entire history. We only know it | ||
1456 | * was tainted so we dump it as root in mode 2. | ||
1457 | */ | ||
1458 | if (mm->dumpable == 2) { /* Setuid core dump mode */ | ||
1459 | flag = O_EXCL; /* Stop rewrite attacks */ | ||
1460 | current->fsuid = 0; /* Dump root private */ | ||
1461 | } | ||
1448 | mm->dumpable = 0; | 1462 | mm->dumpable = 0; |
1449 | init_completion(&mm->core_done); | 1463 | init_completion(&mm->core_done); |
1450 | spin_lock_irq(¤t->sighand->siglock); | 1464 | spin_lock_irq(¤t->sighand->siglock); |
@@ -1470,7 +1484,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1470 | lock_kernel(); | 1484 | lock_kernel(); |
1471 | format_corename(corename, core_pattern, signr); | 1485 | format_corename(corename, core_pattern, signr); |
1472 | unlock_kernel(); | 1486 | unlock_kernel(); |
1473 | file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE, 0600); | 1487 | file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, 0600); |
1474 | if (IS_ERR(file)) | 1488 | if (IS_ERR(file)) |
1475 | goto fail_unlock; | 1489 | goto fail_unlock; |
1476 | inode = file->f_dentry->d_inode; | 1490 | inode = file->f_dentry->d_inode; |
@@ -1495,6 +1509,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1495 | close_fail: | 1509 | close_fail: |
1496 | filp_close(file, NULL); | 1510 | filp_close(file, NULL); |
1497 | fail_unlock: | 1511 | fail_unlock: |
1512 | current->fsuid = fsuid; | ||
1498 | complete_all(&mm->core_done); | 1513 | complete_all(&mm->core_done); |
1499 | fail: | 1514 | fail: |
1500 | return retval; | 1515 | return retval; |