mirror of
https://github.com/OISF/suricata.git
synced 2026-10-11 22:09:53 +00:00
http2: respect max-table-size in headers size update
Ticket: 8755 The config parameter was only taken into account from the settings frame HEADER_TABLE_SIZE Emits an event http2.header_table_overflow when we have the first header that we cannot keep in Suricata's memory due to the configured limit.
This commit is contained in:
committed by
Victor Julien
parent
1197bd175b
commit
521deb07d6
@@ -27,3 +27,4 @@ alert http2 any any -> any any (msg:"SURICATA HTTP2 data on stream zero"; flow:e
|
||||
# disabled by default, as it can happen in legit cases depending on the max-frames config value
|
||||
# alert http2 any any -> any any (msg:"SURICATA HTTP2 too many frames"; flow:established; app-layer-event:http2.too_many_frames; classtype:protocol-command-decode; sid:2290019; rev:1;)
|
||||
alert http2 any any -> any any (msg:"SURICATA HTTP2 compression bomb"; flow:established; app-layer-event:http2.compression_bomb; classtype:protocol-command-decode; sid:2290020; rev:1;)
|
||||
alert http2 any any -> any any (msg:"SURICATA HTTP2 headers table overflow"; flow:established; app-layer-event:http2.header_table_overflow; classtype:protocol-command-decode; sid:2290021; rev:1;)
|
||||
|
||||
+10
-14
@@ -677,6 +677,7 @@ pub enum HTTP2Event {
|
||||
FailedDecompression,
|
||||
InvalidRange,
|
||||
HeaderIntegerOverflow,
|
||||
HeaderTableOverflow,
|
||||
TooManyStreams,
|
||||
AuthorityHostMismatch,
|
||||
UserinfoInUri,
|
||||
@@ -981,29 +982,24 @@ impl HTTP2State {
|
||||
&mut self, blocks: &Vec<parser::HTTP2FrameHeaderBlock>, dir: Direction,
|
||||
) -> Vec<HTTP2Event> {
|
||||
let mut events = Vec::new();
|
||||
let (mut update, mut sizeup) = (false, 0);
|
||||
for block in blocks {
|
||||
if block.error >= parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeError {
|
||||
events.push(HTTP2Event::InvalidHeader);
|
||||
} else if block.error == parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate {
|
||||
update = true;
|
||||
if block.sizeupdate > sizeup {
|
||||
sizeup = block.sizeupdate;
|
||||
}
|
||||
} else if block.error
|
||||
== parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeIntegerOverflow
|
||||
{
|
||||
events.push(HTTP2Event::HeaderIntegerOverflow);
|
||||
}
|
||||
}
|
||||
if update {
|
||||
//borrow checker forbids to pass directly dyn_headers
|
||||
let dyn_headers = if dir == Direction::ToClient {
|
||||
&mut self.dynamic_headers_tc
|
||||
} else {
|
||||
&mut self.dynamic_headers_ts
|
||||
};
|
||||
dyn_headers.max_size = sizeup as usize;
|
||||
let dyn_headers = if dir == Direction::ToClient {
|
||||
&mut self.dynamic_headers_tc
|
||||
} else {
|
||||
&mut self.dynamic_headers_ts
|
||||
};
|
||||
if dyn_headers.overflow == 2 {
|
||||
// event only once
|
||||
dyn_headers.overflow = 3;
|
||||
events.push(HTTP2Event::HeaderTableOverflow);
|
||||
}
|
||||
return events;
|
||||
}
|
||||
|
||||
@@ -401,8 +401,8 @@ fn http2_parse_headers_block_literal_incindex<'a>(
|
||||
if dyn_headers.current_size <= (unsafe { HTTP2_MAX_TABLESIZE } as usize) {
|
||||
//overflow had not yet happened
|
||||
dyn_headers.table.push(headcopy);
|
||||
} else if dyn_headers.current_size > dyn_headers.max_size {
|
||||
//overflow happens, we cannot replace evicted headers
|
||||
} else {
|
||||
//overflow happens, we cannot record new headers
|
||||
dyn_headers.overflow = 2;
|
||||
}
|
||||
}
|
||||
@@ -506,7 +506,14 @@ fn http2_parse_headers_block_dynamic_size<'a>(
|
||||
toremove += 1;
|
||||
}
|
||||
dyn_headers.table.drain(0..toremove);
|
||||
if maxsize2 <= unsafe { HTTP2_MAX_TABLESIZE.into() } {
|
||||
dyn_headers.overflow = 0;
|
||||
}
|
||||
} else if maxsize2 > unsafe { HTTP2_MAX_TABLESIZE.into() } {
|
||||
//mark potential overflow
|
||||
dyn_headers.overflow = 1;
|
||||
}
|
||||
dyn_headers.max_size = maxsize2 as usize;
|
||||
return Ok((
|
||||
i3,
|
||||
HTTP2FrameHeaderBlock {
|
||||
|
||||
Reference in New Issue
Block a user