[PATCH net 1/1] net: sctp: fix AUTH HMAC list overflow into auth_chunks
From: Ren Wei <hidden>
Date: 2026-07-03 07:19:58
Also in:
linux-sctp
Subsystem:
networking [general], sctp protocol, the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marcelo Ricardo Leitner, Xin Long, Linus Torvalds
From: Zihan Xi <redacted>
sctp_auth_ep_set_hmacs() may advertise a 12-byte HMAC-ALGO parameter when
four identifiers are configured, but the association only stores ten bytes
in c.auth_hmacs. sctp_association_init() copies the advertised length and
overwrites the adjacent auth_chunks field, so sctp_auth_asoc_verify_hmac_id()
accepts forged HMAC identifiers and sctp_auth_get_hmac() indexes past
sctp_hmac_list.
Clamp the stored parameter length to the association buffer, copy only that
many bytes when initializing an association, and reject out-of-range HMAC
identifiers in sctp_auth_get_hmac().
Fixes: 65b07e5d0d09 ("[SCTP]: API updates to suport SCTP-AUTH extensions.")
Cc: stable@vger.kernel.org
Reported-by: Yuan Tan <redacted>
Reported-by: Xin Liu <redacted>
Assisted-by: Codex:gpt-5.4
Signed-off-by: Zihan Xi <redacted>
Reviewed-by: Ren Wei <redacted>
---
net/sctp/associola.c | 10 +++++++---
net/sctp/auth.c | 10 ++++++++--
net/sctp/sm_statefuns.c | 2 ++
3 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 62d3cc1558..760457def6 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c@@ -260,9 +260,13 @@ static struct sctp_association *sctp_association_init( asoc->strreset_enable = ep->strreset_enable; /* Save the hmacs and chunks list into this association */ - if (ep->auth_hmacs_list) - memcpy(asoc->c.auth_hmacs, ep->auth_hmacs_list, - ntohs(ep->auth_hmacs_list->param_hdr.length)); + if (ep->auth_hmacs_list) { + size_t hmac_len = min_t(size_t, + ntohs(ep->auth_hmacs_list->param_hdr.length), + sizeof(asoc->c.auth_hmacs)); + + memcpy(asoc->c.auth_hmacs, ep->auth_hmacs_list, hmac_len); + } if (ep->auth_chunk_list) memcpy(asoc->c.auth_chunks, ep->auth_chunk_list, ntohs(ep->auth_chunk_list->param_hdr.length));
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index be9782760f..4d14bd6185 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c@@ -447,6 +447,8 @@ struct sctp_shared_key *sctp_auth_get_shkey( const struct sctp_hmac *sctp_auth_get_hmac(__u16 hmac_id) { + if (hmac_id >= SCTP_AUTH_NUM_HMACS) + return NULL; return &sctp_hmac_list[hmac_id]; }
@@ -510,6 +512,9 @@ int sctp_auth_asoc_verify_hmac_id(const struct sctp_association *asoc, hmacs = (struct sctp_hmac_algo_param *)asoc->c.auth_hmacs; n_elt = (ntohs(hmacs->param_hdr.length) - sizeof(struct sctp_paramhdr)) >> 1; + n_elt = min_t(__u16, n_elt, + (sizeof(asoc->c.auth_hmacs) - + sizeof(struct sctp_paramhdr)) / sizeof(__u16)); return __sctp_auth_find_hmacid(hmacs->hmac_ids, n_elt, hmac_id); }
@@ -708,8 +713,9 @@ int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep, ep->auth_hmacs_list->hmac_ids[i] = htons(hmacs->shmac_idents[i]); ep->auth_hmacs_list->param_hdr.length = - htons(sizeof(struct sctp_paramhdr) + - hmacs->shmac_num_idents * sizeof(__u16)); + htons(min_t(__u16, sizeof(struct sctp_paramhdr) + + hmacs->shmac_num_idents * sizeof(__u16), + SCTP_AUTH_NUM_HMACS * sizeof(__u16) + 2)); return 0; }
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index d23d935e12..21cda509a0 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c@@ -4431,6 +4431,8 @@ static enum sctp_ierror sctp_sf_authenticate( sig_len = ntohs(chunk->chunk_hdr->length) - sizeof(struct sctp_auth_chunk); hmac = sctp_auth_get_hmac(ntohs(auth_hdr->hmac_id)); + if (!hmac) + return SCTP_IERROR_AUTH_BAD_HMAC; if (sig_len != hmac->hmac_len) return SCTP_IERROR_PROTO_VIOLATION;
--
2.43.0