Skip to content

Commit 85f54cf

Browse files
lxingregkh
authored andcommitted
sctp: validate embedded address parameter length
[ Upstream commit e9361d0 ] 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: 1da177e ("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> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 53788b1 commit 85f54cf

1 file changed

Lines changed: 8 additions & 2 deletions

File tree

net/sctp/sm_make_chunk.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2662,6 +2662,9 @@ static int sctp_process_param(struct sctp_association *asoc,
26622662
goto fall_through;
26632663

26642664
addr_param = param.v + sizeof(struct sctp_addip_param);
2665+
if (ntohs(addr_param->p.length) >
2666+
ntohs(param.p->length) - sizeof(struct sctp_addip_param))
2667+
break;
26652668

26662669
af = sctp_get_af_specific(param_type2af(addr_param->p.type));
26672670
if (!af)
@@ -3060,13 +3063,16 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
30603063
union sctp_addr addr;
30613064
struct sctp_af *af;
30623065

3063-
addr_param = (void *)asconf_param + sizeof(*asconf_param);
3064-
30653066
if (asconf_param->param_hdr.type != SCTP_PARAM_ADD_IP &&
30663067
asconf_param->param_hdr.type != SCTP_PARAM_DEL_IP &&
30673068
asconf_param->param_hdr.type != SCTP_PARAM_SET_PRIMARY)
30683069
return SCTP_ERROR_UNKNOWN_PARAM;
30693070

3071+
addr_param = (void *)asconf_param + sizeof(*asconf_param);
3072+
if (ntohs(addr_param->p.length) >
3073+
ntohs(asconf_param->param_hdr.length) - sizeof(*asconf_param))
3074+
return SCTP_ERROR_PROTO_VIOLATION;
3075+
30703076
switch (addr_param->p.type) {
30713077
case SCTP_PARAM_IPV6_ADDRESS:
30723078
if (!asoc->peer.ipv6_address)

0 commit comments

Comments
 (0)