diff options
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r-- | fs/fcntl.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c index bfecc6238083..d2f3ed8acd93 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/security.h> | 16 | #include <linux/security.h> |
17 | #include <linux/ptrace.h> | 17 | #include <linux/ptrace.h> |
18 | #include <linux/signal.h> | 18 | #include <linux/signal.h> |
19 | #include <linux/rcupdate.h> | ||
19 | 20 | ||
20 | #include <asm/poll.h> | 21 | #include <asm/poll.h> |
21 | #include <asm/siginfo.h> | 22 | #include <asm/siginfo.h> |
@@ -64,8 +65,8 @@ static int locate_fd(struct files_struct *files, | |||
64 | if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) | 65 | if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) |
65 | goto out; | 66 | goto out; |
66 | 67 | ||
67 | fdt = files_fdtable(files); | ||
68 | repeat: | 68 | repeat: |
69 | fdt = files_fdtable(files); | ||
69 | /* | 70 | /* |
70 | * Someone might have closed fd's in the range | 71 | * Someone might have closed fd's in the range |
71 | * orig_start..fdt->next_fd | 72 | * orig_start..fdt->next_fd |
@@ -95,9 +96,15 @@ repeat: | |||
95 | if (error) | 96 | if (error) |
96 | goto repeat; | 97 | goto repeat; |
97 | 98 | ||
99 | /* | ||
100 | * We reacquired files_lock, so we are safe as long as | ||
101 | * we reacquire the fdtable pointer and use it while holding | ||
102 | * the lock, no one can free it during that time. | ||
103 | */ | ||
104 | fdt = files_fdtable(files); | ||
98 | if (start <= fdt->next_fd) | 105 | if (start <= fdt->next_fd) |
99 | fdt->next_fd = newfd + 1; | 106 | fdt->next_fd = newfd + 1; |
100 | 107 | ||
101 | error = newfd; | 108 | error = newfd; |
102 | 109 | ||
103 | out: | 110 | out: |
@@ -163,7 +170,7 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd) | |||
163 | if (!tofree && FD_ISSET(newfd, fdt->open_fds)) | 170 | if (!tofree && FD_ISSET(newfd, fdt->open_fds)) |
164 | goto out_fput; | 171 | goto out_fput; |
165 | 172 | ||
166 | fdt->fd[newfd] = file; | 173 | rcu_assign_pointer(fdt->fd[newfd], file); |
167 | FD_SET(newfd, fdt->open_fds); | 174 | FD_SET(newfd, fdt->open_fds); |
168 | FD_CLR(newfd, fdt->close_on_exec); | 175 | FD_CLR(newfd, fdt->close_on_exec); |
169 | spin_unlock(&files->file_lock); | 176 | spin_unlock(&files->file_lock); |