diff options
| author | Siddharth Doshi <sdoshi@mvista.com> | 2024-07-16 21:07:31 +0530 |
|---|---|---|
| committer | Armin Kuster <akuster808@gmail.com> | 2024-07-29 20:07:01 -0400 |
| commit | f0deac37873e0e4c2f7adcdfa6846679743a600f (patch) | |
| tree | c2c13056de67868180078d47e666cd995b409295 | |
| parent | 6880ab150e1d09d7de6763453db95d1a832fbabd (diff) | |
| download | meta-security-f0deac37873e0e4c2f7adcdfa6846679743a600f.tar.gz | |
Suricata: Security Fix for CVE-2024-37151, CVE-2024-38534, CVE-2024-38535, CVE-2024-38536
Upstream-Status: Backport from [https://github.com/OISF/suricata/commit/aab7f35c76721df19403a7c0c0025feae12f3b6b, https://github.com/OISF/suricata/commit/a753cdbe84caee3b66d0bf49b2712d29a50d67ae, https://github.com/OISF/suricata/commit/c82fa5ca0d1ce0bd8f936e0b860707a6571373b2, https://github.com/OISF/suricata/commit/2bd3bd0e318f19008e9fe068ab17277c530ffb92]
CVE's Fixed:
CVE-2024-37151 suricata: suricata: packet reassembly failure, which can lead to policy bypass
CVE-2024-38534 suricata: suricata: Crafted modbus traffic can lead to unlimited resource accumulation within a flow
CVE-2024-38535 suricata: Suricata: can run out of memory when parsing crafted HTTP/2 traffic
CVE-2024-38536 suricata: NULL pointer dereference when http.memcap is reached
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
| -rw-r--r-- | recipes-ids/suricata/files/CVE-2024-37151.patch | 53 | ||||
| -rw-r--r-- | recipes-ids/suricata/files/CVE-2024-38534.patch | 44 | ||||
| -rw-r--r-- | recipes-ids/suricata/files/CVE-2024-38535.patch | 57 | ||||
| -rw-r--r-- | recipes-ids/suricata/files/CVE-2024-38535_pre.patch | 292 | ||||
| -rw-r--r-- | recipes-ids/suricata/files/CVE-2024-38536.patch | 40 | ||||
| -rw-r--r-- | recipes-ids/suricata/suricata_7.0.0.bb | 5 |
6 files changed, 491 insertions, 0 deletions
diff --git a/recipes-ids/suricata/files/CVE-2024-37151.patch b/recipes-ids/suricata/files/CVE-2024-37151.patch new file mode 100644 index 0000000..7e5d8e2 --- /dev/null +++ b/recipes-ids/suricata/files/CVE-2024-37151.patch | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | From a6052dca1e27f3c8f96ec7be0fe7514c56a0d56f Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Victor Julien <vjulien@oisf.net> | ||
| 3 | Date: Tue, 4 Jun 2024 14:43:22 +0200 | ||
| 4 | Subject: [PATCH 1/4] defrag: don't use completed tracker | ||
| 5 | |||
| 6 | When a Tracker is set up for a IPID, frags come in for it and it's | ||
| 7 | reassembled and complete, the `DefragTracker::remove` flag is set. This | ||
| 8 | is mean to tell the hash cleanup code to recyle the tracker and to let | ||
| 9 | the lookup code skip the tracker during lookup. | ||
| 10 | |||
| 11 | A logic error lead to the following scenario: | ||
| 12 | |||
| 13 | 1. there are sufficient frag trackers to make sure the hash table is | ||
| 14 | filled with trackers | ||
| 15 | 2. frags for a Packet with IPID X are processed correctly (X1) | ||
| 16 | 3. frags for a new Packet that also has IPID X come in quickly after the | ||
| 17 | first (X2). | ||
| 18 | 4. during the lookup, the frag for X2 hashes to a hash row that holds | ||
| 19 | more than one tracker | ||
| 20 | 5. as the trackers in hash row are evaluated, it finds the tracker for | ||
| 21 | X1, but since the `remove` bit is not checked, it is returned as the | ||
| 22 | tracker for X2. | ||
| 23 | 6. reassembly fails, as the tracker is already complete | ||
| 24 | |||
| 25 | The logic error is that only for the first tracker in a row the `remove` | ||
| 26 | bit was checked, leading to reuse to a closed tracker if there were more | ||
| 27 | trackers in the hash row. | ||
| 28 | |||
| 29 | Ticket: #7042. | ||
| 30 | |||
| 31 | Upstream-Status: Backport from [https://github.com/OISF/suricata/commit/aab7f35c76721df19403a7c0c0025feae12f3b6b] | ||
| 32 | CVE: CVE-2024-37151 | ||
| 33 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
| 34 | --- | ||
| 35 | src/defrag-hash.c | 2 +- | ||
| 36 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
| 37 | |||
| 38 | diff --git a/src/defrag-hash.c b/src/defrag-hash.c | ||
| 39 | index 2f19ce2..87d40f9 100644 | ||
| 40 | --- a/src/defrag-hash.c | ||
| 41 | +++ b/src/defrag-hash.c | ||
| 42 | @@ -591,7 +591,7 @@ DefragTracker *DefragGetTrackerFromHash (Packet *p) | ||
| 43 | return dt; | ||
| 44 | } | ||
| 45 | |||
| 46 | - if (DefragTrackerCompare(dt, p) != 0) { | ||
| 47 | + if (!dt->remove && DefragTrackerCompare(dt, p) != 0) { | ||
| 48 | /* we found our tracker, lets put it on top of the | ||
| 49 | * hash list -- this rewards active trackers */ | ||
| 50 | if (dt->hnext) { | ||
| 51 | -- | ||
| 52 | 2.44.0 | ||
| 53 | |||
diff --git a/recipes-ids/suricata/files/CVE-2024-38534.patch b/recipes-ids/suricata/files/CVE-2024-38534.patch new file mode 100644 index 0000000..14a958c --- /dev/null +++ b/recipes-ids/suricata/files/CVE-2024-38534.patch | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | From f1645ea911d4e90b1be8ee5863e8e1a665079cce Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Philippe Antoine <pantoine@oisf.net> | ||
| 3 | Date: Thu, 25 Apr 2024 21:24:33 +0200 | ||
| 4 | Subject: [PATCH 2/4] modbus: abort flow parsing on flood | ||
| 5 | |||
| 6 | Ticket: 6987 | ||
| 7 | |||
| 8 | Let's not spend more resources for a flow which is trying to | ||
| 9 | make us do it... | ||
| 10 | |||
| 11 | (cherry picked from commit 37509e8e0ed097f8e0174df754835ac60584fc72) | ||
| 12 | |||
| 13 | Upstream-Status: Backport from [https://github.com/OISF/suricata/commit/a753cdbe84caee3b66d0bf49b2712d29a50d67ae] | ||
| 14 | CVE: CVE-2024-38534 | ||
| 15 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
| 16 | --- | ||
| 17 | rust/src/modbus/modbus.rs | 4 ++-- | ||
| 18 | 1 file changed, 2 insertions(+), 2 deletions(-) | ||
| 19 | |||
| 20 | diff --git a/rust/src/modbus/modbus.rs b/rust/src/modbus/modbus.rs | ||
| 21 | index 246e9ca..d2f7c6b 100644 | ||
| 22 | --- a/rust/src/modbus/modbus.rs | ||
| 23 | +++ b/rust/src/modbus/modbus.rs | ||
| 24 | @@ -189,7 +189,7 @@ impl ModbusState { | ||
| 25 | None => { | ||
| 26 | let mut tx = match self.new_tx() { | ||
| 27 | Some(tx) => tx, | ||
| 28 | - None => return AppLayerResult::ok(), | ||
| 29 | + None => return AppLayerResult::err(), | ||
| 30 | }; | ||
| 31 | tx.set_events_from_flags(&msg.error_flags); | ||
| 32 | tx.request = Some(msg); | ||
| 33 | @@ -215,7 +215,7 @@ impl ModbusState { | ||
| 34 | None => { | ||
| 35 | let mut tx = match self.new_tx() { | ||
| 36 | Some(tx) => tx, | ||
| 37 | - None => return AppLayerResult::ok(), | ||
| 38 | + None => return AppLayerResult::err(), | ||
| 39 | }; | ||
| 40 | if msg | ||
| 41 | .access_type | ||
| 42 | -- | ||
| 43 | 2.44.0 | ||
| 44 | |||
diff --git a/recipes-ids/suricata/files/CVE-2024-38535.patch b/recipes-ids/suricata/files/CVE-2024-38535.patch new file mode 100644 index 0000000..7ac72c8 --- /dev/null +++ b/recipes-ids/suricata/files/CVE-2024-38535.patch | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | From 6b00dc36d7527f051c2346f03d20f8d9e5a60138 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Philippe Antoine <pantoine@oisf.net> | ||
| 3 | Date: Mon, 17 Jun 2024 16:30:49 +0200 | ||
| 4 | Subject: [PATCH 3/4] http2: do not expand duplicate headers | ||
| 5 | |||
| 6 | Ticket: 7104 | ||
| 7 | |||
| 8 | As this can cause a big mamory allocation due to the quadratic | ||
| 9 | nature of the HPACK compression. | ||
| 10 | |||
| 11 | (cherry picked from commit 5bd17934df321b88f502d48afdd6cc8bad4787a7) | ||
| 12 | |||
| 13 | Upstream-Status: Backport from [https://github.com/OISF/suricata/commit/c82fa5ca0d1ce0bd8f936e0b860707a6571373b2] | ||
| 14 | CVE: CVE-2024-38535 | ||
| 15 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
| 16 | --- | ||
| 17 | rust/src/http2/detect.rs | 8 ++++---- | ||
| 18 | 1 file changed, 4 insertions(+), 4 deletions(-) | ||
| 19 | |||
| 20 | diff --git a/rust/src/http2/detect.rs b/rust/src/http2/detect.rs | ||
| 21 | index 99261ad..9c2f8ab 100644 | ||
| 22 | --- a/rust/src/http2/detect.rs | ||
| 23 | +++ b/rust/src/http2/detect.rs | ||
| 24 | @@ -432,11 +432,11 @@ pub fn http2_frames_get_header_value_vec( | ||
| 25 | if found == 0 { | ||
| 26 | vec.extend_from_slice(&block.value); | ||
| 27 | found = 1; | ||
| 28 | - } else if found == 1 { | ||
| 29 | + } else if found == 1 && Rc::strong_count(&block.name) <= 2 { | ||
| 30 | vec.extend_from_slice(&[b',', b' ']); | ||
| 31 | vec.extend_from_slice(&block.value); | ||
| 32 | found = 2; | ||
| 33 | - } else { | ||
| 34 | + } else if Rc::strong_count(&block.name) <= 2 { | ||
| 35 | vec.extend_from_slice(&[b',', b' ']); | ||
| 36 | vec.extend_from_slice(&block.value); | ||
| 37 | } | ||
| 38 | @@ -469,14 +469,14 @@ fn http2_frames_get_header_value<'a>( | ||
| 39 | if found == 0 { | ||
| 40 | single = Ok(&block.value); | ||
| 41 | found = 1; | ||
| 42 | - } else if found == 1 { | ||
| 43 | + } else if found == 1 && Rc::strong_count(&block.name) <= 2 { | ||
| 44 | if let Ok(s) = single { | ||
| 45 | vec.extend_from_slice(s); | ||
| 46 | } | ||
| 47 | vec.extend_from_slice(&[b',', b' ']); | ||
| 48 | vec.extend_from_slice(&block.value); | ||
| 49 | found = 2; | ||
| 50 | - } else { | ||
| 51 | + } else if Rc::strong_count(&block.name) <= 2 { | ||
| 52 | vec.extend_from_slice(&[b',', b' ']); | ||
| 53 | vec.extend_from_slice(&block.value); | ||
| 54 | } | ||
| 55 | -- | ||
| 56 | 2.44.0 | ||
| 57 | |||
diff --git a/recipes-ids/suricata/files/CVE-2024-38535_pre.patch b/recipes-ids/suricata/files/CVE-2024-38535_pre.patch new file mode 100644 index 0000000..2aa42c4 --- /dev/null +++ b/recipes-ids/suricata/files/CVE-2024-38535_pre.patch | |||
| @@ -0,0 +1,292 @@ | |||
| 1 | From 390f09692eb99809c679d3f350c7cc185d163e1a Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Philippe Antoine <pantoine@oisf.net> | ||
| 3 | Date: Wed, 27 Mar 2024 14:33:54 +0100 | ||
| 4 | Subject: [PATCH] http2: use a reference counter for headers | ||
| 5 | |||
| 6 | Ticket: 6892 | ||
| 7 | |||
| 8 | As HTTP hpack header compression allows one single byte to | ||
| 9 | express a previously seen arbitrary-size header block (name+value) | ||
| 10 | we should avoid to copy the vectors data, but just point | ||
| 11 | to the same data, while reamining memory safe, even in the case | ||
| 12 | of later headers eviction from the dybnamic table. | ||
| 13 | |||
| 14 | Rust std solution is Rc, and the use of clone, so long as the | ||
| 15 | data is accessed by only one thread. | ||
| 16 | |||
| 17 | Note: This patch is needed to patch CVE-2024-38535 as it defines Rc. | ||
| 18 | Upstream-Status: Backport from [https://github.com/OISF/suricata/commit/390f09692eb99809c679d3f350c7cc185d163e1a] | ||
| 19 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
| 20 | --- | ||
| 21 | rust/src/http2/detect.rs | 19 +++++++------ | ||
| 22 | rust/src/http2/http2.rs | 2 +- | ||
| 23 | rust/src/http2/parser.rs | 61 +++++++++++++++++++++------------------- | ||
| 24 | 3 files changed, 43 insertions(+), 39 deletions(-) | ||
| 25 | |||
| 26 | diff --git a/rust/src/http2/detect.rs b/rust/src/http2/detect.rs | ||
| 27 | index 9c2f8ab..e068a17 100644 | ||
| 28 | --- a/rust/src/http2/detect.rs | ||
| 29 | +++ b/rust/src/http2/detect.rs | ||
| 30 | @@ -23,6 +23,7 @@ use crate::core::Direction; | ||
| 31 | use crate::detect::uint::{detect_match_uint, DetectUintData}; | ||
| 32 | use std::ffi::CStr; | ||
| 33 | use std::str::FromStr; | ||
| 34 | +use std::rc::Rc; | ||
| 35 | |||
| 36 | fn http2_tx_has_frametype( | ||
| 37 | tx: &mut HTTP2Transaction, direction: Direction, value: u8, | ||
| 38 | @@ -404,7 +405,7 @@ fn http2_frames_get_header_firstvalue<'a>( | ||
| 39 | for frame in frames { | ||
| 40 | if let Some(blocks) = http2_header_blocks(frame) { | ||
| 41 | for block in blocks.iter() { | ||
| 42 | - if block.name == name.as_bytes() { | ||
| 43 | + if block.name.as_ref() == name.as_bytes() { | ||
| 44 | return Ok(&block.value); | ||
| 45 | } | ||
| 46 | } | ||
| 47 | @@ -428,7 +429,7 @@ pub fn http2_frames_get_header_value_vec( | ||
| 48 | for frame in frames { | ||
| 49 | if let Some(blocks) = http2_header_blocks(frame) { | ||
| 50 | for block in blocks.iter() { | ||
| 51 | - if block.name == name.as_bytes() { | ||
| 52 | + if block.name.as_ref() == name.as_bytes() { | ||
| 53 | if found == 0 { | ||
| 54 | vec.extend_from_slice(&block.value); | ||
| 55 | found = 1; | ||
| 56 | @@ -465,7 +466,7 @@ fn http2_frames_get_header_value<'a>( | ||
| 57 | for frame in frames { | ||
| 58 | if let Some(blocks) = http2_header_blocks(frame) { | ||
| 59 | for block in blocks.iter() { | ||
| 60 | - if block.name == name.as_bytes() { | ||
| 61 | + if block.name.as_ref() == name.as_bytes() { | ||
| 62 | if found == 0 { | ||
| 63 | single = Ok(&block.value); | ||
| 64 | found = 1; | ||
| 65 | @@ -905,8 +906,8 @@ fn http2_tx_set_header(state: &mut HTTP2State, name: &[u8], input: &[u8]) { | ||
| 66 | }; | ||
| 67 | let mut blocks = Vec::new(); | ||
| 68 | let b = parser::HTTP2FrameHeaderBlock { | ||
| 69 | - name: name.to_vec(), | ||
| 70 | - value: input.to_vec(), | ||
| 71 | + name: Rc::new(name.to_vec()), | ||
| 72 | + value: Rc::new(input.to_vec()), | ||
| 73 | error: parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess, | ||
| 74 | sizeupdate: 0, | ||
| 75 | }; | ||
| 76 | @@ -1061,15 +1062,15 @@ mod tests { | ||
| 77 | }; | ||
| 78 | let mut blocks = Vec::new(); | ||
| 79 | let b = parser::HTTP2FrameHeaderBlock { | ||
| 80 | - name: "Host".as_bytes().to_vec(), | ||
| 81 | - value: "abc.com".as_bytes().to_vec(), | ||
| 82 | + name: "Host".as_bytes().to_vec().into(), | ||
| 83 | + value: "abc.com".as_bytes().to_vec().into(), | ||
| 84 | error: parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess, | ||
| 85 | sizeupdate: 0, | ||
| 86 | }; | ||
| 87 | blocks.push(b); | ||
| 88 | let b2 = parser::HTTP2FrameHeaderBlock { | ||
| 89 | - name: "Host".as_bytes().to_vec(), | ||
| 90 | - value: "efg.net".as_bytes().to_vec(), | ||
| 91 | + name: "Host".as_bytes().to_vec().into(), | ||
| 92 | + value: "efg.net".as_bytes().to_vec().into(), | ||
| 93 | error: parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess, | ||
| 94 | sizeupdate: 0, | ||
| 95 | }; | ||
| 96 | diff --git a/rust/src/http2/http2.rs b/rust/src/http2/http2.rs | ||
| 97 | index 326030f..d14ca06 100644 | ||
| 98 | --- a/rust/src/http2/http2.rs | ||
| 99 | +++ b/rust/src/http2/http2.rs | ||
| 100 | @@ -204,7 +204,7 @@ impl HTTP2Transaction { | ||
| 101 | |||
| 102 | fn handle_headers(&mut self, blocks: &[parser::HTTP2FrameHeaderBlock], dir: Direction) { | ||
| 103 | for block in blocks { | ||
| 104 | - if block.name == b"content-encoding" { | ||
| 105 | + if block.name.as_ref() == b"content-encoding" { | ||
| 106 | self.decoder.http2_encoding_fromvec(&block.value, dir); | ||
| 107 | } | ||
| 108 | } | ||
| 109 | diff --git a/rust/src/http2/parser.rs b/rust/src/http2/parser.rs | ||
| 110 | index adabeb2..1a46437 100644 | ||
| 111 | --- a/rust/src/http2/parser.rs | ||
| 112 | +++ b/rust/src/http2/parser.rs | ||
| 113 | @@ -30,6 +30,7 @@ use nom7::sequence::tuple; | ||
| 114 | use nom7::{Err, IResult}; | ||
| 115 | use std::fmt; | ||
| 116 | use std::str::FromStr; | ||
| 117 | +use std::rc::Rc; | ||
| 118 | |||
| 119 | #[repr(u8)] | ||
| 120 | #[derive(Clone, Copy, PartialEq, Eq, FromPrimitive, Debug)] | ||
| 121 | @@ -295,8 +296,8 @@ fn http2_frame_header_static(n: u64, dyn_headers: &HTTP2DynTable) -> Option<HTTP | ||
| 122 | }; | ||
| 123 | if !name.is_empty() { | ||
| 124 | return Some(HTTP2FrameHeaderBlock { | ||
| 125 | - name: name.as_bytes().to_vec(), | ||
| 126 | - value: value.as_bytes().to_vec(), | ||
| 127 | + name: Rc::new(name.as_bytes().to_vec()), | ||
| 128 | + value: Rc::new(value.as_bytes().to_vec()), | ||
| 129 | error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess, | ||
| 130 | sizeupdate: 0, | ||
| 131 | }); | ||
| 132 | @@ -304,23 +305,23 @@ fn http2_frame_header_static(n: u64, dyn_headers: &HTTP2DynTable) -> Option<HTTP | ||
| 133 | //use dynamic table | ||
| 134 | if n == 0 { | ||
| 135 | return Some(HTTP2FrameHeaderBlock { | ||
| 136 | - name: Vec::new(), | ||
| 137 | - value: Vec::new(), | ||
| 138 | + name: Rc::new(Vec::new()), | ||
| 139 | + value: Rc::new(Vec::new()), | ||
| 140 | error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeIndex0, | ||
| 141 | sizeupdate: 0, | ||
| 142 | }); | ||
| 143 | } else if dyn_headers.table.len() + HTTP2_STATIC_HEADERS_NUMBER < n as usize { | ||
| 144 | return Some(HTTP2FrameHeaderBlock { | ||
| 145 | - name: Vec::new(), | ||
| 146 | - value: Vec::new(), | ||
| 147 | + name: Rc::new(Vec::new()), | ||
| 148 | + value: Rc::new(Vec::new()), | ||
| 149 | error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeNotIndexed, | ||
| 150 | sizeupdate: 0, | ||
| 151 | }); | ||
| 152 | } else { | ||
| 153 | let indyn = dyn_headers.table.len() - (n as usize - HTTP2_STATIC_HEADERS_NUMBER); | ||
| 154 | let headcopy = HTTP2FrameHeaderBlock { | ||
| 155 | - name: dyn_headers.table[indyn].name.to_vec(), | ||
| 156 | - value: dyn_headers.table[indyn].value.to_vec(), | ||
| 157 | + name: dyn_headers.table[indyn].name.clone(), | ||
| 158 | + value: dyn_headers.table[indyn].value.clone(), | ||
| 159 | error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess, | ||
| 160 | sizeupdate: 0, | ||
| 161 | }; | ||
| 162 | @@ -348,8 +349,10 @@ impl fmt::Display for HTTP2HeaderDecodeStatus { | ||
| 163 | |||
| 164 | #[derive(Clone, Debug)] | ||
| 165 | pub struct HTTP2FrameHeaderBlock { | ||
| 166 | - pub name: Vec<u8>, | ||
| 167 | - pub value: Vec<u8>, | ||
| 168 | + // Use Rc reference counted so that indexed headers do not get copied. | ||
| 169 | + // Otherwise, this leads to quadratic complexity in memory occupation. | ||
| 170 | + pub name: Rc<Vec<u8>>, | ||
| 171 | + pub value: Rc<Vec<u8>>, | ||
| 172 | pub error: HTTP2HeaderDecodeStatus, | ||
| 173 | pub sizeupdate: u64, | ||
| 174 | } | ||
| 175 | @@ -391,7 +394,7 @@ fn http2_parse_headers_block_literal_common<'a>( | ||
| 176 | ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> { | ||
| 177 | let (i3, name, error) = if index == 0 { | ||
| 178 | match http2_parse_headers_block_string(input) { | ||
| 179 | - Ok((r, n)) => Ok((r, n, HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess)), | ||
| 180 | + Ok((r, n)) => Ok((r, Rc::new(n), HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess)), | ||
| 181 | Err(e) => Err(e), | ||
| 182 | } | ||
| 183 | } else { | ||
| 184 | @@ -403,7 +406,7 @@ fn http2_parse_headers_block_literal_common<'a>( | ||
| 185 | )), | ||
| 186 | None => Ok(( | ||
| 187 | input, | ||
| 188 | - Vec::new(), | ||
| 189 | + Rc::new(Vec::new()), | ||
| 190 | HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeNotIndexed, | ||
| 191 | )), | ||
| 192 | } | ||
| 193 | @@ -413,7 +416,7 @@ fn http2_parse_headers_block_literal_common<'a>( | ||
| 194 | i4, | ||
| 195 | HTTP2FrameHeaderBlock { | ||
| 196 | name, | ||
| 197 | - value, | ||
| 198 | + value: Rc::new(value), | ||
| 199 | error, | ||
| 200 | sizeupdate: 0, | ||
| 201 | }, | ||
| 202 | @@ -435,8 +438,8 @@ fn http2_parse_headers_block_literal_incindex<'a>( | ||
| 203 | match r { | ||
| 204 | Ok((r, head)) => { | ||
| 205 | let headcopy = HTTP2FrameHeaderBlock { | ||
| 206 | - name: head.name.to_vec(), | ||
| 207 | - value: head.value.to_vec(), | ||
| 208 | + name: head.name.clone(), | ||
| 209 | + value: head.value.clone(), | ||
| 210 | error: head.error, | ||
| 211 | sizeupdate: 0, | ||
| 212 | }; | ||
| 213 | @@ -556,8 +559,8 @@ fn http2_parse_headers_block_dynamic_size<'a>( | ||
| 214 | return Ok(( | ||
| 215 | i3, | ||
| 216 | HTTP2FrameHeaderBlock { | ||
| 217 | - name: Vec::new(), | ||
| 218 | - value: Vec::new(), | ||
| 219 | + name: Rc::new(Vec::new()), | ||
| 220 | + value: Rc::new(Vec::new()), | ||
| 221 | error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate, | ||
| 222 | sizeupdate: maxsize2, | ||
| 223 | }, | ||
| 224 | @@ -614,8 +617,8 @@ fn http2_parse_headers_blocks<'a>( | ||
| 225 | // if we error from http2_parse_var_uint, we keep the first parsed headers | ||
| 226 | if err.code == ErrorKind::LengthValue { | ||
| 227 | blocks.push(HTTP2FrameHeaderBlock { | ||
| 228 | - name: Vec::new(), | ||
| 229 | - value: Vec::new(), | ||
| 230 | + name: Rc::new(Vec::new()), | ||
| 231 | + value: Rc::new(Vec::new()), | ||
| 232 | error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeIntegerOverflow, | ||
| 233 | sizeupdate: 0, | ||
| 234 | }); | ||
| 235 | @@ -765,8 +768,8 @@ mod tests { | ||
| 236 | match r0 { | ||
| 237 | Ok((remainder, hd)) => { | ||
| 238 | // Check the first message. | ||
| 239 | - assert_eq!(hd.name, ":method".as_bytes().to_vec()); | ||
| 240 | - assert_eq!(hd.value, "GET".as_bytes().to_vec()); | ||
| 241 | + assert_eq!(hd.name, ":method".as_bytes().to_vec().into()); | ||
| 242 | + assert_eq!(hd.value, "GET".as_bytes().to_vec().into()); | ||
| 243 | // And we should have no bytes left. | ||
| 244 | assert_eq!(remainder.len(), 0); | ||
| 245 | } | ||
| 246 | @@ -782,8 +785,8 @@ mod tests { | ||
| 247 | match r1 { | ||
| 248 | Ok((remainder, hd)) => { | ||
| 249 | // Check the first message. | ||
| 250 | - assert_eq!(hd.name, "accept".as_bytes().to_vec()); | ||
| 251 | - assert_eq!(hd.value, "*/*".as_bytes().to_vec()); | ||
| 252 | + assert_eq!(hd.name, "accept".as_bytes().to_vec().into()); | ||
| 253 | + assert_eq!(hd.value, "*/*".as_bytes().to_vec().into()); | ||
| 254 | // And we should have no bytes left. | ||
| 255 | assert_eq!(remainder.len(), 0); | ||
| 256 | assert_eq!(dynh.table.len(), 1); | ||
| 257 | @@ -802,8 +805,8 @@ mod tests { | ||
| 258 | match result { | ||
| 259 | Ok((remainder, hd)) => { | ||
| 260 | // Check the first message. | ||
| 261 | - assert_eq!(hd.name, ":authority".as_bytes().to_vec()); | ||
| 262 | - assert_eq!(hd.value, "localhost:3000".as_bytes().to_vec()); | ||
| 263 | + assert_eq!(hd.name, ":authority".as_bytes().to_vec().into()); | ||
| 264 | + assert_eq!(hd.value, "localhost:3000".as_bytes().to_vec().into()); | ||
| 265 | // And we should have no bytes left. | ||
| 266 | assert_eq!(remainder.len(), 0); | ||
| 267 | assert_eq!(dynh.table.len(), 2); | ||
| 268 | @@ -820,8 +823,8 @@ mod tests { | ||
| 269 | match r3 { | ||
| 270 | Ok((remainder, hd)) => { | ||
| 271 | // same as before | ||
| 272 | - assert_eq!(hd.name, ":authority".as_bytes().to_vec()); | ||
| 273 | - assert_eq!(hd.value, "localhost:3000".as_bytes().to_vec()); | ||
| 274 | + assert_eq!(hd.name, ":authority".as_bytes().to_vec().into()); | ||
| 275 | + assert_eq!(hd.value, "localhost:3000".as_bytes().to_vec().into()); | ||
| 276 | // And we should have no bytes left. | ||
| 277 | assert_eq!(remainder.len(), 0); | ||
| 278 | assert_eq!(dynh.table.len(), 2); | ||
| 279 | @@ -856,8 +859,8 @@ mod tests { | ||
| 280 | match r2 { | ||
| 281 | Ok((remainder, hd)) => { | ||
| 282 | // Check the first message. | ||
| 283 | - assert_eq!(hd.name, ":path".as_bytes().to_vec()); | ||
| 284 | - assert_eq!(hd.value, "/doc/manual/html/index.html".as_bytes().to_vec()); | ||
| 285 | + assert_eq!(hd.name, ":path".as_bytes().to_vec().into()); | ||
| 286 | + assert_eq!(hd.value, "/doc/manual/html/index.html".as_bytes().to_vec().into()); | ||
| 287 | // And we should have no bytes left. | ||
| 288 | assert_eq!(remainder.len(), 0); | ||
| 289 | assert_eq!(dynh.table.len(), 2); | ||
| 290 | -- | ||
| 291 | 2.44.0 | ||
| 292 | |||
diff --git a/recipes-ids/suricata/files/CVE-2024-38536.patch b/recipes-ids/suricata/files/CVE-2024-38536.patch new file mode 100644 index 0000000..2d4b3d7 --- /dev/null +++ b/recipes-ids/suricata/files/CVE-2024-38536.patch | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | From 4026bca7f04c419dd3f3ba17a1af17bbcbcf18bc Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Philippe Antoine <pantoine@oisf.net> | ||
| 3 | Date: Fri, 17 May 2024 09:39:52 +0200 | ||
| 4 | Subject: [PATCH 4/4] http: fix nul deref on memcap reached | ||
| 5 | |||
| 6 | HttpRangeOpenFileAux may return NULL in different cases, including | ||
| 7 | when memcap is reached. | ||
| 8 | But is only caller did not check it before calling HttpRangeAppendData | ||
| 9 | which would dereference the NULL value. | ||
| 10 | |||
| 11 | Ticket: 7029 | ||
| 12 | (cherry picked from commit fd262df457f67f2174752dd6505ba2ed5911fd96) | ||
| 13 | |||
| 14 | Upstream-Status: Backport from [https://github.com/OISF/suricata/commit/2bd3bd0e318f19008e9fe068ab17277c530ffb92] | ||
| 15 | CVE: CVE-2024-38536 | ||
| 16 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
| 17 | --- | ||
| 18 | src/app-layer-htp-range.c | 6 ++++-- | ||
| 19 | 1 file changed, 4 insertions(+), 2 deletions(-) | ||
| 20 | |||
| 21 | diff --git a/src/app-layer-htp-range.c b/src/app-layer-htp-range.c | ||
| 22 | index 3cdde35..f0d75a9 100644 | ||
| 23 | --- a/src/app-layer-htp-range.c | ||
| 24 | +++ b/src/app-layer-htp-range.c | ||
| 25 | @@ -351,8 +351,10 @@ static HttpRangeContainerBlock *HttpRangeOpenFile(HttpRangeContainerFile *c, uin | ||
| 26 | { | ||
| 27 | HttpRangeContainerBlock *r = | ||
| 28 | HttpRangeOpenFileAux(c, start, end, total, sbcfg, name, name_len, flags); | ||
| 29 | - if (HttpRangeAppendData(sbcfg, r, data, len) < 0) { | ||
| 30 | - SCLogDebug("Failed to append data while opening"); | ||
| 31 | + if (r) { | ||
| 32 | + if (HttpRangeAppendData(sbcfg, r, data, len) < 0) { | ||
| 33 | + SCLogDebug("Failed to append data while opening"); | ||
| 34 | + } | ||
| 35 | } | ||
| 36 | return r; | ||
| 37 | } | ||
| 38 | -- | ||
| 39 | 2.44.0 | ||
| 40 | |||
diff --git a/recipes-ids/suricata/suricata_7.0.0.bb b/recipes-ids/suricata/suricata_7.0.0.bb index 21d4306..1f3b694 100644 --- a/recipes-ids/suricata/suricata_7.0.0.bb +++ b/recipes-ids/suricata/suricata_7.0.0.bb | |||
| @@ -16,6 +16,11 @@ SRC_URI += " \ | |||
| 16 | file://suricata.service \ | 16 | file://suricata.service \ |
| 17 | file://run-ptest \ | 17 | file://run-ptest \ |
| 18 | file://fixup.patch \ | 18 | file://fixup.patch \ |
| 19 | file://CVE-2024-37151.patch \ | ||
| 20 | file://CVE-2024-38534.patch \ | ||
| 21 | file://CVE-2024-38535_pre.patch \ | ||
| 22 | file://CVE-2024-38535.patch \ | ||
| 23 | file://CVE-2024-38536.patch \ | ||
| 19 | " | 24 | " |
| 20 | 25 | ||
| 21 | inherit autotools pkgconfig python3native systemd ptest cargo cargo-update-recipe-crates | 26 | inherit autotools pkgconfig python3native systemd ptest cargo cargo-update-recipe-crates |
