pgsql: config limit maximum number of live transactions

As is done for other protocols

Ticket: #5527
pull/7884/head
Philippe Antoine 4 years ago committed by Victor Julien
parent e160917bcf
commit af40873127

@ -1721,7 +1721,7 @@ incompatible with ``decode-mime``. If both are enabled,
Maximum transactions Maximum transactions
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
MQTT, FTP, and NFS have each a `max-tx` parameter that can be customized. MQTT, FTP, PostgreSQL and NFS have each a `max-tx` parameter that can be customized.
`max-tx` refers to the maximum number of live transactions for each flow. `max-tx` refers to the maximum number of live transactions for each flow.
An app-layer event `protocol.too_many_transactions` is triggered when this value is reached. An app-layer event `protocol.too_many_transactions` is triggered when this value is reached.
The point of this parameter is to find a balance between the completeness of analysis The point of this parameter is to find a balance between the completeness of analysis

@ -32,12 +32,15 @@ pub const PGSQL_CONFIG_DEFAULT_STREAM_DEPTH: u32 = 0;
static mut ALPROTO_PGSQL: AppProto = ALPROTO_UNKNOWN; static mut ALPROTO_PGSQL: AppProto = ALPROTO_UNKNOWN;
static mut PGSQL_MAX_TX: usize = 1024;
#[repr(u8)] #[repr(u8)]
#[derive(Copy, Clone, PartialOrd, PartialEq, Debug)] #[derive(Copy, Clone, PartialOrd, PartialEq, Debug)]
pub enum PgsqlTransactionState { pub enum PgsqlTransactionState {
Init = 0, Init = 0,
RequestReceived, RequestReceived,
ResponseDone, ResponseDone,
FlushedOut,
} }
#[derive(Debug)] #[derive(Debug)]
@ -123,6 +126,7 @@ pub struct PgsqlState {
backend_secret_key: u32, backend_secret_key: u32,
backend_pid: u32, backend_pid: u32,
state_progress: PgsqlStateProgress, state_progress: PgsqlStateProgress,
tx_index_completed: usize,
} }
impl State<PgsqlTransaction> for PgsqlState { impl State<PgsqlTransaction> for PgsqlState {
@ -145,6 +149,7 @@ impl PgsqlState {
backend_secret_key: 0, backend_secret_key: 0,
backend_pid: 0, backend_pid: 0,
state_progress: PgsqlStateProgress::IdleState, state_progress: PgsqlStateProgress::IdleState,
tx_index_completed: 0,
} }
} }
@ -162,6 +167,7 @@ impl PgsqlState {
} }
} }
if found { if found {
self.tx_index_completed = 0;
self.transactions.remove(index); self.transactions.remove(index);
} }
} }
@ -180,6 +186,21 @@ impl PgsqlState {
self.tx_id += 1; self.tx_id += 1;
tx.tx_id = self.tx_id; tx.tx_id = self.tx_id;
SCLogDebug!("Creating new transaction. tx_id: {}", tx.tx_id); SCLogDebug!("Creating new transaction. tx_id: {}", tx.tx_id);
if self.transactions.len() > unsafe { PGSQL_MAX_TX } + self.tx_index_completed {
// If there are too many open transactions,
// mark the earliest ones as completed, and take care
// to avoid quadratic complexity
let mut index = self.tx_index_completed;
for tx_old in &mut self.transactions.range_mut(self.tx_index_completed..) {
index = index + 1;
if tx_old.tx_state < PgsqlTransactionState::ResponseDone {
tx_old.tx_state = PgsqlTransactionState::FlushedOut;
//TODO set event
break;
}
}
self.tx_index_completed = index;
}
return tx; return tx;
} }
@ -738,6 +759,13 @@ pub unsafe extern "C" fn rs_pgsql_register_parser() {
} }
AppLayerParserSetStreamDepth(IPPROTO_TCP as u8, ALPROTO_PGSQL, stream_depth) AppLayerParserSetStreamDepth(IPPROTO_TCP as u8, ALPROTO_PGSQL, stream_depth)
} }
if let Some(val) = conf_get("app-layer.protocols.pgsql.max-tx") {
if let Ok(v) = val.parse::<usize>() {
PGSQL_MAX_TX = v;
} else {
SCLogError!("Invalid value for pgsql.max-tx");
}
}
} else { } else {
SCLogDebug!("Protocol detector and parser disabled for PGSQL."); SCLogDebug!("Protocol detector and parser disabled for PGSQL.");
} }

@ -835,6 +835,8 @@ app-layer:
enabled: no enabled: no
# Stream reassembly size for PostgreSQL. By default, track it completely. # Stream reassembly size for PostgreSQL. By default, track it completely.
stream-depth: 0 stream-depth: 0
# Maximum number of live PostgreSQL transactions per flow
# max-tx: 1024
dcerpc: dcerpc:
enabled: yes enabled: yes
ftp: ftp:

Loading…
Cancel
Save