From: Simon Horman <horms@kernel.org>
To: lucien.xin@gmail.com
Cc: Simon Horman <horms@kernel.org>,
netdev@vger.kernel.org, linux-sctp@vger.kernel.org,
davem@davemloft.net, kuba@kernel.org, edumazet@google.com,
pabeni@redhat.com, marcelo.leitner@gmail.com
Subject: Re: [PATCH net 1/2] sctp: factor out INIT verification failure handling
Date: Wed, 17 Jun 2026 11:39:54 +0100 [thread overview]
Message-ID: <20260617103954.852101-1-horms@kernel.org> (raw)
In-Reply-To: <6fb546c80126a410349e724045ce16a41413c8a6.1781570014.git.lucien.xin@gmail.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://netdev-ai.bots.linux.dev/sashiko/
---
sctp: factor out INIT verification failure handling
This refactor moves the duplicated INIT/INIT-ACK error handling out of
sctp_sf_do_5_1B_init(), sctp_sf_do_5_1C_ack(), and
sctp_sf_do_unexpected_init() into a new helper sctp_abort_on_init_err().
The commit message states "No functional change intended."
> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
> index 9b23c11cbb9e..544f308ee527 100644
> --- a/net/sctp/sm_statefuns.c
> +++ b/net/sctp/sm_statefuns.c
[ ... ]
> @@ -548,50 +531,9 @@ enum sctp_disposition sctp_sf_do_5_1C_ack(struct net *net,
> err_chunk = NULL;
> if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type,
> (struct sctp_init_chunk *)chunk->chunk_hdr, chunk,
> - &err_chunk)) {
> -
> - enum sctp_error error = SCTP_ERROR_NO_RESOURCE;
> -
> - /* This chunk contains fatal error. It is to be discarded.
> - * Send an ABORT, with causes. If there are no causes,
> - * then there wasn't enough memory. Just terminate
> - * the association.
> - */
> - if (err_chunk) {
> - packet = sctp_abort_pkt_new(net, ep, asoc, arg,
> - (__u8 *)(err_chunk->chunk_hdr) +
> - sizeof(struct sctp_chunkhdr),
> - ntohs(err_chunk->chunk_hdr->length) -
> - sizeof(struct sctp_chunkhdr));
> -
> - sctp_chunk_free(err_chunk);
> -
> - if (packet) {
> - sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
> - SCTP_PACKET(packet));
> - SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
> - error = SCTP_ERROR_INV_PARAM;
> - }
> - }
> -
> - /* SCTP-AUTH, Section 6.3:
> - * It should be noted that if the receiver wants to tear
> - * down an association in an authenticated way only, the
> - * handling of malformed packets should not result in
> - * tearing down the association.
> - *
> - * This means that if we only want to abort associations
> - * in an authenticated way (i.e AUTH+ABORT), then we
> - * can't destroy this association just because the packet
> - * was malformed.
> - */
> - if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
> - return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
> -
> - SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> - return sctp_stop_t1_and_abort(net, commands, error, ECONNREFUSED,
> - asoc, chunk->transport);
> - }
> + &err_chunk))
> + return sctp_abort_on_init_err(net, ep, asoc, chunk, arg,
> + commands, err_chunk);
[High]
In the original sctp_sf_do_5_1C_ack() the "if (err_chunk) { ... }"
block is non-controlling: when err_chunk is NULL the code skips the
block, falls through with error == SCTP_ERROR_NO_RESOURCE, consults
sctp_auth_recv_cid(SCTP_CID_ABORT, asoc) and either pdiscards or runs
sctp_stop_t1_and_abort() to tear the half-open association down.
[High]
In the new helper, can the INIT-ACK + NULL err_chunk case still reach
that path? Looking at sctp_abort_on_init_err():
if (!err_chunk)
return sctp_sf_tabort_8_4_8(net, ep, asoc, SCTP_ST_CHUNK(0),
arg, commands);
...
if (chunk->chunk_hdr->type != SCTP_CID_INIT_ACK) {
...
}
/* SCTP-AUTH, Section 6.3 ... */
if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
return sctp_sf_pdiscard(...);
SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
return sctp_stop_t1_and_abort(net, commands, error, ECONNREFUSED,
asoc, chunk->transport);
[High]
The !err_chunk early return runs before the INIT-ACK type check, so
when sctp_verify_init() returns 0 with *errp left as NULL on an
INIT-ACK, control now goes to sctp_sf_tabort_8_4_8() rather than the
auth-check + sctp_stop_t1_and_abort() path.
[High]
Is the NULL-err_chunk case actually reachable on an INIT-ACK? In
sctp_process_inv_mandatory() and sctp_process_inv_paramlength() in
net/sctp/sm_make_chunk.c, *errp is allocated via sctp_make_op_error_space()
or sctp_make_violation_paramlen() and the function returns 0
unconditionally:
if (!*errp)
*errp = sctp_make_op_error_space(asoc, chunk, 0);
if (*errp)
sctp_init_cause(...);
return 0;
So an allocation failure on a malformed INIT-ACK reaches the helper
with err_chunk == NULL.
[High]
On that path, does the new code skip several actions that the original
performed? sctp_sf_tabort_8_4_8() emits an OOTB ABORT and pdiscards;
it does not stop T1-init, does not call SCTP_CMD_SET_SK_ERR(ECONNREFUSED),
does not issue SCTP_CMD_INIT_FAILED, does not transition the asoc to
SCTP_STATE_CLOSED, and does not increment SCTP_MIB_ABORTEDS.
[High]
As a result, would connect(2) wait for T1-init to exhaust its
retransmissions instead of receiving ECONNREFUSED promptly, and would
SCTP_MIB_ABORTEDS no longer be incremented (with SCTP_MIB_IN_PKT_DISCARDS
being incremented in its place)?
[High]
Does this also bypass the SCTP-AUTH section 6.3 check quoted in the
comment? Previously, when AUTH-ABORT was negotiated and err_chunk
was NULL, sctp_auth_recv_cid() caused sctp_sf_pdiscard() to be returned
and no ABORT was emitted on the wire. In the new path, sctp_sf_tabort_8_4_8()
sends an unauthenticated OOTB ABORT regardless of AUTH negotiation.
[High]
Finally, does the disposition return value also change from
SCTP_DISPOSITION_ABORT to SCTP_DISPOSITION_CONSUME on this path?
[High]
Would moving the chunk->chunk_hdr->type check ahead of the !err_chunk
early return restore the original semantics for INIT-ACK while keeping
the sctp_sf_tabort_8_4_8() fallback for INIT?
[ ... ]
> @@ -6485,6 +6403,61 @@ static void sctp_send_stale_cookie_err(struct net *net,
> }
> }
>
> +static enum sctp_disposition sctp_abort_on_init_err(
> + struct net *net,
> + const struct sctp_endpoint *ep,
> + const struct sctp_association *asoc,
> + const struct sctp_chunk *chunk,
> + void *arg,
> + struct sctp_cmd_seq *commands,
> + struct sctp_chunk *err_chunk)
> +{
> + enum sctp_error error = SCTP_ERROR_NO_RESOURCE;
> + struct sctp_packet *packet;
> + struct sctp_chunkhdr *ch;
> +
> + if (!err_chunk)
> + return sctp_sf_tabort_8_4_8(net, ep, asoc, SCTP_ST_CHUNK(0),
> + arg, commands);
> +
> + ch = err_chunk->chunk_hdr;
> + packet = sctp_abort_pkt_new(net, ep, asoc, arg,
> + (__u8 *)ch + sizeof(*ch),
> + ntohs(ch->length) - sizeof(*ch));
> +
> + sctp_chunk_free(err_chunk);
> +
> + if (packet) {
> + sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
> + SCTP_PACKET(packet));
> + SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
> + error = SCTP_ERROR_INV_PARAM;
> + }
> +
> + if (chunk->chunk_hdr->type != SCTP_CID_INIT_ACK) {
> + if (!packet)
> + return SCTP_DISPOSITION_NOMEM;
> + return SCTP_DISPOSITION_CONSUME;
> + }
> + /* SCTP-AUTH, Section 6.3:
> + * It should be noted that if the receiver wants to tear
> + * down an association in an authenticated way only, the
> + * handling of malformed packets should not result in
> + * tearing down the association.
> + *
> + * This means that if we only want to abort associations
> + * in an authenticated way (i.e AUTH+ABORT), then we
> + * can't destroy this association just because the packet
> + * was malformed.
> + */
> + if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
> + return sctp_sf_pdiscard(net, ep, asoc, SCTP_ST_CHUNK(0), arg,
> + commands);
> +
> + SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> + return sctp_stop_t1_and_abort(net, commands, error, ECONNREFUSED,
> + asoc, chunk->transport);
> +}
next prev parent reply other threads:[~2026-06-17 10:40 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-16 0:33 [PATCH net 0/2] sctp: validate INIT in COOKIE-ECHO when auth disabled Xin Long
2026-06-16 0:33 ` [PATCH net 1/2] sctp: factor out INIT verification failure handling Xin Long
2026-06-17 10:39 ` Simon Horman [this message]
2026-06-16 0:33 ` [PATCH net 2/2] sctp: add INIT verification after cookie unpacking Xin Long
2026-06-17 10:40 ` Simon Horman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260617103954.852101-1-horms@kernel.org \
--to=horms@kernel.org \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=linux-sctp@vger.kernel.org \
--cc=lucien.xin@gmail.com \
--cc=marcelo.leitner@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox