[PATCH RFC POC 34/50] sctp: install the peeloff descriptor when the syscall returns

From: Christian Brauner

Date: Tue Sep 15 2026 - 08:01:19 EST


Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@xxxxxxxxxx>
---
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