diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2008-04-22 04:45:46 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2008-04-25 09:23:48 -0400 |
commit | 6b335d9c80d7f3c2a3f6545f664ae9007a0f3821 (patch) | |
tree | fa9ab80e1fddc05b79a76bd10922b3328fe6c3e6 /kernel/fork.c | |
parent | 42faad99658eed7ca8bd328ffa4bcb7d78c9bcca (diff) |
[PATCH] close race in unshare_files()
updating current->files requires task_lock
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 20 |
1 files changed, 9 insertions, 11 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 89fe414645e9..76f05a08062b 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; |
@@ -855,7 +849,8 @@ static int copy_io(unsigned long clone_flags, struct task_struct *tsk) | |||
855 | int unshare_files(void) | 849 | int unshare_files(void) |
856 | { | 850 | { |
857 | struct files_struct *files = current->files; | 851 | struct files_struct *files = current->files; |
858 | int rc; | 852 | struct files_struct *newf; |
853 | int error = 0; | ||
859 | 854 | ||
860 | BUG_ON(!files); | 855 | BUG_ON(!files); |
861 | 856 | ||
@@ -866,10 +861,13 @@ int unshare_files(void) | |||
866 | atomic_inc(&files->count); | 861 | atomic_inc(&files->count); |
867 | return 0; | 862 | return 0; |
868 | } | 863 | } |
869 | rc = copy_files(0, current); | 864 | newf = dup_fd(files, &error); |
870 | if(rc) | 865 | if (newf) { |
871 | current->files = files; | 866 | task_lock(current); |
872 | return rc; | 867 | current->files = newf; |
868 | task_unlock(current); | ||
869 | } | ||
870 | return error; | ||
873 | } | 871 | } |
874 | 872 | ||
875 | EXPORT_SYMBOL(unshare_files); | 873 | EXPORT_SYMBOL(unshare_files); |