Re: [PATCH net] sctp: fix OOB write to userspace in sctp_getsockopt_peer_auth_chunks

Xin Long <[email protected]> Thu, 16 Apr 2026 09:46:51 -0400
Newsgroups org.kernel.vger.linux-sctp,org.kernel.vger.linux-kernel,org.kernel.vger.netdev,org.kernel.vger.stable
Message-ID <CADvbK_d_T++kjJ1U3g8RZRM8AUTHsrqD47Y3EuB3wZQTxeZ6Fg@mail.gmail.com>
On Wed, Apr 15, 2026 at 11:19 PM Michael Bommarito
<[email protected]> wrote:
>
> sctp_getsockopt_peer_auth_chunks() checks that the caller's optval
> buffer is large enough for the peer AUTH chunk list with
>
>     if (len < num_chunks)
>             return -EINVAL;
>
> but then writes num_chunks bytes to p->gauth_chunks, which lives
> at offset offsetof(struct sctp_authchunks, gauth_chunks) == 8
> inside optval.  The check is missing the sizeof(struct
> sctp_authchunks) = 8-byte header.  When the caller supplies
> len == num_chunks (for any num_chunks > 0) the test passes but
> copy_to_user() writes sizeof(struct sctp_authchunks) = 8 bytes
> past the declared buffer.
>
> The sibling function sctp_getsockopt_local_auth_chunks() at the
> next line already has the correct check:
>
>     if (len < sizeof(struct sctp_authchunks) + num_chunks)
>             return -EINVAL;
>
> Align the peer variant with its sibling.
>
> Reproducer confirms on v7.0-13-generic: an unprivileged userspace
> caller that opens a loopback SCTP association with AUTH enabled,
> queries num_chunks with a short optval, then issues the real
> getsockopt with len == num_chunks and sentinel bytes painted past
> the buffer observes those sentinel bytes overwritten with the
> peer's AUTH chunk type.  The bytes written are under the peer's
> control but land in the caller's own userspace; this is not a
> kernel memory corruption, but it is a kernel-side contract
> violation that can silently corrupt adjacent userspace data.
>
> Fixes: 65b07e5d0d09 ("[SCTP]: API updates to suport SCTP-AUTH extensions.")
> Cc: [email protected]
> Assisted-by: Claude:claude-opus-4-6
> Signed-off-by: Michael Bommarito <[email protected]>
> ---
>  net/sctp/socket.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 05fb00c9c335..f5d442753dc9 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -7033,7 +7033,7 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
>
>         /* See if the user provided enough room for all the data */
>         num_chunks = ntohs(ch->param_hdr.length) - sizeof(struct sctp_paramhdr);
> -       if (len < num_chunks)
> +       if (len < sizeof(struct sctp_authchunks) + num_chunks)
>                 return -EINVAL;
>
>         if (copy_to_user(to, ch->chunks, num_chunks))
> --
> 2.53.0
>

Acked-by: Xin Long <[email protected]>