Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <[email protected]>
---
 net/sctp/socket.c | 78 +++++++++++++++++++++----------------------------------
 1 file changed, 29 insertions(+), 49 deletions(-)

diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index c7b9e325ec1c..b75c50af8c16 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -5744,46 +5744,41 @@ static int sctp_do_peeloff(struct sock *sk, 
sctp_assoc_t id,
 }
 
 static int sctp_getsockopt_peeloff_common(struct sock *sk, sctp_peeloff_arg_t 
*peeloff,
-                                         struct file **newfile, unsigned flags)
+                                         unsigned flags)
 {
        struct socket *newsock;
+       struct file *newfile;
+       const struct fd_slot *fd;
        int retval;
 
        retval = sctp_do_peeloff(sk, peeloff->associd, &newsock);
        if (retval < 0)
-               goto out;
+               return retval;
 
-       /* Map the socket to an unused fd that can be returned to the user.  */
-       retval = get_unused_fd_flags(flags & SOCK_CLOEXEC);
-       if (retval < 0) {
+       /* Map the socket to a reserved fd that can be returned to the user. */
+       fd = fd_prepare(flags & SOCK_CLOEXEC);
+       if (IS_ERR(fd)) {
                sock_release(newsock);
-               goto out;
-       }
-
-       *newfile = sock_alloc_file(newsock, 0, NULL);
-       if (IS_ERR(*newfile)) {
-               put_unused_fd(retval);
-               retval = PTR_ERR(*newfile);
-               *newfile = NULL;
-               return retval;
+               return PTR_ERR(fd);
        }
 
-       pr_debug("%s: sk:%p, newsk:%p, sd:%d\n", __func__, sk, newsock->sk,
-                retval);
-
-       peeloff->sd = retval;
+       newfile = sock_alloc_file(newsock, 0, NULL);
+       if (IS_ERR(newfile))
+               return PTR_ERR(newfile);
 
        if (flags & SOCK_NONBLOCK)
-               (*newfile)->f_flags |= O_NONBLOCK;
-out:
-       return retval;
+               newfile->f_flags |= O_NONBLOCK;
+
+       peeloff->sd = fd_stage(fd, newfile);
+       pr_debug("%s: sk:%p, newsk:%p, sd:%d\n", __func__, sk, newsock->sk,
+                peeloff->sd);
+       return peeloff->sd;
 }
 
 static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user 
*optval, int __user *optlen)
 {
        sctp_peeloff_arg_t peeloff;
-       struct file *newfile = NULL;
-       int retval = 0;
+       int retval;
 
        if (len < sizeof(sctp_peeloff_arg_t))
                return -EINVAL;
@@ -5791,24 +5786,17 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int 
len, char __user *optval
        if (copy_from_user(&peeloff, optval, len))
                return -EFAULT;
 
-       retval = sctp_getsockopt_peeloff_common(sk, &peeloff, &newfile, 0);
+       retval = sctp_getsockopt_peeloff_common(sk, &peeloff, 0);
        if (retval < 0)
-               goto out;
+               return retval;
 
        /* Return the fd mapped to the new socket.  */
-       if (put_user(len, optlen)) {
-               fput(newfile);
-               put_unused_fd(retval);
+       if (put_user(len, optlen))
                return -EFAULT;
-       }
 
-       if (copy_to_user(optval, &peeloff, len)) {
-               fput(newfile);
-               put_unused_fd(retval);
+       if (copy_to_user(optval, &peeloff, len))
                return -EFAULT;
-       }
-       fd_install(retval, newfile);
-out:
+
        return retval;
 }
 
@@ -5816,8 +5804,7 @@ static int sctp_getsockopt_peeloff_flags(struct sock *sk, 
int len,
                                         char __user *optval, int __user 
*optlen)
 {
        sctp_peeloff_flags_arg_t peeloff;
-       struct file *newfile = NULL;
-       int retval = 0;
+       int retval;
 
        if (len < sizeof(sctp_peeloff_flags_arg_t))
                return -EINVAL;
@@ -5826,24 +5813,17 @@ static int sctp_getsockopt_peeloff_flags(struct sock 
*sk, int len,
                return -EFAULT;
 
        retval = sctp_getsockopt_peeloff_common(sk, &peeloff.p_arg,
-                                               &newfile, peeloff.flags);
+                                               peeloff.flags);
        if (retval < 0)
-               goto out;
+               return retval;
 
        /* Return the fd mapped to the new socket.  */
-       if (put_user(len, optlen)) {
-               fput(newfile);
-               put_unused_fd(retval);
+       if (put_user(len, optlen))
                return -EFAULT;
-       }
 
-       if (copy_to_user(optval, &peeloff, len)) {
-               fput(newfile);
-               put_unused_fd(retval);
+       if (copy_to_user(optval, &peeloff, len))
                return -EFAULT;
-       }
-       fd_install(retval, newfile);
-out:
+
        return retval;
 }
 

-- 
2.53.0


Reply via email to