diff options
Diffstat (limited to 'kernel/fork.c')
| -rw-r--r-- | kernel/fork.c | 58 |
1 files changed, 24 insertions, 34 deletions
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 | } | ||
