From 37a9003736413b0bc9704099e189fd402922df43 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Tue, 7 May 2024 16:33:00 +0200 Subject: [PATCH] rust/probing: safety check for null input Ticket: 7013 Done consistently for all protocols This may change some protocols behaviors which failed early if they found there was not enough data... --- rust/src/dcerpc/dcerpc.rs | 2 +- rust/src/dcerpc/dcerpc_udp.rs | 2 +- rust/src/dhcp/dhcp.rs | 2 +- rust/src/dns/dns.rs | 4 ++-- rust/src/krb/krb5.rs | 6 ++++++ rust/src/modbus/modbus.rs | 3 +++ rust/src/mqtt/mqtt.rs | 3 +++ rust/src/nfs/nfs.rs | 12 ++++++++++++ rust/src/ntp/ntp.rs | 3 +++ rust/src/quic/quic.rs | 3 +++ rust/src/smb/smb.rs | 4 ++-- rust/src/snmp/snmp.rs | 3 +++ 12 files changed, 40 insertions(+), 7 deletions(-) diff --git a/rust/src/dcerpc/dcerpc.rs b/rust/src/dcerpc/dcerpc.rs index 759d5c2634..3a1af7df53 100644 --- a/rust/src/dcerpc/dcerpc.rs +++ b/rust/src/dcerpc/dcerpc.rs @@ -1293,7 +1293,7 @@ pub unsafe extern "C" fn rs_dcerpc_probe_tcp(_f: *const core::Flow, direction: u len: u32, rdir: *mut u8) -> AppProto { SCLogDebug!("Probing packet for DCERPC"); - if len == 0 { + if len == 0 || input.is_null() { return core::ALPROTO_UNKNOWN; } let slice: &[u8] = std::slice::from_raw_parts(input as *mut u8, len as usize); diff --git a/rust/src/dcerpc/dcerpc_udp.rs b/rust/src/dcerpc/dcerpc_udp.rs index b17cc8d1fa..2007c867bf 100644 --- a/rust/src/dcerpc/dcerpc_udp.rs +++ b/rust/src/dcerpc/dcerpc_udp.rs @@ -310,7 +310,7 @@ pub unsafe extern "C" fn rs_dcerpc_probe_udp(_f: *const core::Flow, direction: u len: u32, rdir: *mut u8) -> core::AppProto { SCLogDebug!("Probing the packet for DCERPC/UDP"); - if len == 0 { + if len == 0 || input.is_null() { return core::ALPROTO_UNKNOWN; } let slice: &[u8] = std::slice::from_raw_parts(input as *mut u8, len as usize); diff --git a/rust/src/dhcp/dhcp.rs b/rust/src/dhcp/dhcp.rs index b69b675b8c..7f0da5526e 100644 --- a/rust/src/dhcp/dhcp.rs +++ b/rust/src/dhcp/dhcp.rs @@ -184,7 +184,7 @@ pub unsafe extern "C" fn rs_dhcp_probing_parser(_flow: *const Flow, input_len: u32, _rdir: *mut u8) -> AppProto { - if input_len < DHCP_MIN_FRAME_LEN { + if input_len < DHCP_MIN_FRAME_LEN || input.is_null() { return ALPROTO_UNKNOWN; } diff --git a/rust/src/dns/dns.rs b/rust/src/dns/dns.rs index 587054dab6..045adbe218 100644 --- a/rust/src/dns/dns.rs +++ b/rust/src/dns/dns.rs @@ -896,7 +896,7 @@ pub extern "C" fn SCDnsTxGetResponseFlags(tx: &mut DNSTransaction) -> u16 { unsafe extern "C" fn probe_udp( _flow: *const core::Flow, _dir: u8, input: *const u8, len: u32, rdir: *mut u8, ) -> AppProto { - if len == 0 || len < std::mem::size_of::() as u32 { + if input.is_null() || len < std::mem::size_of::() as u32 { return core::ALPROTO_UNKNOWN; } let slice: &[u8] = std::slice::from_raw_parts(input as *mut u8, len as usize); @@ -916,7 +916,7 @@ unsafe extern "C" fn probe_udp( unsafe extern "C" fn c_probe_tcp( _flow: *const core::Flow, direction: u8, input: *const u8, len: u32, rdir: *mut u8, ) -> AppProto { - if len == 0 || len < std::mem::size_of::() as u32 + 2 { + if input.is_null() || len < std::mem::size_of::() as u32 + 2 { return core::ALPROTO_UNKNOWN; } let slice: &[u8] = std::slice::from_raw_parts(input as *mut u8, len as usize); diff --git a/rust/src/krb/krb5.rs b/rust/src/krb/krb5.rs index ddcca94b29..aceeb86d2b 100644 --- a/rust/src/krb/krb5.rs +++ b/rust/src/krb/krb5.rs @@ -364,6 +364,9 @@ pub unsafe extern "C" fn rs_krb5_probing_parser(_flow: *const Flow, input:*const u8, input_len: u32, _rdir: *mut u8) -> AppProto { + if input.is_null() { + return ALPROTO_UNKNOWN; + } let slice = build_slice!(input,input_len as usize); let alproto = ALPROTO_KRB5; if slice.len() <= 10 { return ALPROTO_FAILED; } @@ -403,6 +406,9 @@ pub unsafe extern "C" fn rs_krb5_probing_parser_tcp(_flow: *const Flow, input:*const u8, input_len: u32, rdir: *mut u8) -> AppProto { + if input.is_null() { + return ALPROTO_UNKNOWN; + } let slice = build_slice!(input,input_len as usize); if slice.len() <= 14 { return ALPROTO_FAILED; } match be_u32(slice) as IResult<&[u8],u32> { diff --git a/rust/src/modbus/modbus.rs b/rust/src/modbus/modbus.rs index 1c0ecc884d..18e98089b2 100644 --- a/rust/src/modbus/modbus.rs +++ b/rust/src/modbus/modbus.rs @@ -274,6 +274,9 @@ impl ModbusState { pub extern "C" fn rs_modbus_probe( _flow: *const core::Flow, _direction: u8, input: *const u8, len: u32, _rdir: *mut u8, ) -> AppProto { + if input.is_null() { + return ALPROTO_UNKNOWN; + } let slice: &[u8] = unsafe { std::slice::from_raw_parts(input as *mut u8, len as usize) }; match MODBUS_PARSER.probe(slice, Direction::Unknown) { Status::Recognized => unsafe { ALPROTO_MODBUS }, diff --git a/rust/src/mqtt/mqtt.rs b/rust/src/mqtt/mqtt.rs index 66067eb6fa..dace75c8ec 100644 --- a/rust/src/mqtt/mqtt.rs +++ b/rust/src/mqtt/mqtt.rs @@ -619,6 +619,9 @@ impl MQTTState { pub unsafe extern "C" fn rs_mqtt_probing_parser( _flow: *const Flow, _direction: u8, input: *const u8, input_len: u32, _rdir: *mut u8, ) -> AppProto { + if input.is_null() { + return ALPROTO_UNKNOWN; + } let buf = build_slice!(input, input_len as usize); match parse_fixed_header(buf) { Ok((_, hdr)) => { diff --git a/rust/src/nfs/nfs.rs b/rust/src/nfs/nfs.rs index 98fb56b7e4..cb07ef6303 100644 --- a/rust/src/nfs/nfs.rs +++ b/rust/src/nfs/nfs.rs @@ -1861,6 +1861,9 @@ pub unsafe extern "C" fn rs_nfs_probe_ms( direction: u8, input: *const u8, len: u32, rdir: *mut u8) -> AppProto { + if input.is_null() { + return ALPROTO_UNKNOWN; + } let slice: &[u8] = build_slice!(input, len as usize); SCLogDebug!("rs_nfs_probe_ms: probing direction {:02x}", direction); let mut adirection : u8 = 0; @@ -1900,6 +1903,9 @@ pub unsafe extern "C" fn rs_nfs_probe(_f: *const Flow, _rdir: *mut u8) -> AppProto { + if input.is_null() { + return ALPROTO_UNKNOWN; + } let slice: &[u8] = build_slice!(input, len as usize); SCLogDebug!("rs_nfs_probe: running probe"); match nfs_probe(slice, direction.into()) { @@ -1918,6 +1924,9 @@ pub unsafe extern "C" fn rs_nfs_probe_udp_ts(_f: *const Flow, _rdir: *mut u8) -> AppProto { + if input.is_null() { + return ALPROTO_UNKNOWN; + } let slice: &[u8] = build_slice!(input, len as usize); match nfs_probe_udp(slice, Direction::ToServer) { 1 => { ALPROTO_NFS }, @@ -1935,6 +1944,9 @@ pub unsafe extern "C" fn rs_nfs_probe_udp_tc(_f: *const Flow, _rdir: *mut u8) -> AppProto { + if input.is_null() { + return ALPROTO_UNKNOWN; + } let slice: &[u8] = build_slice!(input, len as usize); match nfs_probe_udp(slice, Direction::ToClient) { 1 => { ALPROTO_NFS }, diff --git a/rust/src/ntp/ntp.rs b/rust/src/ntp/ntp.rs index c7b3b3d018..3a06cfb8b1 100644 --- a/rust/src/ntp/ntp.rs +++ b/rust/src/ntp/ntp.rs @@ -245,6 +245,9 @@ pub extern "C" fn ntp_probing_parser(_flow: *const Flow, input:*const u8, input_len: u32, _rdir: *mut u8) -> AppProto { + if input.is_null() { + return ALPROTO_UNKNOWN; + } let slice: &[u8] = unsafe { std::slice::from_raw_parts(input as *mut u8, input_len as usize) }; let alproto = unsafe{ ALPROTO_NTP }; match parse_ntp(slice) { diff --git a/rust/src/quic/quic.rs b/rust/src/quic/quic.rs index 473a7df427..330b0f8d37 100644 --- a/rust/src/quic/quic.rs +++ b/rust/src/quic/quic.rs @@ -376,6 +376,9 @@ pub unsafe extern "C" fn rs_quic_state_tx_free(state: *mut std::os::raw::c_void, pub unsafe extern "C" fn rs_quic_probing_parser( _flow: *const Flow, _direction: u8, input: *const u8, input_len: u32, _rdir: *mut u8, ) -> AppProto { + if input.is_null() { + return ALPROTO_UNKNOWN; + } let slice = build_slice!(input, input_len as usize); if QuicHeader::from_bytes(slice, DEFAULT_DCID_LEN).is_ok() { diff --git a/rust/src/smb/smb.rs b/rust/src/smb/smb.rs index fbbb636e89..56e1685e30 100644 --- a/rust/src/smb/smb.rs +++ b/rust/src/smb/smb.rs @@ -2115,7 +2115,7 @@ pub unsafe extern "C" fn rs_smb_probe_begins_tcp(_f: *const Flow, flags: u8, input: *const u8, len: u32, rdir: *mut u8) -> AppProto { - if len < MIN_REC_SIZE as u32 { + if len < MIN_REC_SIZE as u32 || input.is_null() { return ALPROTO_UNKNOWN; } let slice = build_slice!(input, len as usize); @@ -2129,7 +2129,7 @@ pub unsafe extern "C" fn rs_smb_probe_tcp(_f: *const Flow, flags: u8, input: *const u8, len: u32, rdir: *mut u8) -> AppProto { - if len < MIN_REC_SIZE as u32 { + if len < MIN_REC_SIZE as u32 || input.is_null() { return ALPROTO_UNKNOWN; } let slice = build_slice!(input, len as usize); diff --git a/rust/src/snmp/snmp.rs b/rust/src/snmp/snmp.rs index 3b78b47f7a..3e68f70b08 100644 --- a/rust/src/snmp/snmp.rs +++ b/rust/src/snmp/snmp.rs @@ -357,6 +357,9 @@ pub unsafe extern "C" fn rs_snmp_probing_parser(_flow: *const Flow, input:*const u8, input_len: u32, _rdir: *mut u8) -> AppProto { + if input.is_null() { + return ALPROTO_UNKNOWN; + } let slice = build_slice!(input,input_len as usize); let alproto = ALPROTO_SNMP; if slice.len() < 4 { return ALPROTO_FAILED; }