You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
suricata/src/decode-sctp.c

88 lines
2.0 KiB
C

/* Copyright (C) 2011-2021 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* \ingroup decode
*
* @{
*/
/**
* \file
*
* \author Eric Leblond <eric@regit.org>
*
* Decode SCTP
*/
#include "suricata-common.h"
#include "decode.h"
#include "decode-sctp.h"
#include "decode-events.h"
#include "util-validate.h"
#include "util-unittest.h"
#include "util-debug.h"
#include "util-optimize.h"
#include "flow.h"
static int DecodeSCTPPacket(ThreadVars *tv, Packet *p, const uint8_t *pkt, uint16_t len)
{
DEBUG_VALIDATE_BUG_ON(pkt == NULL);
if (unlikely(len < SCTP_HEADER_LEN)) {
ENGINE_SET_INVALID_EVENT(p, SCTP_PKT_TOO_SMALL);
return -1;
}
p->sctph = (SCTPHdr *)pkt;
SET_SCTP_SRC_PORT(p,&p->sp);
SET_SCTP_DST_PORT(p,&p->dp);
p->payload = (uint8_t *)pkt + sizeof(SCTPHdr);
p->payload_len = len - sizeof(SCTPHdr);
p->proto = IPPROTO_SCTP;
return 0;
}
int DecodeSCTP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
const uint8_t *pkt, uint16_t len)
{
StatsIncr(tv, dtv->counter_sctp);
if (unlikely(DecodeSCTPPacket(tv, p,pkt,len) < 0)) {
decode: cleanup packet properly on bad packets In case of bad IPv4, TCP or UDP, the per packet ip4vars/tcpvars/udpvar structures would not be cleaned up because the cleanup depends on the 'header' pointer being set, but the error handling would unset that. This could mean these structures were already filled with values before the error was detected. As packets were recycled, the next packet decoding would use this unclean structure. To make things worse these structures are part of unions. IPv4/IPv6 and TCP/ICMPv4/ICMPv6 share the same memory location. LibFuzzer+UBSAN found this both locally and in Oss-Fuzz: decode-ipv6.c:654:9: runtime error: load of value 6, which is not a valid value for type 'bool' #0 0x6146f0 in DecodeIPV6 /src/suricata/src/decode-ipv6.c:654:9 #1 0x617e96 in DecodeNull /src/suricata/src/decode-null.c:70:13 #2 0x9dd8a4 in DecodePcapFile /src/suricata/src/source-pcap-file.c:412:9 #3 0x4c8ed2 in LLVMFuzzerTestOneInput /src/suricata/src/tests/fuzz/fuzz_sigpcap.c:158:25 #4 0x457e51 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:556:15 #5 0x457575 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:470:3 #6 0x459917 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:698:19 #7 0x45a6a5 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:830:5 #8 0x448728 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:824:6 #9 0x472552 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:19:10 #10 0x7ff0d097b82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) #11 0x41bde8 in _start (/out/fuzz_sigpcap+0x41bde8) Bug: #3496
6 years ago
CLEAR_SCTP_PACKET(p);
return TM_ECODE_FAILED;
}
#ifdef DEBUG
SCLogDebug("SCTP sp: %" PRIu32 " -> dp: %" PRIu32,
SCTP_GET_SRC_PORT(p), SCTP_GET_DST_PORT(p));
#endif
FlowSetupPacket(p);
return TM_ECODE_OK;
}
/**
* @}
*/