mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] sctp: validate cookie AUTH state before use
@ 2026-08-04 20:00 Jérémy Jean
  2026-08-07 18:47 ` Xin Long
  2026-08-07 22:40 ` patchwork-bot+netdevbpf
  0 siblings, 2 replies; 4+ messages in thread
From: Jérémy Jean @ 2026-08-04 20:00 UTC (permalink / raw)
  To: Marcelo Ricardo Leitner, Xin Long, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, linux-sctp
  Cc: netdev, linux-kernel, Jérémy Jean

When cookie authentication is disabled, COOKIE_ECHO restores fixed-size
AUTH fields directly from peer-controlled cookie bytes.  A forged RANDOM
length, HMAC list, or CHUNKS list can then reach association consumers
with lengths or identifiers that were never validated against the local
backing arrays.

A forged RANDOM length can cause out-of-bounds reads during key-vector
construction.  A forged HMAC identifier also caused a 32-byte write past
a zero-length AUTH chunk, providing a primitive for a local privilege
escalation chain.

Validate the cookie's RANDOM, HMACS, and CHUNKS parameters at the cookie
trust boundary before copying them into the association.  Reject invalid
types, malformed lengths, unsupported HMAC identifiers, HMAC lists
without SHA1, and forbidden chunk ids.

Fixes: bbd0d59809f9 ("[SCTP]: Implement the receive and verification of AUTH chunk")
Fixes: 1f485649f529 ("[SCTP]: Implement SCTP-AUTH internals")
Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
Assisted-by: Codex:gpt-5.5
---
 include/net/sctp/auth.h  |  3 ++
 net/sctp/auth.c          | 75 ++++++++++++++++++++++++++++++++++++++++
 net/sctp/sm_make_chunk.c |  3 ++
 3 files changed, 81 insertions(+)

diff --git a/include/net/sctp/auth.h b/include/net/sctp/auth.h
index 6f2cd562b1de..74b3790e2a3d 100644
--- a/include/net/sctp/auth.h
+++ b/include/net/sctp/auth.h
@@ -22,6 +22,7 @@ struct sctp_endpoint;
 struct sctp_association;
 struct sctp_authkey;
 struct sctp_hmacalgo;
+struct sctp_cookie;
 
 /* Defines an HMAC algorithm supported by SCTP chunk authentication */
 struct sctp_hmac {
@@ -72,6 +73,8 @@ struct sctp_shared_key *sctp_auth_get_shkey(
 int sctp_auth_asoc_copy_shkeys(const struct sctp_endpoint *ep,
 				struct sctp_association *asoc,
 				gfp_t gfp);
+bool sctp_auth_verify_cookie_params(const struct sctp_endpoint *ep,
+				    const struct sctp_cookie *cookie);
 const struct sctp_hmac *sctp_auth_get_hmac(__u16 hmac_id);
 const struct sctp_hmac *
 sctp_auth_asoc_get_hmac(const struct sctp_association *asoc);
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index c901d373af80..cc4229ee116d 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -377,6 +377,81 @@ int sctp_auth_asoc_copy_shkeys(const struct sctp_endpoint *ep,
 	return -ENOMEM;
 }
 
+static bool sctp_auth_chunk_id_forbidden(__u8 chunk_id)
+{
+	switch (chunk_id) {
+	case SCTP_CID_INIT:
+	case SCTP_CID_INIT_ACK:
+	case SCTP_CID_SHUTDOWN_COMPLETE:
+	case SCTP_CID_AUTH:
+		return true;
+	default:
+		return false;
+	}
+}
+
+/* Verify AUTH parameters copied from a state cookie before they are restored
+ * into an association.  When cookie authentication is disabled these fields
+ * are peer-controlled, so they must satisfy the same constraints as locally
+ * generated AUTH parameters.
+ */
+bool sctp_auth_verify_cookie_params(const struct sctp_endpoint *ep,
+				    const struct sctp_cookie *cookie)
+{
+	const struct sctp_paramhdr *random;
+	const struct sctp_hmac_algo_param *hmacs;
+	const struct sctp_chunks_param *chunks;
+	u16 hmacs_len, chunks_len;
+	u16 n_hmacs, n_chunks, i;
+	bool has_sha1 = false;
+
+	if (sctp_sk(ep->base.sk)->cookie_auth_enable || !ep->auth_enable)
+		return true;
+
+	random = (const struct sctp_paramhdr *)cookie->auth_random;
+	if (random->type != SCTP_PARAM_RANDOM ||
+	    ntohs(random->length) != sizeof(*random) + SCTP_AUTH_RANDOM_LENGTH)
+		return false;
+
+	hmacs = (const struct sctp_hmac_algo_param *)cookie->auth_hmacs;
+	hmacs_len = ntohs(hmacs->param_hdr.length);
+	if (hmacs->param_hdr.type != SCTP_PARAM_HMAC_ALGO ||
+	    hmacs_len < sizeof(struct sctp_paramhdr) +
+			sizeof(hmacs->hmac_ids[0]) ||
+	    hmacs_len > sizeof(cookie->auth_hmacs) ||
+	    (hmacs_len - sizeof(struct sctp_paramhdr)) %
+			sizeof(hmacs->hmac_ids[0]))
+		return false;
+
+	n_hmacs = (hmacs_len - sizeof(struct sctp_paramhdr)) /
+		  sizeof(hmacs->hmac_ids[0]);
+	for (i = 0; i < n_hmacs; i++) {
+		u16 hmac_id = ntohs(hmacs->hmac_ids[i]);
+
+		if (!sctp_hmac_supported(hmac_id))
+			return false;
+		if (hmac_id == SCTP_AUTH_HMAC_ID_SHA1)
+			has_sha1 = true;
+	}
+	if (!has_sha1)
+		return false;
+
+	chunks = (const struct sctp_chunks_param *)cookie->auth_chunks;
+	chunks_len = ntohs(chunks->param_hdr.length);
+	if (chunks->param_hdr.type != SCTP_PARAM_CHUNKS ||
+	    chunks_len < sizeof(struct sctp_paramhdr) ||
+	    chunks_len > sizeof(cookie->auth_chunks))
+		return false;
+
+	n_chunks = chunks_len - sizeof(struct sctp_paramhdr);
+	for (i = 0; i < n_chunks; i++) {
+		if (sctp_auth_chunk_id_forbidden(chunks->chunks[i]))
+			return false;
+	}
+
+	return true;
+}
+
 
 /* Public interface to create the association shared key.
  * See code above for the algorithm.
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 0ae30c3c8913..c08a5753fb58 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1852,6 +1852,9 @@ struct sctp_association *sctp_unpack_cookie(
 	/* Set up our peer's port number.  */
 	retval->peer.port = ntohs(chunk->sctp_hdr->source);
 
+	if (!sctp_auth_verify_cookie_params(ep, bear_cookie))
+		goto malformed;
+
 	/* Populate the association from the cookie.  */
 	memcpy(&retval->c, bear_cookie, sizeof(*bear_cookie));
 
-- 
2.47.3

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] sctp: validate cookie AUTH state before use
  2026-08-04 20:00 [PATCH] sctp: validate cookie AUTH state before use Jérémy Jean
@ 2026-08-07 18:47 ` Xin Long
  2026-08-07 18:49   ` Xin Long
  2026-08-07 22:40 ` patchwork-bot+netdevbpf
  1 sibling, 1 reply; 4+ messages in thread
From: Xin Long @ 2026-08-07 18:47 UTC (permalink / raw)
  To: Jérémy Jean
  Cc: Marcelo Ricardo Leitner, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, linux-sctp, netdev,
	linux-kernel

[sashiko-gemini]:
> > +bool sctp_auth_verify_cookie_params(const struct sctp_endpoint *ep,
> > +                                    const struct sctp_cookie *cookie)
> > +{
> > +        const struct sctp_paramhdr *random;
> > +        const struct sctp_hmac_algo_param *hmacs;
> > +        const struct sctp_chunks_param *chunks;
> > +        u16 hmacs_len, chunks_len;
> > +        u16 n_hmacs, n_chunks, i;
> > +        bool has_sha1 = false;
> > +
> > +        if (sctp_sk(ep->base.sk)->cookie_auth_enable || !ep->auth_enable)
> > +                return true;
> This is a pre-existing issue, but does skipping validation when
> cookie_auth_enable is true leave the system vulnerable if auth_enable is
> dynamically toggled?
> When an endpoint has auth_enable = 0, it generates state cookies with a
> zero-initialized auth_hmacs array. If the administrator then dynamically
> enables auth_enable = 1, an attacker could send a COOKIE_ECHO with the
> previously generated cookie (which has a valid MAC) bundled with an AUTH
> chunk.
> Because cookie_auth_enable is true, this check skips validation and the
> zeroed auth_hmacs is restored. When the AUTH chunk is processed,
> sctp_auth_asoc_verify_hmac_id() calculates the element count with a zeroed
> length:
> sctp_auth_asoc_verify_hmac_id() {
>         hmacs = (struct sctp_hmac_algo_param *)asoc->c.auth_hmacs;
>         n_elt = (ntohs(hmacs->param_hdr.length) -
>                  sizeof(struct sctp_paramhdr)) >> 1;
>
>         return __sctp_auth_find_hmacid(hmacs->hmac_ids, n_elt, hmac_id);
> }
> Since length is 0, this underflows to 65534, causing an out-of-bounds read
> of 131,068 bytes past the association allocation in
> __sctp_auth_find_hmacid().

False positive: when cookie_auth_enable is true, the cookie is already
authenticated. The cookie content is generated locally, so validation is
unnecessary.


[sashiko-claude]:
> > +bool sctp_auth_verify_cookie_params(const struct sctp_endpoint *ep,
> > +                                    const struct sctp_cookie *cookie)
> > +{
> > +        const struct sctp_paramhdr *random;
> > +        const struct sctp_hmac_algo_param *hmacs;
> > +        const struct sctp_chunks_param *chunks;
> > +        u16 hmacs_len, chunks_len;
> > +        u16 n_hmacs, n_chunks, i;
> > +        bool has_sha1 = false;
> > +
> > +        if (sctp_sk(ep->base.sk)->cookie_auth_enable || !ep->auth_enable)
> > +                return true;
> Discovered by: opus-5, old-prompts · Missed by: sashiko-gemini
> This isn't a bug introduced by this patch, but does the new invariant leave
> the underflowing consumer reachable in the default configuration?  With
> cookie_auth_enable set (the default from protocol.c), this early return
> skips all validation, and sctp_auth_asoc_verify_hmac_id() still has no
> lower bound on the parameter length:
> net/sctp/auth.c:sctp_auth_asoc_verify_hmac_id() {
>         hmacs = (struct sctp_hmac_algo_param *)asoc->c.auth_hmacs;
>         n_elt = (ntohs(hmacs->param_hdr.length) -
>                  sizeof(struct sctp_paramhdr)) >> 1;
>         return __sctp_auth_find_hmacid(hmacs->hmac_ids, n_elt, hmac_id);
> }
> For a zero-length parameter the unsigned subtraction wraps and the
> truncation into __u16 n_elt yields 65534, so __sctp_auth_find_hmacid()
> scans about 128 KB past the 12-byte asoc->c.auth_hmacs array in softirq
> context.  Note the sibling consumer __sctp_auth_cid() does guard this
> case:
>         if (!param || param->param_hdr.length == 0)
>                 return 0;
> Is a zero-length asoc->c.auth_hmacs together with peer.auth_capable == 1
> reachable without any forged cookie?  It looks like it is:
> sctp_association_init()
>         if (ep->auth_hmacs_list)
>                 memcpy(asoc->c.auth_hmacs, ep->auth_hmacs_list,
>                         ntohs(ep->auth_hmacs_list->param_hdr.length));
> with ep->auth_hmacs_list NULL while ep->auth_enable == 0 (the default in
> sctp_endpoint_init()), so c.auth_hmacs stays all zero.  Afterwards
> sctp_setsockopt_auth_supported() does:
>         ep->auth_enable = !!params->assoc_value;
> and sctp_process_ext_param() then sets, for that same already-created
> association:
>                         if (asoc->ep->auth_enable)
>                                 asoc->peer.auth_capable = 1;
> A remote AUTH chunk then reaches sctp_sf_authenticate() ->
> sctp_auth_asoc_verify_hmac_id() with the underflow.  If the scan happens
> to match the attacker's 16-bit hmac_id, sctp_auth_get_hmac() indexes the
> four-entry sctp_hmac_list[] with that id and the resulting hmac_len gates
> the 20/32-byte digest write in sctp_auth_calculate_hmac().
> Would it be worth adding the same length == 0 guard to
> sctp_auth_asoc_verify_hmac_id(), and bounding the index in
> sctp_auth_get_hmac(), rather than relying only on the conditionally
> executed cookie check?  The same applies to
> sctp_auth_make_key_vector(), which still does:
>         random_len = ntohs(random->param_hdr.length);
>         ...
>         memcpy(new->data, random, random_len);
> out of the fixed 36-byte asoc->c.auth_random.

False positive: same reason as above.

> > +
> > +        random = (const struct sctp_paramhdr *)cookie->auth_random;
> > +        if (random->type != SCTP_PARAM_RANDOM ||
> > +            ntohs(random->length) != sizeof(*random) + SCTP_AUTH_RANDOM_LENGTH)
> > +                return false;
> > +
> > +        hmacs = (const struct sctp_hmac_algo_param *)cookie->auth_hmacs;
> > +        hmacs_len = ntohs(hmacs->param_hdr.length);
> > +        if (hmacs->param_hdr.type != SCTP_PARAM_HMAC_ALGO ||
> > +            hmacs_len < sizeof(struct sctp_paramhdr) +
> > +                        sizeof(hmacs->hmac_ids[0]) ||
> > +            hmacs_len > sizeof(cookie->auth_hmacs) ||
> > +            (hmacs_len - sizeof(struct sctp_paramhdr)) %
> > +                        sizeof(hmacs->hmac_ids[0]))
> > +                return false;
> Discovered by: opus-5, old-prompts · Missed by: sashiko-gemini
> Can these checks reject a cookie this endpoint minted itself?
> The decision to validate is taken from ep->auth_enable sampled at
> COOKIE-ECHO time, not from the state that produced the INIT-ACK, while the
> HMACS and CHUNKS tests unconditionally require a well-formed parameter.  An
> all-zero (absent) auth_hmacs/auth_chunks looks like a state the producer
> legitimately creates:
> net/sctp/associola.c:sctp_association_init() {
>         if (ep->auth_hmacs_list)
>                 memcpy(asoc->c.auth_hmacs, ep->auth_hmacs_list, ...);
>         if (ep->auth_chunk_list)
>                 memcpy(asoc->c.auth_chunks, ep->auth_chunk_list, ...);
> }
> auth_random is the only one of the three always written, and the endpoint
> lists are NULL while ep->auth_enable == 0, which is the default in
> sctp_endpoint_init().  sctp_make_init() treats the zero-length case as
> "parameter omitted" rather than malformed:
>                 auth_hmacs = (struct sctp_paramhdr *)asoc->c.auth_hmacs;
>                 if (auth_hmacs->length)
>                         chunksize += SCTP_PAD4(ntohs(auth_hmacs->length));
>                 else
>                         auth_hmacs = NULL;
> sctp_pack_cookie() copies asoc->c verbatim, so the outstanding cookie
> carries those zeros.  If the application then calls
> setsockopt(SCTP_AUTH_SUPPORTED) while the cookie is still within
> Valid.Cookie.Life, and cookie_hmac_alg is none, the early return above is
> skipped and "hmacs->param_hdr.type != SCTP_PARAM_HMAC_ALGO" fails with
> type 0.
> Given that, does the comment "they must satisfy the same constraints as
> locally generated AUTH parameters" hold?  Locally generated parameters may
> legitimately be absent.

ep->auth_enable can be changed at any time during the handshake, especially
on a listening socket, and we should not change this behavior for backward
compatibility at this time.

If it changes from 0 to 1 while processing a COOKIE-ECHO, the packet will
be rejected and the connection will eventually fail, but it will not lead
to a crash. Changing ep->auth_enable during an active handshake should be
considered invalid SCTP usage.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] sctp: validate cookie AUTH state before use
  2026-08-07 18:47 ` Xin Long
@ 2026-08-07 18:49   ` Xin Long
  0 siblings, 0 replies; 4+ messages in thread
From: Xin Long @ 2026-08-07 18:49 UTC (permalink / raw)
  To: Jérémy Jean
  Cc: Marcelo Ricardo Leitner, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, linux-sctp, netdev,
	linux-kernel

On Fri, Aug 7, 2026 at 2:47 PM Xin Long <lucien.xin@gmail.com> wrote:
>
> [sashiko-gemini]:
> > > +bool sctp_auth_verify_cookie_params(const struct sctp_endpoint *ep,
> > > +                                    const struct sctp_cookie *cookie)
> > > +{
> > > +        const struct sctp_paramhdr *random;
> > > +        const struct sctp_hmac_algo_param *hmacs;
> > > +        const struct sctp_chunks_param *chunks;
> > > +        u16 hmacs_len, chunks_len;
> > > +        u16 n_hmacs, n_chunks, i;
> > > +        bool has_sha1 = false;
> > > +
> > > +        if (sctp_sk(ep->base.sk)->cookie_auth_enable || !ep->auth_enable)
> > > +                return true;
> > This is a pre-existing issue, but does skipping validation when
> > cookie_auth_enable is true leave the system vulnerable if auth_enable is
> > dynamically toggled?
> > When an endpoint has auth_enable = 0, it generates state cookies with a
> > zero-initialized auth_hmacs array. If the administrator then dynamically
> > enables auth_enable = 1, an attacker could send a COOKIE_ECHO with the
> > previously generated cookie (which has a valid MAC) bundled with an AUTH
> > chunk.
> > Because cookie_auth_enable is true, this check skips validation and the
> > zeroed auth_hmacs is restored. When the AUTH chunk is processed,
> > sctp_auth_asoc_verify_hmac_id() calculates the element count with a zeroed
> > length:
> > sctp_auth_asoc_verify_hmac_id() {
> >         hmacs = (struct sctp_hmac_algo_param *)asoc->c.auth_hmacs;
> >         n_elt = (ntohs(hmacs->param_hdr.length) -
> >                  sizeof(struct sctp_paramhdr)) >> 1;
> >
> >         return __sctp_auth_find_hmacid(hmacs->hmac_ids, n_elt, hmac_id);
> > }
> > Since length is 0, this underflows to 65534, causing an out-of-bounds read
> > of 131,068 bytes past the association allocation in
> > __sctp_auth_find_hmacid().
>
> False positive: when cookie_auth_enable is true, the cookie is already
> authenticated. The cookie content is generated locally, so validation is
> unnecessary.
>
>
> [sashiko-claude]:
> > > +bool sctp_auth_verify_cookie_params(const struct sctp_endpoint *ep,
> > > +                                    const struct sctp_cookie *cookie)
> > > +{
> > > +        const struct sctp_paramhdr *random;
> > > +        const struct sctp_hmac_algo_param *hmacs;
> > > +        const struct sctp_chunks_param *chunks;
> > > +        u16 hmacs_len, chunks_len;
> > > +        u16 n_hmacs, n_chunks, i;
> > > +        bool has_sha1 = false;
> > > +
> > > +        if (sctp_sk(ep->base.sk)->cookie_auth_enable || !ep->auth_enable)
> > > +                return true;
> > Discovered by: opus-5, old-prompts · Missed by: sashiko-gemini
> > This isn't a bug introduced by this patch, but does the new invariant leave
> > the underflowing consumer reachable in the default configuration?  With
> > cookie_auth_enable set (the default from protocol.c), this early return
> > skips all validation, and sctp_auth_asoc_verify_hmac_id() still has no
> > lower bound on the parameter length:
> > net/sctp/auth.c:sctp_auth_asoc_verify_hmac_id() {
> >         hmacs = (struct sctp_hmac_algo_param *)asoc->c.auth_hmacs;
> >         n_elt = (ntohs(hmacs->param_hdr.length) -
> >                  sizeof(struct sctp_paramhdr)) >> 1;
> >         return __sctp_auth_find_hmacid(hmacs->hmac_ids, n_elt, hmac_id);
> > }
> > For a zero-length parameter the unsigned subtraction wraps and the
> > truncation into __u16 n_elt yields 65534, so __sctp_auth_find_hmacid()
> > scans about 128 KB past the 12-byte asoc->c.auth_hmacs array in softirq
> > context.  Note the sibling consumer __sctp_auth_cid() does guard this
> > case:
> >         if (!param || param->param_hdr.length == 0)
> >                 return 0;
> > Is a zero-length asoc->c.auth_hmacs together with peer.auth_capable == 1
> > reachable without any forged cookie?  It looks like it is:
> > sctp_association_init()
> >         if (ep->auth_hmacs_list)
> >                 memcpy(asoc->c.auth_hmacs, ep->auth_hmacs_list,
> >                         ntohs(ep->auth_hmacs_list->param_hdr.length));
> > with ep->auth_hmacs_list NULL while ep->auth_enable == 0 (the default in
> > sctp_endpoint_init()), so c.auth_hmacs stays all zero.  Afterwards
> > sctp_setsockopt_auth_supported() does:
> >         ep->auth_enable = !!params->assoc_value;
> > and sctp_process_ext_param() then sets, for that same already-created
> > association:
> >                         if (asoc->ep->auth_enable)
> >                                 asoc->peer.auth_capable = 1;
> > A remote AUTH chunk then reaches sctp_sf_authenticate() ->
> > sctp_auth_asoc_verify_hmac_id() with the underflow.  If the scan happens
> > to match the attacker's 16-bit hmac_id, sctp_auth_get_hmac() indexes the
> > four-entry sctp_hmac_list[] with that id and the resulting hmac_len gates
> > the 20/32-byte digest write in sctp_auth_calculate_hmac().
> > Would it be worth adding the same length == 0 guard to
> > sctp_auth_asoc_verify_hmac_id(), and bounding the index in
> > sctp_auth_get_hmac(), rather than relying only on the conditionally
> > executed cookie check?  The same applies to
> > sctp_auth_make_key_vector(), which still does:
> >         random_len = ntohs(random->param_hdr.length);
> >         ...
> >         memcpy(new->data, random, random_len);
> > out of the fixed 36-byte asoc->c.auth_random.
>
> False positive: same reason as above.
>
> > > +
> > > +        random = (const struct sctp_paramhdr *)cookie->auth_random;
> > > +        if (random->type != SCTP_PARAM_RANDOM ||
> > > +            ntohs(random->length) != sizeof(*random) + SCTP_AUTH_RANDOM_LENGTH)
> > > +                return false;
> > > +
> > > +        hmacs = (const struct sctp_hmac_algo_param *)cookie->auth_hmacs;
> > > +        hmacs_len = ntohs(hmacs->param_hdr.length);
> > > +        if (hmacs->param_hdr.type != SCTP_PARAM_HMAC_ALGO ||
> > > +            hmacs_len < sizeof(struct sctp_paramhdr) +
> > > +                        sizeof(hmacs->hmac_ids[0]) ||
> > > +            hmacs_len > sizeof(cookie->auth_hmacs) ||
> > > +            (hmacs_len - sizeof(struct sctp_paramhdr)) %
> > > +                        sizeof(hmacs->hmac_ids[0]))
> > > +                return false;
> > Discovered by: opus-5, old-prompts · Missed by: sashiko-gemini
> > Can these checks reject a cookie this endpoint minted itself?
> > The decision to validate is taken from ep->auth_enable sampled at
> > COOKIE-ECHO time, not from the state that produced the INIT-ACK, while the
> > HMACS and CHUNKS tests unconditionally require a well-formed parameter.  An
> > all-zero (absent) auth_hmacs/auth_chunks looks like a state the producer
> > legitimately creates:
> > net/sctp/associola.c:sctp_association_init() {
> >         if (ep->auth_hmacs_list)
> >                 memcpy(asoc->c.auth_hmacs, ep->auth_hmacs_list, ...);
> >         if (ep->auth_chunk_list)
> >                 memcpy(asoc->c.auth_chunks, ep->auth_chunk_list, ...);
> > }
> > auth_random is the only one of the three always written, and the endpoint
> > lists are NULL while ep->auth_enable == 0, which is the default in
> > sctp_endpoint_init().  sctp_make_init() treats the zero-length case as
> > "parameter omitted" rather than malformed:
> >                 auth_hmacs = (struct sctp_paramhdr *)asoc->c.auth_hmacs;
> >                 if (auth_hmacs->length)
> >                         chunksize += SCTP_PAD4(ntohs(auth_hmacs->length));
> >                 else
> >                         auth_hmacs = NULL;
> > sctp_pack_cookie() copies asoc->c verbatim, so the outstanding cookie
> > carries those zeros.  If the application then calls
> > setsockopt(SCTP_AUTH_SUPPORTED) while the cookie is still within
> > Valid.Cookie.Life, and cookie_hmac_alg is none, the early return above is
> > skipped and "hmacs->param_hdr.type != SCTP_PARAM_HMAC_ALGO" fails with
> > type 0.
> > Given that, does the comment "they must satisfy the same constraints as
> > locally generated AUTH parameters" hold?  Locally generated parameters may
> > legitimately be absent.
>
> ep->auth_enable can be changed at any time during the handshake, especially
> on a listening socket, and we should not change this behavior for backward
> compatibility at this time.
>
> If it changes from 0 to 1 while processing a COOKIE-ECHO, the packet will
> be rejected and the connection will eventually fail, but it will not lead
> to a crash. Changing ep->auth_enable during an active handshake should be
> considered invalid SCTP usage.

Acked-by: Xin Long <lucien.xin@gmail.com>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] sctp: validate cookie AUTH state before use
  2026-08-04 20:00 [PATCH] sctp: validate cookie AUTH state before use Jérémy Jean
  2026-08-07 18:47 ` Xin Long
@ 2026-08-07 22:40 ` patchwork-bot+netdevbpf
  1 sibling, 0 replies; 4+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-08-07 22:40 UTC (permalink / raw)
  To: =?utf-8?b?SsOpcsOpbXkgSmVhbiA8SmVyZW15LkplYW5Ab3NzLmN5YmVyLmdvdXYuZnI+?=
  Cc: marcelo.leitner, lucien.xin, davem, edumazet, kuba, pabeni,
	horms, linux-sctp, netdev, linux-kernel

Hello:

This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Tue,  4 Aug 2026 20:00:42 +0000 you wrote:
> When cookie authentication is disabled, COOKIE_ECHO restores fixed-size
> AUTH fields directly from peer-controlled cookie bytes.  A forged RANDOM
> length, HMAC list, or CHUNKS list can then reach association consumers
> with lengths or identifiers that were never validated against the local
> backing arrays.
> 
> A forged RANDOM length can cause out-of-bounds reads during key-vector
> construction.  A forged HMAC identifier also caused a 32-byte write past
> a zero-length AUTH chunk, providing a primitive for a local privilege
> escalation chain.
> 
> [...]

Here is the summary with links:
  - sctp: validate cookie AUTH state before use
    https://git.kernel.org/netdev/net/c/3dbb44d88b1e

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-08-07 22:40 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-04 20:00 [PATCH] sctp: validate cookie AUTH state before use Jérémy Jean
2026-08-07 18:47 ` Xin Long
2026-08-07 18:49   ` Xin Long
2026-08-07 22:40 ` patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®