]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
sctp: validate embedded address parameter length
authorXin Long <lucien.xin@gmail.com>
Tue, 9 Jun 2026 22:14:28 +0000 (18:14 -0400)
committerJakub Kicinski <kuba@kernel.org>
Thu, 11 Jun 2026 22:18:08 +0000 (15:18 -0700)
sctp_verify_asconf() and sctp_verify_param() only validate ADD_IP, DEL_IP,
and SET_PRIMARY parameters against a fixed minimum size of sizeof(struct
sctp_addip_param) + sizeof(struct sctp_paramhdr). This ensures the outer
parameter is large enough to contain an embedded address parameter header,
but does not verify that the embedded address parameter's declared length
fits within the bounds of the outer parameter.

Later, sctp_process_param() and sctp_process_asconf_param() extract the
embedded address parameter and pass it to af->from_addr_param(), which uses
the address parameter length to parse the variable-length address payload.
A malformed peer can therefore advertise an embedded address parameter
length that exceeds the remaining bytes in the enclosing parameter.

Validate that addr_param->p.length does not exceed the space available
after the sctp_addip_param header before processing the embedded address
parameter. Reject malformed parameters when the embedded address length
extends beyond the enclosing parameter bounds.

This prevents out-of-bounds reads when parsing malformed parameters carried
in INIT or ASCONF processing paths.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: sashiko <sashiko-bot@kernel.org>
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Link: https://patch.msgid.link/7838b86b69f52add28808fb59034c8f992e97b2d.1781043268.git.lucien.xin@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/sctp/sm_make_chunk.c

index 1741a9f33d8c7111f4ab304716fa417caf3229cb..41958b8e59fd53643b15e1bf87e8a25b26f636af 100644 (file)
@@ -2641,6 +2641,9 @@ do_addr_param:
                        goto fall_through;
 
                addr_param = param.v + sizeof(struct sctp_addip_param);
+               if (ntohs(addr_param->p.length) >
+                   ntohs(param.p->length) - sizeof(struct sctp_addip_param))
+                       break;
 
                af = sctp_get_af_specific(param_type2af(addr_param->p.type));
                if (!af)
@@ -3039,13 +3042,16 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
        union sctp_addr addr;
        struct sctp_af *af;
 
-       addr_param = (void *)asconf_param + sizeof(*asconf_param);
-
        if (asconf_param->param_hdr.type != SCTP_PARAM_ADD_IP &&
            asconf_param->param_hdr.type != SCTP_PARAM_DEL_IP &&
            asconf_param->param_hdr.type != SCTP_PARAM_SET_PRIMARY)
                return SCTP_ERROR_UNKNOWN_PARAM;
 
+       addr_param = (void *)asconf_param + sizeof(*asconf_param);
+       if (ntohs(addr_param->p.length) >
+           ntohs(asconf_param->param_hdr.length) - sizeof(*asconf_param))
+               return SCTP_ERROR_PROTO_VIOLATION;
+
        switch (addr_param->p.type) {
        case SCTP_PARAM_IPV6_ADDRESS:
                if (!asoc->peer.ipv6_address)