Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 49 additions & 30 deletions rust/src/dcerpc/dcerpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -762,21 +762,20 @@ impl DCERPCState {
}
}

pub fn handle_input_data(&mut self, stream_slice: StreamSlice, direction: Direction) -> AppLayerResult {
let retval;
let mut cur_i = stream_slice.as_slice();
let mut consumed = 0u32;
let mut rem = cur_i.len() as u32;
fn handle_gap (&mut self, i: &[u8], direction: Direction, mimic: bool) -> (u32, i8) {
let mut consumed;

if !mimic && ((!self.ts_gap && !self.tc_gap) || ((self.ts_gap && direction == Direction::ToClient) || (self.tc_gap && direction == Direction::ToServer))) {
return (0, 0);
}
// Skip the record since this means that its in the middle of a known length record
if (self.ts_gap && direction == Direction::ToServer) || (self.tc_gap && direction == Direction::ToClient) {
SCLogDebug!("Trying to catch up after GAP (input {})", cur_i.len());
match self.search_dcerpc_record(cur_i) {
Ok((_, pg)) => {
SCLogDebug!("DCERPC record found");
let offset = cur_i.len() - pg.len();
cur_i = &cur_i[offset..];
consumed = offset as u32;
SCLogDebug!("Trying to catch up after GAP (input {})", i.len());
match self.search_dcerpc_record(i) {
Ok((_, pg)) => {
SCLogDebug!("DCERPC record found");
let offset = i.len() - pg.len();
consumed = offset as u32;
if !mimic {
match direction {
Direction::ToServer => {
self.ts_gap = false;
Expand All @@ -785,20 +784,36 @@ impl DCERPCState {
self.tc_gap = false;
}
}
},
_ => {
consumed = cur_i.len() as u32;
// At least 2 bytes are required to know if a new record is beginning
if consumed < 2 {
consumed = 0;
} else {
consumed -= 1;
}
SCLogDebug!("DCERPC record NOT found");
return AppLayerResult::incomplete(consumed, 2);
},
}
}
},
_ => {
consumed = i.len() as u32;
// At least 2 bytes are required to know if a new record is beginning
if consumed < 2 {
consumed = 0;
} else {
consumed -= 1;
}
SCLogDebug!("DCERPC record NOT found");
return (consumed, -1);
},
}

(consumed, 0)
}

pub fn handle_input_data(&mut self, stream_slice: StreamSlice, direction: Direction) -> AppLayerResult {
let retval;
let mut cur_i = stream_slice.as_slice();
let mut rem = cur_i.len() as u32;

SCLogDebug!("ts_gap: {:?}; direction: {:?}; tc_gap: {:?}", self.ts_gap, direction, self.tc_gap);
let (nb, ret) = self.handle_gap(cur_i, direction, false /* handling the actual gap */);
let mut consumed = nb;
if ret == -1 {
return AppLayerResult::incomplete(consumed, 2);
}
cur_i = &cur_i[consumed as usize..];
rem -= consumed;

let mut flow = std::ptr::null_mut();
Expand All @@ -817,7 +832,11 @@ impl DCERPCState {
header.rpc_vers,
header.rpc_vers_minor
);
return AppLayerResult::err();
SCLogDebug!("mimicing gap for invalid header");
let (nb, _ret) = self.handle_gap(cur_i, direction, true /* mimicing a gap */);
consumed += nb;
/* no need to update rem/cur_i as it won't be used anymore */
return AppLayerResult::incomplete(consumed, rem - consumed);
}
header
}
Expand Down Expand Up @@ -859,10 +878,10 @@ impl DCERPCState {

let hdrtype = hdr.hdrtype;

let _hdr = Frame::new(flow, &stream_slice, &cur_i[consumed as usize..], DCERPC_HDR_LEN as i64, DCERPCFrameType::Hdr as u8, None);
let _pdu = Frame::new(flow, &stream_slice, &cur_i[consumed as usize..], fraglen as i64, DCERPCFrameType::Pdu as u8, None);
let _hdr = Frame::new(flow, &stream_slice, cur_i, DCERPC_HDR_LEN as i64, DCERPCFrameType::Hdr as u8, None);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you reverting fc9da1c which was incorrect as found by oss-fuzz
Am I understanding this correctly ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you reverting fc9da1c which was incorrect as found by oss-fuzz Am I understanding this correctly ?

No, I'm not reverting it. I'm creating the slice in the beginning now so it'll be wrong to index here at consumed. L816: https://github.com/OISF/suricata/pull/14805/files#diff-bb348f48dcbb4845f97a114f74772ee4849098c3254221826e5e0a61cbe35830R816

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was already done at line 716
cur_i = &cur_i[offset..];
(with the line after being consumed = offset as u32; which is why fc9da1c is wrong)

Copy link
Member Author

@inashivb inashivb Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right. I'm surprised fuzzers didn't catch that. Behavior in this PR looks correct to me. wdyt?

Edit: I think I misunderstood what you are saying in this thread. Are you referring to fuzzers finding the crash in #14766 and that being fixed here? Then, yes. I did not realize that the crash found by the fuzzers was not because of the new code.

let _pdu = Frame::new(flow, &stream_slice, cur_i, fraglen as i64, DCERPCFrameType::Pdu as u8, None);
if fraglen >= DCERPC_HDR_LEN && rem > DCERPC_HDR_LEN as u32 {
let _data = Frame::new(flow, &stream_slice, &cur_i[(consumed + DCERPC_HDR_LEN as u32) as usize..], (fraglen - DCERPC_HDR_LEN) as i64, DCERPCFrameType::Data as u8, None);
let _data = Frame::new(flow, &stream_slice, &cur_i[DCERPC_HDR_LEN as usize..], (fraglen - DCERPC_HDR_LEN) as i64, DCERPCFrameType::Data as u8, None);
}
let current_call_id = hdr.call_id;

Expand Down
Loading