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