[PATCH] get rid of corner case in dup3() entirely
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 26 Jul 2008 17:38:19 +0000 (13:38 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 27 Jul 2008 00:53:44 +0000 (20:53 -0400)
Since Ulrich is OK with getting rid of dup3(fd, fd, flags) completely,
to hell the damn thing goes.  Corner case for dup2() is handled in
sys_dup2() (complete with -EBADF if dup2(fd, fd) is called with fd
that is not open), the rest is done in dup3().

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/fcntl.c

index ce12a68..3deec98 100644 (file)
@@ -135,18 +135,12 @@ asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags)
        if ((flags & ~O_CLOEXEC) != 0)
                return -EINVAL;
 
+       if (unlikely(oldfd == newfd))
+               return -EINVAL;
+
        spin_lock(&files->file_lock);
        if (!(file = fcheck(oldfd)))
                goto out_unlock;
-       err = newfd;
-       if (unlikely(newfd == oldfd)) {
-               if (flags & O_CLOEXEC) {
-                       fdt = files_fdtable(files);
-                       FD_SET(newfd, fdt->close_on_exec);
-               }
-               goto out_unlock;
-       }
-       err = -EBADF;
        if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
                goto out_unlock;
        get_file(file);                 /* We are now finished with oldfd */
@@ -194,6 +188,14 @@ out_fput:
 
 asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
 {
+       if (unlikely(newfd == oldfd)) { /* corner case */
+               struct files_struct *files = current->files;
+               rcu_read_lock();
+               if (!fcheck_files(files, oldfd))
+                       oldfd = -EBADF;
+               rcu_read_unlock();
+               return oldfd;
+       }
        return sys_dup3(oldfd, newfd, 0);
 }