Received: by 2002:a05:6a10:5bc5:0:0:0:0 with SMTP id os5csp2829471pxb; Mon, 1 Nov 2021 02:42:36 -0700 (PDT) X-Google-Smtp-Source: ABdhPJydDw6NRYnEJFQLGIyIUmqry+Gn/Z8a1K2uS9DACK07pFfSSYZsE8sNbHMpVfw+eYa10MLf X-Received: by 2002:a17:906:c005:: with SMTP id e5mr34527529ejz.480.1635759756608; Mon, 01 Nov 2021 02:42:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1635759756; cv=none; d=google.com; s=arc-20160816; b=tqSDZm+PWk6b54hlNuaLJYOEpKCenKZZ16+H3Wi3q3admeP6VDYCrokE3ncGXOVjtw O5i6gcho2C1rrSimVJpFODe0zfs3u8BYsC/wYaLjAgFKHQcWh3SJvV3QcIK82QOvs93b dZF4mULul9WYaUE8Xkf5DMntC5fVXKhnPfdN9qbJiZB8gP8n0ZqKGAjIQJdGRqkUtEeX oYQcc6hN78lgjM7S6n/QEaCOm5vfIRdcgkYMDDXoUF8Hs8RT2OZpUHjIu6X3xSGatG+q heFIP5h4E9Gtnhxj+pUJM66eh7uzyLwogfem4D0j9kQFgpHduLHxqY5k66i4VXs5LyJa 1EvA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=+cnRo+LndFEEsmAssml/cjRXXNs0u9UhEFPl+R8p+ic=; b=d4lN8dlO2F0NwgbZ3LX0mEdsjqFBUZzBhjpaD8SkdqENJhzEd8KE67sRuZVVmNl9Yp WnVOfHmSpNCRc7m+zfXBXFQdJbUZoTnY4mPm0+SVA0NgRKuzsNgBjX9FcCs1dYvvWUqa nvj0wAVTViSOasFflRdnxpcp0bDiR56Hr6xSy9UnIc63oWaFAgf/kQfFiUpIfWPQgbhf W3/2ddmVq/qjmZuRgAosAhHz/fhRHuxxUe4WGwVWRmLnT12BtKdZJGhAAwwhq0ifuAZD 1dk55dwEGKsICnYlolryDT2oNiTO340jM/SpH0N7fHtxGo9S1PHNUWl+IR/EUFnPqYF7 xH0g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=HbZJ72Ve; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id qk12si23604154ejc.631.2021.11.01.02.42.13; Mon, 01 Nov 2021 02:42:36 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=HbZJ72Ve; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233688AbhKAJkM (ORCPT + 99 others); Mon, 1 Nov 2021 05:40:12 -0400 Received: from mail.kernel.org ([198.145.29.99]:43594 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232556AbhKAJhs (ORCPT ); Mon, 1 Nov 2021 05:37:48 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id EE038611CA; Mon, 1 Nov 2021 09:26:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1635758807; bh=uSR3PZPp5qtAhh3J7+ecbG6Ur4HJljEGrS071nObm7E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HbZJ72VeeEq7fqdjHp4ZSvTzhhhywlpAUPj6GhSZUg64CM6xbyvs06OLtfPwpAI4t uQFSMS9RIe5JvOaI75C0siIXUPNIhlVJFXxVve8lbgnck/DjkDNcRCAhWVaI/NpkDa odj3hakIt0mS9a8yQb6vvjOLF4f1E2NBHsyxx+bI= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Xin Long , Marcelo Ricardo Leitner , Jakub Kicinski , Sasha Levin Subject: [PATCH 5.10 66/77] sctp: fix the processing for INIT_ACK chunk Date: Mon, 1 Nov 2021 10:17:54 +0100 Message-Id: <20211101082525.458195463@linuxfoundation.org> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211101082511.254155853@linuxfoundation.org> References: <20211101082511.254155853@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Xin Long [ Upstream commit 438b95a7c98f77d51cbf4db021f41b602d750a3f ] Currently INIT_ACK chunk in non-cookie_echoed state is processed in sctp_sf_discard_chunk() to send an abort with the existent asoc's vtag if the chunk length is not valid. But the vtag in the chunk's sctphdr is not verified, which may be exploited by one to cook a malicious chunk to terminal a SCTP asoc. sctp_sf_discard_chunk() also is called in many other places to send an abort, and most of those have this problem. This patch is to fix it by sending abort with the existent asoc's vtag only if the vtag from the chunk's sctphdr is verified in sctp_sf_discard_chunk(). Note on sctp_sf_do_9_1_abort() and sctp_sf_shutdown_pending_abort(), the chunk length has been verified before sctp_sf_discard_chunk(), so replace it with sctp_sf_discard(). On sctp_sf_do_asconf_ack() and sctp_sf_do_asconf(), move the sctp_chunk_length_valid check ahead of sctp_sf_discard_chunk(), then replace it with sctp_sf_discard(). Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Xin Long Acked-by: Marcelo Ricardo Leitner Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/sctp/sm_statefuns.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 89a86728184d..5063f9884367 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -2280,7 +2280,7 @@ enum sctp_disposition sctp_sf_shutdown_pending_abort( */ if (SCTP_ADDR_DEL == sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) - return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands); + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); if (!sctp_err_chunk_valid(chunk)) return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); @@ -2326,7 +2326,7 @@ enum sctp_disposition sctp_sf_shutdown_sent_abort( */ if (SCTP_ADDR_DEL == sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) - return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands); + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); if (!sctp_err_chunk_valid(chunk)) return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); @@ -2596,7 +2596,7 @@ enum sctp_disposition sctp_sf_do_9_1_abort( */ if (SCTP_ADDR_DEL == sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) - return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands); + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); if (!sctp_err_chunk_valid(chunk)) return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); @@ -3745,6 +3745,11 @@ enum sctp_disposition sctp_sf_do_asconf(struct net *net, return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); } + /* Make sure that the ASCONF ADDIP chunk has a valid length. */ + if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_addip_chunk))) + return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, + commands); + /* ADD-IP: Section 4.1.1 * This chunk MUST be sent in an authenticated way by using * the mechanism defined in [I-D.ietf-tsvwg-sctp-auth]. If this chunk @@ -3753,13 +3758,7 @@ enum sctp_disposition sctp_sf_do_asconf(struct net *net, */ if (!asoc->peer.asconf_capable || (!net->sctp.addip_noauth && !chunk->auth)) - return sctp_sf_discard_chunk(net, ep, asoc, type, arg, - commands); - - /* Make sure that the ASCONF ADDIP chunk has a valid length. */ - if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_addip_chunk))) - return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, - commands); + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); hdr = (struct sctp_addiphdr *)chunk->skb->data; serial = ntohl(hdr->serial); @@ -3888,6 +3887,12 @@ enum sctp_disposition sctp_sf_do_asconf_ack(struct net *net, return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); } + /* Make sure that the ADDIP chunk has a valid length. */ + if (!sctp_chunk_length_valid(asconf_ack, + sizeof(struct sctp_addip_chunk))) + return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, + commands); + /* ADD-IP, Section 4.1.2: * This chunk MUST be sent in an authenticated way by using * the mechanism defined in [I-D.ietf-tsvwg-sctp-auth]. If this chunk @@ -3896,14 +3901,7 @@ enum sctp_disposition sctp_sf_do_asconf_ack(struct net *net, */ if (!asoc->peer.asconf_capable || (!net->sctp.addip_noauth && !asconf_ack->auth)) - return sctp_sf_discard_chunk(net, ep, asoc, type, arg, - commands); - - /* Make sure that the ADDIP chunk has a valid length. */ - if (!sctp_chunk_length_valid(asconf_ack, - sizeof(struct sctp_addip_chunk))) - return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, - commands); + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); addip_hdr = (struct sctp_addiphdr *)asconf_ack->skb->data; rcvd_serial = ntohl(addip_hdr->serial); @@ -4475,6 +4473,9 @@ enum sctp_disposition sctp_sf_discard_chunk(struct net *net, { struct sctp_chunk *chunk = arg; + if (asoc && !sctp_vtag_verify(chunk, asoc)) + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); + /* Make sure that the chunk has a valid length. * Since we don't know the chunk type, we use a general * chunkhdr structure to make a comparison. -- 2.33.0