Accepted mainline fix74b21f52c5c5net/sctpPatch author · Linux 7.2

Proof/Linux kernel/sctp: Adaptation Indication length

KERNEL.01 — Mainline contribution

Generic TLV validity is not type validity.

The generic SCTP parameter walker proved a parameter header existed. A later consumer cast the same pointer to a fixed-layout structure and read a 32-bit field the peer never sent — then returned it in the state cookie.

Commit74b21f52c5c5
Subsystemnet/sctp
Filesm_make_chunk.c
RolePatch author · Signed-off-by
Fixes1da177e4c3f4
MainlineLinux 7.2
Stable6 releases verified
Acked-byXin Long
A fixed-layout SCTP parameter must be validated against the size of its complete typed structure before code reads fields beyond the generic parameter header.
Class
type-specific length under-validation
Trigger
header-only Adaptation Indication
Primitive
bounded 4-byte out-of-parameter read
Observable
value reflected in INIT ACK cookie
Upstream credit.This is an accepted mainline fix authored by Charles Vosburgh. The commit carries Signed-off-by: Charles Vosburgh, Acked-by: Xin Long and Signed-off-by: Jakub Kicinski. No executable reproducer is published.

SCTP INIT parameters are TLVs. Generic TLV validation can prove a parameter header is present and internally parseable — but that does not prove a fixed-layout parameter contains all the fields its concrete type requires.

The Adaptation Layer Indication parameter has a fixed layout: a four-byte SCTP parameter header followed by a 32-bit Adaptation Code Point. The peer controls the declared length.

A fixed-layout SCTP parameter must be validated against the size of its complete typed structure before code reads fields beyond the generic parameter header.

Before the fix, the verification switch grouped Adaptation Layer Indication with parameters that required no additional type-specific validation:

Missing type checksctp_verify_param()
case SCTP_PARAM_UNRECOGNIZED_PARAMETERS:
case SCTP_PARAM_ECN_CAPABLE:
case SCTP_PARAM_ADAPTATION_LAYER_IND:
	break;

Later, ordinary parameter processing assumed the full structure existed:

Typed consumersctp_process_param()
case SCTP_PARAM_ADAPTATION_LAYER_IND:
	asoc->peer.adaptation_ind = ntohl(param.aind->adaptation_ind);
	break;

Two parser layers disagreed: the generic walker accepted a four-byte header, and the type-specific consumer read a field beginning after those four bytes.

This is more than a local out-of-bounds read inside the parser. When the malformed parameter is the last one in an INIT, the missing field is not attacker-supplied parameter data at all — it begins at receive-buffer tailroom. The value read as adaptation_ind then becomes peer association state and is incorporated into the SCTP state cookie returned in the INIT ACK.

01 · Input

Header-only parameter

Four bytes where eight are required, placed last in the INIT.

02 · Accept

Generic walker

Structural TLV validity holds; no type-size check runs.

03 · Read

Past the declaration

The typed consumer dereferences into skb tailroom.

04 · Reflect

State cookie

The four-byte value is returned to the peer in the INIT ACK.

The research used three controls together rather than relying on a crash or on source inspection alone. The strongest local A/B comparison held the kernel base, configuration, guest setup, probe and input shape constant, changing only the patch state.

Baseline

Normal INIT

Establishes that the SCTP listener and packet path are working.

Valid control

Correctly sized parameter

An eight-byte Adaptation Indication verifies the feature works and the supplied code point is preserved.

Malformed case

Header-only parameter

Exercises the missing type-size boundary; before the patch it could reflect a controlled four-byte tail marker.

ENV owned KVM/QEMU guest, init_on_alloc=0 BASELINE normal INIT → INIT ACK: PASS CONTROL valid 8-byte Adaptation Indication → code point preserved MALFORMED 4-byte header-only, last parameter PRIMED tailroom marker observed in returned cookie (pre-patch) DEFAULT VIRTIO zero values across the corresponding sample POST-PATCH malformed request aborted before typed read: PASS
Stated limits. The exact-default allocation control produced zero values, which matters: the source bug is reachable regardless, but observable non-zero disclosure depends on receive-buffer and allocation behaviour. This work does not claim arbitrary-address reads, attacker-selected memory disclosure, deterministic secret extraction, a write primitive, code execution, or privilege escalation.
BoundaryResult
Untrusted inputSCTP INIT parameter type and declared length
Existing checkGeneric parameter-header / TLV validation
Missing checkConcrete struct sctp_adaptation_ind size validation
Unsafe useRead of adaptation_ind beyond the declared parameter
Observable consequenceFour-byte value propagated into the returned state cookie under an affected allocation profile
Parser correctness cannot depend on allocator initialization masking an invalid access.
From finding to accepted patch

A kernel finding is not finished until the patch lands.

Reporting a parser gap is the easy half. The accepted result required a patch that used the subsystem’s existing error path, a claim narrow enough to survive maintainer review, and honest reporting of the allocation-profile dependency.

SK.01

Source mapping

Separate the generic TLV walker from every type-specific consumer that dereferences past the header.

SK.02

Layer hypothesis

Look for parameters whose fixed layout is larger than what the generic check proves.

SK.03

A/B construction

Hold kernel base, config, guest and probe constant; change only the patch state.

SK.04

Skeptic gate

Report the exact-default control that produced zeros rather than only the result that supports the claim.

HUMAN

Patch and upstream review

Author the fix against the existing invalid-parameter-length path, submit, and carry maintainer feedback to acceptance.

Mainline commit 74b21f52c5c5 separates Adaptation Layer Indication from the no-extra-validation cases and checks the complete structure size:

Accepted upstream changenet/sctp/sm_make_chunk.c
case SCTP_PARAM_ADAPTATION_LAYER_IND:
	if (ntohs(param.p->length) != sizeof(*param.aind)) {
		sctp_process_inv_paramlength(asoc, param.p,
					     chunk, err_chunk);
		retval = SCTP_IERROR_ABORT;
	}
	break;

A malformed parameter now follows the existing invalid-parameter-length handling path, and association processing is aborted before sctp_process_param() can read the missing field.

Upstream trailerspublic commit message
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Charles Vosburgh <trilobyte777@gmail.com>
Acked-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

The Fixes: tag names the public upstream vulnerable lineage. This page does not claim that every intervening release was independently executed. Directly reviewed vulnerable source included Linux 7.1.4, Linux 7.2-rc4 and the pre-fix networking-tree base.

TreeReleaseStatus
MainlineLinux 7.2first final release containing the fix
Stable 6.18.y6.18.44verified carrying the change
Stable 6.12.y6.12.103verified carrying the change
Stable 6.6.y6.6.151verified carrying the change
Stable 6.1.y6.1.183verified carrying the change
Stable 5.15.y5.15.216verified carrying the change
Stable 5.10.y5.10.265verified carrying the change

Kernel vendors and downstream distributions should still verify the exact patch status of the branch they ship rather than infer it from version numbering.

A durable regression test should keep all three parser cases together:

  1. baseline INIT succeeds;
  2. a valid eight-byte Adaptation Indication succeeds and retains the supplied value;
  3. a header-only Adaptation Indication is rejected before any typed payload read.

Testing under both clearing and non-clearing allocation profiles is useful. The malformed input should be rejected for parser correctness regardless of whether the surrounding allocator would otherwise make the invalid bytes appear to be zero.

No fixed-layout SCTP field may be read until the parameter length has been validated against the complete structure required by that parameter type.
JULY 2026
Issue validated and patch prepared for Linux networking review.
JULY 2026
Patch submitted upstream.
2026-07-29
Commit 74b21f52c5c5 recorded in upstream Git history.
LINUX 7.2
First final mainline release containing the fix.
AUGUST 2026
Stable inclusion verified across the 6.18, 6.12, 6.6, 6.1, 5.15 and 5.10 releases listed above.
  1. Linux mainline commit 74b21f52c5c5
  2. git.kernel.org commit view
  3. Patch submission and review thread

Credit: Patch authored by Charles Vosburgh and carried upstream with Signed-off-by: Charles Vosburgh. Acknowledged by Xin Long and signed into the networking tree by Jakub Kicinski. Research was AI-assisted through source mapping and hypothesis generation; validation, patch authorship and upstream submission remained human.