Proof/Linux kernel/sctp: Adaptation Indication length
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.
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:
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:
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.
Header-only parameter
Four bytes where eight are required, placed last in the INIT.
Generic walker
Structural TLV validity holds; no type-size check runs.
Past the declaration
The typed consumer dereferences into skb tailroom.
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.
Normal INIT
Establishes that the SCTP listener and packet path are working.
Correctly sized parameter
An eight-byte Adaptation Indication verifies the feature works and the supplied code point is preserved.
Header-only parameter
Exercises the missing type-size boundary; before the patch it could reflect a controlled four-byte tail marker.
| Boundary | Result |
|---|---|
| Untrusted input | SCTP INIT parameter type and declared length |
| Existing check | Generic parameter-header / TLV validation |
| Missing check | Concrete struct sctp_adaptation_ind size validation |
| Unsafe use | Read of adaptation_ind beyond the declared parameter |
| Observable consequence | Four-byte value propagated into the returned state cookie under an affected allocation profile |
Parser correctness cannot depend on allocator initialization masking an invalid access.
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.
Source mapping
Separate the generic TLV walker from every type-specific consumer that dereferences past the header.
Layer hypothesis
Look for parameters whose fixed layout is larger than what the generic check proves.
A/B construction
Hold kernel base, config, guest and probe constant; change only the patch state.
Skeptic gate
Report the exact-default control that produced zeros rather than only the result that supports the claim.
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:
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.
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.
| Tree | Release | Status |
|---|---|---|
| Mainline | Linux 7.2 | first final release containing the fix |
| Stable 6.18.y | 6.18.44 | verified carrying the change |
| Stable 6.12.y | 6.12.103 | verified carrying the change |
| Stable 6.6.y | 6.6.151 | verified carrying the change |
| Stable 6.1.y | 6.1.183 | verified carrying the change |
| Stable 5.15.y | 5.15.216 | verified carrying the change |
| Stable 5.10.y | 5.10.265 | verified 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:
- baseline INIT succeeds;
- a valid eight-byte Adaptation Indication succeeds and retains the supplied value;
- 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.
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.