diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-25 22:05:55 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-25 22:05:55 -0400 |
| commit | bc84e0a160e383deb56568f4e03bc51b1ce16775 (patch) | |
| tree | 3c8cf1ae23c2f9c165bd7ce63a40b1d5c3aee275 /kernel | |
| parent | a92910723a5af54f81373875fd95133c88df94bd (diff) | |
| parent | f8f95702f0c4529b0f59488f4509608f0c160e77 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
[PATCH] sanitize locate_fd()
[PATCH] sanitize unshare_files/reset_files_struct
[PATCH] sanitize handling of shared descriptor tables in failing execve()
[PATCH] close race in unshare_files()
[PATCH] restore sane ->umount_begin() API
cifs: timeout dfs automounts +little fix.
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/exit.c | 6 | ||||
| -rw-r--r-- | kernel/fork.c | 58 |
2 files changed, 26 insertions, 38 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index cece89f80ab4..97f609f574b1 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
| @@ -507,10 +507,9 @@ void put_files_struct(struct files_struct *files) | |||
| 507 | } | 507 | } |
| 508 | } | 508 | } |
| 509 | 509 | ||
| 510 | EXPORT_SYMBOL(put_files_struct); | 510 | void reset_files_struct(struct files_struct *files) |
| 511 | |||
| 512 | void reset_files_struct(struct task_struct *tsk, struct files_struct *files) | ||
| 513 | { | 511 | { |
| 512 | struct task_struct *tsk = current; | ||
| 514 | struct files_struct *old; | 513 | struct files_struct *old; |
| 515 | 514 | ||
| 516 | old = tsk->files; | 515 | old = tsk->files; |
| @@ -519,7 +518,6 @@ void reset_files_struct(struct task_struct *tsk, struct files_struct *files) | |||
| 519 | task_unlock(tsk); | 518 | task_unlock(tsk); |
| 520 | put_files_struct(old); | 519 | put_files_struct(old); |
| 521 | } | 520 | } |
| 522 | EXPORT_SYMBOL(reset_files_struct); | ||
| 523 | 521 | ||
| 524 | void exit_files(struct task_struct *tsk) | 522 | void exit_files(struct task_struct *tsk) |
| 525 | { | 523 | { |
diff --git a/kernel/fork.c b/kernel/fork.c index 89fe414645e9..efb618fc8ffe 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -805,12 +805,6 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk) | |||
| 805 | goto out; | 805 | goto out; |
| 806 | } | 806 | } |
| 807 | 807 | ||
| 808 | /* | ||
| 809 | * Note: we may be using current for both targets (See exec.c) | ||
| 810 | * This works because we cache current->files (old) as oldf. Don't | ||
| 811 | * break this. | ||
| 812 | */ | ||
| 813 | tsk->files = NULL; | ||
| 814 | newf = dup_fd(oldf, &error); | 808 | newf = dup_fd(oldf, &error); |
| 815 | if (!newf) | 809 | if (!newf) |
| 816 | goto out; | 810 | goto out; |
| @@ -846,34 +840,6 @@ static int copy_io(unsigned long clone_flags, struct task_struct *tsk) | |||
| 846 | return 0; | 840 | return 0; |
| 847 | } | 841 | } |
| 848 | 842 | ||
| 849 | /* | ||
| 850 | * Helper to unshare the files of the current task. | ||
| 851 | * We don't want to expose copy_files internals to | ||
| 852 | * the exec layer of the kernel. | ||
| 853 | */ | ||
| 854 | |||
| 855 | int unshare_files(void) | ||
| 856 | { | ||
| 857 | struct files_struct *files = current->files; | ||
| 858 | int rc; | ||
| 859 | |||
| 860 | BUG_ON(!files); | ||
| 861 | |||
| 862 | /* This can race but the race causes us to copy when we don't | ||
| 863 | need to and drop the copy */ | ||
| 864 | if(atomic_read(&files->count) == 1) | ||
| 865 | { | ||
| 866 | atomic_inc(&files->count); | ||
| 867 | return 0; | ||
| 868 | } | ||
| 869 | rc = copy_files(0, current); | ||
| 870 | if(rc) | ||
| 871 | current->files = files; | ||
| 872 | return rc; | ||
| 873 | } | ||
| 874 | |||
| 875 | EXPORT_SYMBOL(unshare_files); | ||
| 876 | |||
| 877 | static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk) | 843 | static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk) |
| 878 | { | 844 | { |
| 879 | struct sighand_struct *sig; | 845 | struct sighand_struct *sig; |
| @@ -1811,3 +1777,27 @@ bad_unshare_cleanup_thread: | |||
| 1811 | bad_unshare_out: | 1777 | bad_unshare_out: |
| 1812 | return err; | 1778 | return err; |
| 1813 | } | 1779 | } |
| 1780 | |||
| 1781 | /* | ||
| 1782 | * Helper to unshare the files of the current task. | ||
| 1783 | * We don't want to expose copy_files internals to | ||
| 1784 | * the exec layer of the kernel. | ||
| 1785 | */ | ||
| 1786 | |||
| 1787 | int unshare_files(struct files_struct **displaced) | ||
| 1788 | { | ||
| 1789 | struct task_struct *task = current; | ||
| 1790 | struct files_struct *copy; | ||
| 1791 | int error; | ||
| 1792 | |||
| 1793 | error = unshare_fd(CLONE_FILES, ©); | ||
| 1794 | if (error || !copy) { | ||
| 1795 | *displaced = NULL; | ||
| 1796 | return error; | ||
| 1797 | } | ||
| 1798 | *displaced = task->files; | ||
| 1799 | task_lock(task); | ||
| 1800 | task->files = copy; | ||
| 1801 | task_unlock(task); | ||
| 1802 | return 0; | ||
| 1803 | } | ||
