aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2008-04-22 05:31:30 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2008-04-25 09:23:59 -0400
commit3b1253880b7a9e6db54b943b2d40bcf2202f58ab (patch)
tree5301be7b4d4310faa8db5a0d027b81421e36570e /kernel
parentfd8328be874f4190a811c58cd4778ec2c74d2c05 (diff)
[PATCH] sanitize unshare_files/reset_files_struct
* let unshare_files() give caller the displaced files_struct * don't bother with grabbing reference only to drop it in the caller if it hadn't been shared in the first place * in that form unshare_files() is trivially implemented via unshare_fd(), so we eliminate the duplicate logics in fork.c * reset_files_struct() is not just only called for current; it will break the system if somebody ever calls it for anything else (we can't modify ->files of somebody else). Lose the task_struct * argument. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/exit.c3
-rw-r--r--kernel/fork.c54
2 files changed, 26 insertions, 31 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index 3d320003cc03..97f609f574b1 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -507,8 +507,9 @@ void put_files_struct(struct files_struct *files)
507 } 507 }
508} 508}
509 509
510void reset_files_struct(struct task_struct *tsk, struct files_struct *files) 510void reset_files_struct(struct files_struct *files)
511{ 511{
512 struct task_struct *tsk = current;
512 struct files_struct *old; 513 struct files_struct *old;
513 514
514 old = tsk->files; 515 old = tsk->files;
diff --git a/kernel/fork.c b/kernel/fork.c
index 2fc11f2e2b21..efb618fc8ffe 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -840,36 +840,6 @@ static int copy_io(unsigned long clone_flags, struct task_struct *tsk)
840 return 0; 840 return 0;
841} 841}
842 842
843/*
844 * Helper to unshare the files of the current task.
845 * We don't want to expose copy_files internals to
846 * the exec layer of the kernel.
847 */
848
849int unshare_files(void)
850{
851 struct files_struct *files = current->files;
852 struct files_struct *newf;
853 int error = 0;
854
855 BUG_ON(!files);
856
857 /* This can race but the race causes us to copy when we don't
858 need to and drop the copy */
859 if(atomic_read(&files->count) == 1)
860 {
861 atomic_inc(&files->count);
862 return 0;
863 }
864 newf = dup_fd(files, &error);
865 if (newf) {
866 task_lock(current);
867 current->files = newf;
868 task_unlock(current);
869 }
870 return error;
871}
872
873static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk) 843static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
874{ 844{
875 struct sighand_struct *sig; 845 struct sighand_struct *sig;
@@ -1807,3 +1777,27 @@ bad_unshare_cleanup_thread:
1807bad_unshare_out: 1777bad_unshare_out:
1808 return err; 1778 return err;
1809} 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}