Lukas Sismis [Tue, 6 Feb 2024 10:38:19 +0000 (11:38 +0100)]
tcp: do not assign TCP flags to pseudopackets
Previously pseudopackets were assigned with ACK flag which falsely turned
"SYN" flows to "SYN/ACK" flows when Suricata ran with raw content-matching
rules. The problem occured during the flow timeout or Suricata shutdown,
essentially, when the flow was being kicked out (with a pseudopacket).
When Suricata ran without raw content-matching rules (the ruleset did not
contain content matching keywords or it only contained keywords that are
app-layer content-matching) then raw stream reassembly tracking is turned off
(SignatureHasStreamContent()).
This in turn disabled a check in StreamNeedsReassembly() and the right edge
was not checked with the raw stream progress. In turn, it did not generate
a pseudopacket that would go through the detection engine. Suricata with
raw content-matching keywords would therefore on a flow with SYN packet only
return STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION which would generate
the pseudopacket.
In Suricata versions <= 6.0.x, the flow output was correct because
only the commit 1bb6f44ff01363fa29488f1ae83b9368e33c2770 started to
differentiate the right edge calculation between the raw and application
layer streams. The older Suricata versions used only the application layer
right edge equation and therefore did not generate a pseudopacket.
Victor Julien [Sun, 11 Feb 2024 08:29:38 +0000 (09:29 +0100)]
multi-tenant: fix loader dead lock
A dead lock could occur at start up, where a loader thread would
get stuck on it's condition variable, while the main thread was
polling the loaders task results.
Between the main thread unlocking the loader and waking up the
threads, it is possible that the loader has already moved ahead
but not yet entered its conditional wait. The main thread sends
its condition signal, but since the loader isn't yet waiting on
it the signal is ignored. Then when the loader does enter its
conditional wait, the signal is not sent again.
This patch updates the logic to send signals much more often.
It also makes sure that the signal is sent under lock, as the
API requires.
Arne Welzel [Mon, 5 Feb 2024 16:45:30 +0000 (17:45 +0100)]
stats: Do not expand dots of tm_name
When an interface with dots is used, per worker stats are nested by the
dot-separated-components of the interface due to the usage of
OutputStats2Json().
Prevent this by using OutputStats2Json() on a per-thread specific object
and setting this object into the threads object using the
json_object_set_new() which won't do the dot expansion.
This was tested by creating an interface with dots in the name
and checking the stats.
ip link add name a.b.c type dummy
With Suricata 7.0.2, sniffing on the a.b.c interface results in the
following worker stats format:
Simon Dugas [Fri, 29 Dec 2023 16:58:50 +0000 (11:58 -0500)]
detect-engine-iponly: improve ip list performance
The runtime complexity of insertion sort is approx. O(h*n)^2 where
h is the size of the HOME_NET and n is the number of ip only rules
that use the HOME_NET.
Replacing this with qsort significantly improves rule load time when
a large HOME_NET is used in combination with a moderate amount of ip
only rules.
Philippe Antoine [Thu, 25 Jan 2024 13:26:09 +0000 (14:26 +0100)]
detect: respect directionality for filestore
Ticket: 6617
So that rules with keyword like `filestore:to_server,flow`
only store the files to server and not the ones to client...
Directionality only worked with the default scope, ie the
current file, and not the scope tx or scope flow.
For non-default scope, tx or flow, both directions were stored
whatever the directionality specified.
For these non-default scopes, this commit keeps a default
of both directions, but use only one direction if specified.
Need to split flag FLOWFILE_STORE per direction, so that Suricata
can retain this (optional) directional info from the filestore
keyword.
Jason Ish [Thu, 8 Feb 2024 19:21:11 +0000 (13:21 -0600)]
detect-http: add superfluous alloc check for cocci
Add not-needed SCCalloc return check to satisfy our Cocci malloc
checks as it can't see that the caller immediately checks the return
value of this simple wrapper around SCCalloc.
error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
--> src/dns/log.rs:371:29
|
371 | pub fn dns_print_addr(addr: &Vec<u8>) -> std::string::String {
| ^^^^^^^^ help: change this to: `&[u8]`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg
Instead of just setting the old transactions to a drop state so
that they get later cleaned up by Suricata, fail creating new ones.
This is because one call to app-layer parsing can create many
transactions, and quadratic complexity could happen in one
single app-layer parsing because of find_or_create_tx
Philippe Antoine [Tue, 17 Oct 2023 20:01:27 +0000 (22:01 +0200)]
pgsql: parse auth message within its bound
If the next PDU is already in the slice next, do not use it and
restrict ourselves to the length of this PDU.
Avoids overconsumption of memory by quadratic complexity, when
having many small PDUS in one big chunk being parsed
detect: fixes use-after-free with http.request_header
Ticket: #6441
This keyword and the response one use a multiple inspection buffer.
But the different instances point to the same memory address
that comes from HttpHeaderGetBufferSpace and is not owned
by the transaction, and is rebuilt, which is a functional
bug in itself.
As it gets crafted, it can get reallocated if one header
is over 1024 bytes, while the previous freed pointer will still get
used for the previous headers.
Philippe Antoine [Tue, 14 Nov 2023 20:51:37 +0000 (21:51 +0100)]
smtp: avoid creating empty transaction
Ticket: 6477
So as to avoid ending up with too many empty transactions.
This happens when Suricata sees a DATA command in the current
transaction but did not have a confirmation response for it.
Then, if Suricata receives another DATA command, it will
create another new transaction, even if the previous one
is empty. And so, a malicious client can create many empty
transactions by just sending a repeated amount of DATA commands
without having a confirmation code for them.
Suricata cannot use state->current_command == SMTP_COMMAND_DATA
to prevent this attack and needs to resort to a new boolean
is_data because the malicious client may send another dummy command
after each DATA command.
This patch leaves only one call to SMTPTransactionCreate
Philippe Antoine [Thu, 25 Jan 2024 15:01:14 +0000 (16:01 +0100)]
http2: handle reassembly for continuation frames
Ticket: 5926
HTTP2 continuation frames are defined in RFC 9113.
They allow header blocks to be split over multiple HTTP2 frames.
For Suricata to process correctly these header blocks, it
must do the reassembly of the payload of these HTTP2 frames.
Otherwise, we get incomplete decoding for headers names and/or
values while decoding a single frame.
Design is to add a field to the HTTP2 state, as the RFC states that
these continuation frames form a discrete unit :
> Field blocks MUST be transmitted as a contiguous sequence of frames,
> with no interleaved frames of any other type or from any other stream.
So, we do not have to duplicate this reassembly field per stream id.
Another design choice is to wait for the reassembly to be complete
before doing any decoding, to avoid quadratic complexity on partially
decoding of the data.
Philippe Antoine [Tue, 17 Oct 2023 08:26:57 +0000 (10:26 +0200)]
mqtt: fix logic when setting event
Especially sets transactions to complete when we get a response
without having seen the request, so that the transactions
end up getting cleaned (instead of living/leaking in the state).
Also try to set the event on the relevant transaction, instead
of creating a new transaction just for the purpose of having
the event.
When a TCP flow packet has not led to app-layer updates,
it is useless to run DetectRunTx, as there cannot be new
matches.
This happens for instance, when one side sends in a row multiple
packets which are not acked (and thus not parsed in IDS mode).
Doing so requires to move up the call to
AppLayerParserSetTransactionInspectId
so that it is run the same times DetectRunTx is run, and not in the
case where the transaction was not updated.
Jason Ish [Wed, 24 Jan 2024 15:02:19 +0000 (09:02 -0600)]
detect/requires: reset sigerror flags for each rule
"sigerror_ok" and "sigerror_requires" were not being reset after each
rule which could lead to a rule load error being incorrectly tracked
as skipped rather than failed.
Also initialize "skippedsigs" to 0 along with "goodsigs" and
"badsigs", while not directly related to this issue, could also throw
off some stats.
Lukas Sismis [Mon, 11 Dec 2023 00:47:55 +0000 (01:47 +0100)]
doc: remove references to prehistoric versions
Remove references that are mentioning Suricata 3 or less
As a note - only one Suricata 4 reference found:
(suricata-yaml.rst:"In 4.1.x")
Fast pattern selection criteria can be internally found by inspecting
SupportFastPatternForSigMatchList and SigTableSetup functions.
Lukas Sismis [Mon, 30 Oct 2023 11:33:57 +0000 (12:33 +0100)]
dpdk: rework hugepage hints to use per-numa information
Previous integration of hugepage analysis only fetched data
from /proc/meminfo. However this proved to be often
deceiving mainly for providing only global information and
not taking into account different hugepage sizes (e.g. 1GB
hugepages) and different NUMA nodes.
Gleb Smirnoff [Thu, 11 Jan 2024 21:35:21 +0000 (13:35 -0800)]
ipfw: close(2) instead shutdown(2) of the divert(4) socket
The shutdown(2) syscall would always return ENOTCONN for FreeBSD 11,
FreeBSD 12, FreeBSD 13 and FreeBSD 14. It could do some action on the
socket in the kernel in FreeBSD 10 and before, did not test.
Jason Ish [Wed, 29 Nov 2023 16:54:54 +0000 (10:54 -0600)]
requires: pre-scan rule for requires expressions
Add a "pre-scan" rule parse that will check for requires statement. It
will return a special error code (-4) if the requires fails due to
missing requirements.
According to PostgreSQL documentation the maximum number of rows can be
the maximum of tuples that can fit onto max u32 pages - 4,294,967,295 (cf
https://www.postgresql.org/docs/current/limits.html). Some rough
calculations for that indicate that this could go over max u32, so
updating the data_row data type to u64.
Parallel builds caused issues during `cargo vendor`. So do just a single
thread build.
make[4]: Entering directory '/__w/suricata/suricata/rust'
cbindgen --config /__w/suricata/suricata/rust/cbindgen.toml \
--quiet --output /__w/suricata/suricata/rust/dist/rust-bindings.h
CARGO_HOME="/github/home/.cargo" /usr/bin/cargo vendor
Blocking waiting for file lock on package cache
Blocking waiting for file lock on package cache
ERROR: Couldn't execute `cargo metadata` with manifest "/__w/suricata/suricata/rust/Cargo.toml": Metadata(Output { status: ExitStatus(unix_wait_status(25856)), stdout: "", stderr: " Blocking waiting for file lock on package cache\n Blocking waiting for file lock on package cache\nerror: failed to download `adler v1.0.2`\n\nCaused by:\n unable to get packages from source\n\nCaused by:\n failed to parse manifest at `/github/home/.cargo/registry/src/github.com-1ecc6299db9ec823/adler-1.0.2/Cargo.toml`\n\nCaused by:\n no targets specified in the manifest\n either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section must be present\n" })
ERROR: Couldn't generate bindings for /__w/suricata/suricata/rust.
make[4]: *** [Makefile:597: dist/rust-bindings.h] Error 1
make[4]: *** Waiting for unfinished jobs....
Clarify the transform validation step. When a transform indicates that
the content/byte-array is not compatible, validation will stop.
Content is incompatible is some cases -- e.g., following the
to_lowercase transform with content containing uppercase characters.
An alert is not possible since the content contains uppercase and the
transform has converted the buffer into all lowercase.
Add a more visible explanation of that requests, responses, frontend and
and backend are, in Pgsql context, to avoid having to repeat that over
different portions of the docs.
A CanceldRequest can occur after any query request, and is sent over a
new connection, leading to a new flow. It won't take any reply, but, if
processed by the backend, will lead to an ErrorResponse.
With the changes in the probing_ts function, this other one could become
obsolete. Remove it, and directly call `parser::parse_request` when
checking for gaps, instead.
Some non-pgsql traffic seen by Suricata is mistankenly identified as
pgsql, as the probing function is too generic. Now, if the parser sees
an unknown message type, even if it looks like pgsql, it will fail.
We had unkonwn message type for the backend, but not the frontend
messages. It's important to better identify those to improve pgsql
probing functions.
Jason Ish [Wed, 1 Nov 2023 22:57:39 +0000 (16:57 -0600)]
outputs: call plugin ThreadDeinit, not Deinit
With the change to the hash table for tracking threaded loggers, this
call is now called once per thread, so should be changed to the
ThreadDeinit, as that is not longer being called.
Then call Deinit for the primary logger. In threaded mode this would be
the parent, its just the logger in non-threaded mode.