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...

(cherry picked from commit 37a9003736)
pull/11096/head
Philippe Antoine 2 years ago
parent e797836b6e
commit b556619213

@ -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 len: u32, rdir: *mut u8) -> AppProto
{ {
SCLogDebug!("Probing packet for DCERPC"); SCLogDebug!("Probing packet for DCERPC");
if len == 0 { if len == 0 || input.is_null() {
return core::ALPROTO_UNKNOWN; return core::ALPROTO_UNKNOWN;
} }
let slice: &[u8] = std::slice::from_raw_parts(input as *mut u8, len as usize); let slice: &[u8] = std::slice::from_raw_parts(input as *mut u8, len as usize);

@ -311,7 +311,7 @@ pub unsafe extern "C" fn rs_dcerpc_probe_udp(_f: *const core::Flow, direction: u
len: u32, rdir: *mut u8) -> core::AppProto len: u32, rdir: *mut u8) -> core::AppProto
{ {
SCLogDebug!("Probing the packet for DCERPC/UDP"); SCLogDebug!("Probing the packet for DCERPC/UDP");
if len == 0 { if len == 0 || input.is_null() {
return core::ALPROTO_UNKNOWN; return core::ALPROTO_UNKNOWN;
} }
let slice: &[u8] = std::slice::from_raw_parts(input as *mut u8, len as usize); let slice: &[u8] = std::slice::from_raw_parts(input as *mut u8, len as usize);

@ -184,7 +184,7 @@ pub unsafe extern "C" fn rs_dhcp_probing_parser(_flow: *const Flow,
input_len: u32, input_len: u32,
_rdir: *mut u8) -> AppProto _rdir: *mut u8) -> AppProto
{ {
if input_len < DHCP_MIN_FRAME_LEN { if input_len < DHCP_MIN_FRAME_LEN || input.is_null() {
return ALPROTO_UNKNOWN; return ALPROTO_UNKNOWN;
} }

@ -917,7 +917,7 @@ pub unsafe extern "C" fn rs_dns_tx_get_query_rrtype(
pub unsafe extern "C" fn rs_dns_probe( pub unsafe extern "C" fn rs_dns_probe(
_flow: *const core::Flow, _dir: u8, input: *const u8, len: u32, rdir: *mut u8, _flow: *const core::Flow, _dir: u8, input: *const u8, len: u32, rdir: *mut u8,
) -> AppProto { ) -> AppProto {
if len == 0 || len < std::mem::size_of::<DNSHeader>() as u32 { if input.is_null() || len < std::mem::size_of::<DNSHeader>() as u32 {
return core::ALPROTO_UNKNOWN; return core::ALPROTO_UNKNOWN;
} }
let slice: &[u8] = std::slice::from_raw_parts(input as *mut u8, len as usize); let slice: &[u8] = std::slice::from_raw_parts(input as *mut u8, len as usize);
@ -938,7 +938,7 @@ pub unsafe extern "C" fn rs_dns_probe(
pub unsafe extern "C" fn rs_dns_probe_tcp( pub unsafe extern "C" fn rs_dns_probe_tcp(
_flow: *const core::Flow, direction: u8, input: *const u8, len: u32, rdir: *mut u8, _flow: *const core::Flow, direction: u8, input: *const u8, len: u32, rdir: *mut u8,
) -> AppProto { ) -> AppProto {
if len == 0 || len < std::mem::size_of::<DNSHeader>() as u32 + 2 { if input.is_null() || len < std::mem::size_of::<DNSHeader>() as u32 + 2 {
return core::ALPROTO_UNKNOWN; return core::ALPROTO_UNKNOWN;
} }
let slice: &[u8] = std::slice::from_raw_parts(input as *mut u8, len as usize); let slice: &[u8] = std::slice::from_raw_parts(input as *mut u8, len as usize);

@ -363,6 +363,9 @@ pub unsafe extern "C" fn rs_krb5_probing_parser(_flow: *const Flow,
input:*const u8, input_len: u32, input:*const u8, input_len: u32,
_rdir: *mut u8) -> AppProto _rdir: *mut u8) -> AppProto
{ {
if input.is_null() {
return ALPROTO_UNKNOWN;
}
let slice = build_slice!(input,input_len as usize); let slice = build_slice!(input,input_len as usize);
let alproto = ALPROTO_KRB5; let alproto = ALPROTO_KRB5;
if slice.len() <= 10 { return ALPROTO_FAILED; } if slice.len() <= 10 { return ALPROTO_FAILED; }
@ -402,6 +405,9 @@ pub unsafe extern "C" fn rs_krb5_probing_parser_tcp(_flow: *const Flow,
input:*const u8, input_len: u32, input:*const u8, input_len: u32,
rdir: *mut u8) -> AppProto rdir: *mut u8) -> AppProto
{ {
if input.is_null() {
return ALPROTO_UNKNOWN;
}
let slice = build_slice!(input,input_len as usize); let slice = build_slice!(input,input_len as usize);
if slice.len() <= 14 { return ALPROTO_FAILED; } if slice.len() <= 14 { return ALPROTO_FAILED; }
match be_u32(slice) as IResult<&[u8],u32> { match be_u32(slice) as IResult<&[u8],u32> {

@ -274,6 +274,9 @@ impl ModbusState {
pub extern "C" fn rs_modbus_probe( pub extern "C" fn rs_modbus_probe(
_flow: *const core::Flow, _direction: u8, input: *const u8, len: u32, _rdir: *mut u8, _flow: *const core::Flow, _direction: u8, input: *const u8, len: u32, _rdir: *mut u8,
) -> AppProto { ) -> AppProto {
if input.is_null() {
return ALPROTO_UNKNOWN;
}
let slice: &[u8] = unsafe { std::slice::from_raw_parts(input as *mut u8, len as usize) }; let slice: &[u8] = unsafe { std::slice::from_raw_parts(input as *mut u8, len as usize) };
match MODBUS_PARSER.probe(slice, Direction::Unknown) { match MODBUS_PARSER.probe(slice, Direction::Unknown) {
Status::Recognized => unsafe { ALPROTO_MODBUS }, Status::Recognized => unsafe { ALPROTO_MODBUS },

@ -616,6 +616,9 @@ impl MQTTState {
pub unsafe extern "C" fn rs_mqtt_probing_parser( pub unsafe extern "C" fn rs_mqtt_probing_parser(
_flow: *const Flow, _direction: u8, input: *const u8, input_len: u32, _rdir: *mut u8, _flow: *const Flow, _direction: u8, input: *const u8, input_len: u32, _rdir: *mut u8,
) -> AppProto { ) -> AppProto {
if input.is_null() {
return ALPROTO_UNKNOWN;
}
let buf = build_slice!(input, input_len as usize); let buf = build_slice!(input, input_len as usize);
match parse_fixed_header(buf) { match parse_fixed_header(buf) {
Ok((_, hdr)) => { Ok((_, hdr)) => {

@ -1881,6 +1881,9 @@ pub unsafe extern "C" fn rs_nfs_probe_ms(
direction: u8, input: *const u8, direction: u8, input: *const u8,
len: u32, rdir: *mut u8) -> AppProto len: u32, rdir: *mut u8) -> AppProto
{ {
if input.is_null() {
return ALPROTO_UNKNOWN;
}
let slice: &[u8] = build_slice!(input, len as usize); let slice: &[u8] = build_slice!(input, len as usize);
SCLogDebug!("rs_nfs_probe_ms: probing direction {:02x}", direction); SCLogDebug!("rs_nfs_probe_ms: probing direction {:02x}", direction);
let mut adirection : u8 = 0; let mut adirection : u8 = 0;
@ -1920,6 +1923,9 @@ pub unsafe extern "C" fn rs_nfs_probe(_f: *const Flow,
_rdir: *mut u8) _rdir: *mut u8)
-> AppProto -> AppProto
{ {
if input.is_null() {
return ALPROTO_UNKNOWN;
}
let slice: &[u8] = build_slice!(input, len as usize); let slice: &[u8] = build_slice!(input, len as usize);
SCLogDebug!("rs_nfs_probe: running probe"); SCLogDebug!("rs_nfs_probe: running probe");
match nfs_probe(slice, direction.into()) { match nfs_probe(slice, direction.into()) {
@ -1938,6 +1944,9 @@ pub unsafe extern "C" fn rs_nfs_probe_udp_ts(_f: *const Flow,
_rdir: *mut u8) _rdir: *mut u8)
-> AppProto -> AppProto
{ {
if input.is_null() {
return ALPROTO_UNKNOWN;
}
let slice: &[u8] = build_slice!(input, len as usize); let slice: &[u8] = build_slice!(input, len as usize);
match nfs_probe_udp(slice, Direction::ToServer) { match nfs_probe_udp(slice, Direction::ToServer) {
1 => { ALPROTO_NFS }, 1 => { ALPROTO_NFS },
@ -1955,6 +1964,9 @@ pub unsafe extern "C" fn rs_nfs_probe_udp_tc(_f: *const Flow,
_rdir: *mut u8) _rdir: *mut u8)
-> AppProto -> AppProto
{ {
if input.is_null() {
return ALPROTO_UNKNOWN;
}
let slice: &[u8] = build_slice!(input, len as usize); let slice: &[u8] = build_slice!(input, len as usize);
match nfs_probe_udp(slice, Direction::ToClient) { match nfs_probe_udp(slice, Direction::ToClient) {
1 => { ALPROTO_NFS }, 1 => { ALPROTO_NFS },

@ -245,6 +245,9 @@ pub extern "C" fn ntp_probing_parser(_flow: *const Flow,
input:*const u8, input_len: u32, input:*const u8, input_len: u32,
_rdir: *mut u8) -> AppProto _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 slice: &[u8] = unsafe { std::slice::from_raw_parts(input as *mut u8, input_len as usize) };
let alproto = unsafe{ ALPROTO_NTP }; let alproto = unsafe{ ALPROTO_NTP };
match parse_ntp(slice) { match parse_ntp(slice) {

@ -353,6 +353,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( pub unsafe extern "C" fn rs_quic_probing_parser(
_flow: *const Flow, _direction: u8, input: *const u8, input_len: u32, _rdir: *mut u8, _flow: *const Flow, _direction: u8, input: *const u8, input_len: u32, _rdir: *mut u8,
) -> AppProto { ) -> AppProto {
if input.is_null() {
return ALPROTO_UNKNOWN;
}
let slice = build_slice!(input, input_len as usize); let slice = build_slice!(input, input_len as usize);
if QuicHeader::from_bytes(slice, DEFAULT_DCID_LEN).is_ok() { if QuicHeader::from_bytes(slice, DEFAULT_DCID_LEN).is_ok() {

@ -2121,7 +2121,7 @@ pub unsafe extern "C" fn rs_smb_probe_begins_tcp(_f: *const Flow,
flags: u8, input: *const u8, len: u32, rdir: *mut u8) flags: u8, input: *const u8, len: u32, rdir: *mut u8)
-> AppProto -> AppProto
{ {
if len < MIN_REC_SIZE as u32 { if len < MIN_REC_SIZE as u32 || input.is_null() {
return ALPROTO_UNKNOWN; return ALPROTO_UNKNOWN;
} }
let slice = build_slice!(input, len as usize); let slice = build_slice!(input, len as usize);
@ -2135,7 +2135,7 @@ pub unsafe extern "C" fn rs_smb_probe_tcp(_f: *const Flow,
flags: u8, input: *const u8, len: u32, rdir: *mut u8) flags: u8, input: *const u8, len: u32, rdir: *mut u8)
-> AppProto -> AppProto
{ {
if len < MIN_REC_SIZE as u32 { if len < MIN_REC_SIZE as u32 || input.is_null() {
return ALPROTO_UNKNOWN; return ALPROTO_UNKNOWN;
} }
let slice = build_slice!(input, len as usize); let slice = build_slice!(input, len as usize);

@ -357,6 +357,9 @@ pub unsafe extern "C" fn rs_snmp_probing_parser(_flow: *const Flow,
input:*const u8, input:*const u8,
input_len: u32, input_len: u32,
_rdir: *mut u8) -> AppProto { _rdir: *mut u8) -> AppProto {
if input.is_null() {
return ALPROTO_UNKNOWN;
}
let slice = build_slice!(input,input_len as usize); let slice = build_slice!(input,input_len as usize);
let alproto = ALPROTO_SNMP; let alproto = ALPROTO_SNMP;
if slice.len() < 4 { return ALPROTO_FAILED; } if slice.len() < 4 { return ALPROTO_FAILED; }

Loading…
Cancel
Save