Signed-off-by: Christian Brauner --- net/sctp/socket.c | 89 ++++++++++++++++--------------------------------------- 1 file changed, 25 insertions(+), 64 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index ed8293a34240..03f0317c5c38 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -5664,47 +5664,46 @@ static int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, return err; } -static int sctp_getsockopt_peeloff_common(struct sock *sk, sctp_peeloff_arg_t *peeloff, - struct file **newfile, unsigned flags) +static int sctp_getsockopt_peeloff_common(struct sock *sk, + sctp_peeloff_arg_t *peeloff, int len, + char __user *optval, + int __user *optlen, unsigned flags) { struct socket *newsock; 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) { + FD_PREPARE(fdf, flags & SOCK_CLOEXEC, sock_alloc_file(newsock, 0, NULL)); + retval = ACQUIRE_ERR(fd_prepare, &fdf); + if (retval) { 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; } pr_debug("%s: sk:%p, newsk:%p, sd:%d\n", __func__, sk, newsock->sk, - retval); - - peeloff->sd = retval; + fd_prepare_fd(fdf)); if (flags & SOCK_NONBLOCK) - (*newfile)->f_flags |= O_NONBLOCK; -out: - return retval; + fd_prepare_file(fdf)->f_flags |= O_NONBLOCK; + + /* Return the fd mapped to the new socket. */ + if (put_user(len, optlen)) + return -EFAULT; + + if (copy_to_user(optval, &peeloff, len)) + return -EFAULT; + + peeloff->sd = fd_prepare_fd(fdf); + return fd_publish(fdf); } -static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval, int __user *optlen) +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; if (len < sizeof(sctp_peeloff_arg_t)) return -EINVAL; @@ -5712,33 +5711,13 @@ 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); - if (retval < 0) - goto out; - - /* Return the fd mapped to the new socket. */ - if (put_user(len, optlen)) { - fput(newfile); - put_unused_fd(retval); - return -EFAULT; - } - - if (copy_to_user(optval, &peeloff, len)) { - fput(newfile); - put_unused_fd(retval); - return -EFAULT; - } - fd_install(retval, newfile); -out: - return retval; + return sctp_getsockopt_peeloff_common(sk, &peeloff, len, optval, optlen, 0); } 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; if (len < sizeof(sctp_peeloff_flags_arg_t)) return -EINVAL; @@ -5746,26 +5725,8 @@ static int sctp_getsockopt_peeloff_flags(struct sock *sk, int len, if (copy_from_user(&peeloff, optval, len)) return -EFAULT; - retval = sctp_getsockopt_peeloff_common(sk, &peeloff.p_arg, - &newfile, peeloff.flags); - if (retval < 0) - goto out; - - /* Return the fd mapped to the new socket. */ - if (put_user(len, optlen)) { - fput(newfile); - put_unused_fd(retval); - return -EFAULT; - } - - if (copy_to_user(optval, &peeloff, len)) { - fput(newfile); - put_unused_fd(retval); - return -EFAULT; - } - fd_install(retval, newfile); -out: - return retval; + return sctp_getsockopt_peeloff_common(sk, &peeloff.p_arg, len, optval, + optlen, peeloff.flags); } /* 7.1.13 Peer Address Parameters (SCTP_PEER_ADDR_PARAMS) -- 2.47.3