diff options
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r-- | fs/fcntl.c | 33 |
1 files changed, 17 insertions, 16 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c index 9679fcbdeaa0..61d625136813 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -64,11 +64,6 @@ static int locate_fd(unsigned int orig_start, int cloexec) | |||
64 | struct fdtable *fdt; | 64 | struct fdtable *fdt; |
65 | 65 | ||
66 | spin_lock(&files->file_lock); | 66 | spin_lock(&files->file_lock); |
67 | |||
68 | error = -EINVAL; | ||
69 | if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) | ||
70 | goto out; | ||
71 | |||
72 | repeat: | 67 | repeat: |
73 | fdt = files_fdtable(files); | 68 | fdt = files_fdtable(files); |
74 | /* | 69 | /* |
@@ -83,10 +78,6 @@ repeat: | |||
83 | if (start < fdt->max_fds) | 78 | if (start < fdt->max_fds) |
84 | newfd = find_next_zero_bit(fdt->open_fds->fds_bits, | 79 | newfd = find_next_zero_bit(fdt->open_fds->fds_bits, |
85 | fdt->max_fds, start); | 80 | fdt->max_fds, start); |
86 | |||
87 | error = -EMFILE; | ||
88 | if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) | ||
89 | goto out; | ||
90 | 81 | ||
91 | error = expand_files(files, newfd); | 82 | error = expand_files(files, newfd); |
92 | if (error < 0) | 83 | if (error < 0) |
@@ -135,20 +126,20 @@ asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags) | |||
135 | if ((flags & ~O_CLOEXEC) != 0) | 126 | if ((flags & ~O_CLOEXEC) != 0) |
136 | return -EINVAL; | 127 | return -EINVAL; |
137 | 128 | ||
129 | if (unlikely(oldfd == newfd)) | ||
130 | return -EINVAL; | ||
131 | |||
138 | spin_lock(&files->file_lock); | 132 | spin_lock(&files->file_lock); |
139 | if (!(file = fcheck(oldfd))) | 133 | if (!(file = fcheck(oldfd))) |
140 | goto out_unlock; | 134 | goto out_unlock; |
141 | err = newfd; | ||
142 | if (newfd == oldfd) | ||
143 | goto out_unlock; | ||
144 | err = -EBADF; | ||
145 | if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) | ||
146 | goto out_unlock; | ||
147 | get_file(file); /* We are now finished with oldfd */ | 135 | get_file(file); /* We are now finished with oldfd */ |
148 | 136 | ||
149 | err = expand_files(files, newfd); | 137 | err = expand_files(files, newfd); |
150 | if (err < 0) | 138 | if (unlikely(err < 0)) { |
139 | if (err == -EMFILE) | ||
140 | err = -EBADF; | ||
151 | goto out_fput; | 141 | goto out_fput; |
142 | } | ||
152 | 143 | ||
153 | /* To avoid races with open() and dup(), we will mark the fd as | 144 | /* To avoid races with open() and dup(), we will mark the fd as |
154 | * in-use in the open-file bitmap throughout the entire dup2() | 145 | * in-use in the open-file bitmap throughout the entire dup2() |
@@ -189,6 +180,14 @@ out_fput: | |||
189 | 180 | ||
190 | asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd) | 181 | asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd) |
191 | { | 182 | { |
183 | if (unlikely(newfd == oldfd)) { /* corner case */ | ||
184 | struct files_struct *files = current->files; | ||
185 | rcu_read_lock(); | ||
186 | if (!fcheck_files(files, oldfd)) | ||
187 | oldfd = -EBADF; | ||
188 | rcu_read_unlock(); | ||
189 | return oldfd; | ||
190 | } | ||
192 | return sys_dup3(oldfd, newfd, 0); | 191 | return sys_dup3(oldfd, newfd, 0); |
193 | } | 192 | } |
194 | 193 | ||
@@ -321,6 +320,8 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, | |||
321 | switch (cmd) { | 320 | switch (cmd) { |
322 | case F_DUPFD: | 321 | case F_DUPFD: |
323 | case F_DUPFD_CLOEXEC: | 322 | case F_DUPFD_CLOEXEC: |
323 | if (arg >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) | ||
324 | break; | ||
324 | get_file(filp); | 325 | get_file(filp); |
325 | err = dupfd(filp, arg, cmd == F_DUPFD_CLOEXEC); | 326 | err = dupfd(filp, arg, cmd == F_DUPFD_CLOEXEC); |
326 | break; | 327 | break; |