aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-04-25 22:05:55 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-25 22:05:55 -0400
commitbc84e0a160e383deb56568f4e03bc51b1ce16775 (patch)
tree3c8cf1ae23c2f9c165bd7ce63a40b1d5c3aee275 /kernel
parenta92910723a5af54f81373875fd95133c88df94bd (diff)
parentf8f95702f0c4529b0f59488f4509608f0c160e77 (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.c6
-rw-r--r--kernel/fork.c58
2 files changed, 26 insertions, 38 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index cece89f80ab..97f609f574b 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
510EXPORT_SYMBOL(put_files_struct); 510void reset_files_struct(struct files_struct *files)
511
512void 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}
522EXPORT_SYMBOL(reset_files_struct);
523 521
524void exit_files(struct task_struct *tsk) 522void exit_files(struct task_struct *tsk)
525{ 523{
diff --git a/kernel/fork.c b/kernel/fork.c
index 89fe414645e..efb618fc8ff 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
855int 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
875EXPORT_SYMBOL(unshare_files);
876
877static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk) 843static 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:
1811bad_unshare_out: 1777bad_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
1787int 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, &copy);
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}