diff options
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r-- | fs/fcntl.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c index ce12a6885115..3deec9887089 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -135,18 +135,12 @@ asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags) | |||
135 | if ((flags & ~O_CLOEXEC) != 0) | 135 | if ((flags & ~O_CLOEXEC) != 0) |
136 | return -EINVAL; | 136 | return -EINVAL; |
137 | 137 | ||
138 | if (unlikely(oldfd == newfd)) | ||
139 | return -EINVAL; | ||
140 | |||
138 | spin_lock(&files->file_lock); | 141 | spin_lock(&files->file_lock); |
139 | if (!(file = fcheck(oldfd))) | 142 | if (!(file = fcheck(oldfd))) |
140 | goto out_unlock; | 143 | goto out_unlock; |
141 | err = newfd; | ||
142 | if (unlikely(newfd == oldfd)) { | ||
143 | if (flags & O_CLOEXEC) { | ||
144 | fdt = files_fdtable(files); | ||
145 | FD_SET(newfd, fdt->close_on_exec); | ||
146 | } | ||
147 | goto out_unlock; | ||
148 | } | ||
149 | err = -EBADF; | ||
150 | if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) | 144 | if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) |
151 | goto out_unlock; | 145 | goto out_unlock; |
152 | get_file(file); /* We are now finished with oldfd */ | 146 | get_file(file); /* We are now finished with oldfd */ |
@@ -194,6 +188,14 @@ out_fput: | |||
194 | 188 | ||
195 | asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd) | 189 | asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd) |
196 | { | 190 | { |
191 | if (unlikely(newfd == oldfd)) { /* corner case */ | ||
192 | struct files_struct *files = current->files; | ||
193 | rcu_read_lock(); | ||
194 | if (!fcheck_files(files, oldfd)) | ||
195 | oldfd = -EBADF; | ||
196 | rcu_read_unlock(); | ||
197 | return oldfd; | ||
198 | } | ||
197 | return sys_dup3(oldfd, newfd, 0); | 199 | return sys_dup3(oldfd, newfd, 0); |
198 | } | 200 | } |
199 | 201 | ||