Commit Graph

12951 Commits (3b13008c1b6b994df0ae3f702c24780fd253ec32)
 

Author SHA1 Message Date
Philippe Antoine 8f8823b6f2 rust: right condition for both uint to be zero
Theay can overflow leading to their addition to be zero

If a NFS read reply indicates a count of 0xFFFFFFFF

Bug: #4680.
3 years ago
Philippe Antoine 689ac97d72 inspect: debug validation to ensure correct argument 3 years ago
Philippe Antoine c3339c853e detect: fixes InspectionBuffer id with transforms
When InspectionBufferGet gets called with base_id
Later InspectionBufferSetup must also be called with base_id

In case there were transforms, we had base_id != list_id

Not calling InspectionBufferSetup with the right id
resulted in leaving a dangling pointer,
because it was not added to det_ctx->inspect.to_clear_queue

Bug: #4681.
3 years ago
Victor Julien 244dd11c34 flow/manager: fix flows not evicted & freed in time
Flows have been shown to linger for a long time w/o giving up their
resources. This would lead to higher memory use and memcaps getting
reached.

Three main causes have been identified:

Slow passes hash passes. By default the flow manager will scan the
flow hash slowly. It is based on the flow timeout settings, and with
the default config it will take 4 minutes for a full scan to be
complete. This leaves a window for flows that are timed out to linger
for minutes longer than expected.

Flow Manager yields under pressure. The per row TryLock causes work
to be delayed more. The Flow manager will use trylock on a hash row
and will yield immediately if the row is busy. This means that it will
take a full pass before the row is revisited again. If the row holds
busy flows, this could happen many times in a row.

Flow Manager favors evicted flows over active flows. The Flow Manager
will only process the evicted flows if they are present. These flows
have been evicted by workers. The active flows on that hash row will
have to wait until the next hash pass. Of course by then there could
be more evicted flows.

Combined these factors could lead to flows not being considered for
freeing and logging for a very long time, potentially even indefinitly.

The patch addresses the latter two flow manager issues by no longer
using TryLock. It will now simply wait for the lock to be released and
then do its work on it. Additionally for each row both the evicted list
and the active flow list will be processed.

Bug: #4650.
3 years ago
Victor Julien ace349d4d9 af-packet: simplify tpacket-v2 setup code
Setup can no longer fail, so make the function void and remove dead
error checking code.
3 years ago
Victor Julien 2cbfcce0ac af-packet: PacketSetData can't fail; remove check
PacketSetData() can't fail unless the input pointer is NULL, which is
impossible from the af-packet paths calling it. Remove error check to
avoid possible branching.
3 years ago
Victor Julien 12252ba751 af-packet: fix if/down issues with tpacket-v2/autofp
The AFPSwitchState function would close the socket and free the
other resources when the interface went down _and_ the ref cnt was
0. However in autofp mode it was common to get to this point while
packets were still processed in the autofp worker threads, meaning
the ref cnt would not be 0. On the interface coming back up the
initialization code would overwrite the socket and rings, leading
to resource leaks.

Socket ref cnt is decremented from the v2 release callback. If the
callback would get to ref cnt 0, the packet would not be released
in the kernel, but it would (possibly) close the socket if the
iface was down, but not free other resources.

This patch changes the logic to first release the packet to the
kernel and then decrement the ref cnt and it makes the main receive
loop the only one responsible for opening and closing sockets. Wait
with closing the socket and rings until the ref count is 0, which can
happen after AFPSwitchState is called due to packets still being
processed by autofp worker threads.

Bug: #4803.
3 years ago
Victor Julien 3f8e15f70c af-packet: packet checks into debug validate check 3 years ago
Victor Julien 5e05fedc90 af-packet: hide all ebpf/bypass logic behind guards
Leave no runtime checks for bypass/ebpf/xdp if not compiled in.
3 years ago
Victor Julien e63db9d1d2 af-packet: minor code cleanups 3 years ago
Victor Julien e3d20acb98 af-packet: simplify socket handling in tpacket v3
Tpacket v3 only supports workers mode, which means the packet that would
reference a socket won't leave the thread. Therefore keeping a ref count
on the socket is not needed.

This patch removes the per packet reference count increment. The decrement
was missing, so this fixes the ref cnt handling so that after a iface up/
down capture can recover.

It should also lead to a minor performance increase as we avoid a round
of atomic operations per packet.

Bug: #4804.
Bug: #4801.
3 years ago
Victor Julien 6eaaafc360 af-packet: minor config parsing cleanup 3 years ago
Victor Julien be122ceb8f af-packet: remove obsolete define 3 years ago
Victor Julien 558930a192 af-packet: remove zero copy flag
Flag was always set for tpacket v2 and v3, which meant the check
for it in the packet setup paths were useless.
3 years ago
Victor Julien ad862fff37 af-packet: avoid flag colision with kernel
Avoid colision of TP_STATUS_USER_BUSY with TP_STATUS_TS_RAW_HARDWARE,
both were using bit 31.

Bug: #4800.
3 years ago
Victor Julien a022648b9e af-packet: fix soft lockup issues
The Suricata AF_PACKET code opens a socket per thread, then after some minor
setup enters a loop where the socket is poll()'d with a timeout. When the
poll() call returns a non zero positive value, the AF_PACKET ring will be
processed.

The ringbuffer processing logic has a pointer into the ring where we last
checked the ring. From this position we will inspect each frame until we
find a frame with tp_status == TP_STATUS_KERNEL (so essentially 0). This
means the frame is currently owned by the kernel.

There is a special case handling for starting the ring processing but
finding a TP_STATUS_KERNEL immediately. This logic then skip to the next
frame, rerun the check, etc until it either finds an initialized frame or
the last frame of the ringbuffer.

The problem was, however, that the initial uninitialized frame was possibly
(likely?) still being initialized by the kernel. A data race between the
notification through the socket (the poll()) and the updating of the
`tp_status` field in the frame could lead to a valid frame getting skipped.

Of note is that for example libpcap does not do frame scanning. Instead it
simply exits it ring processing loop. Also interesting is that libpcap uses
atomic loads and stores on the tp_status field.

This skipping of frames had 2 bad side effects:

1. in most cases, the buffer would be full enough that the frame would
   be processed in the next pass of the ring, but now the frame would
   out of order. This might have lead to packets belong to the same
   flow getting processed in the wrong order.

2. more severe is the soft lockup case. The skipped frame sits at ring
   buffer index 0. The rest of the ring has been cleared, after the
   initial frame was skipped. As our pass of the ring stops at the end
   of the ring (ptv->frame_offset + 1 == ptv->req.v2.tp_frame_nr) the code
   exits the ring processing loop at goes back to poll(). However, poll()
   will not indicate that there is more data, as the stale frame in the
   ring blocks the kernel from populating more frames beyond it. This
   is now a dead lock, as the kernel waits for Suricata and Suricata
   never touches the ring until it hears from the kernel.

   The scan logic will scan the whole ring at most once, so it won't
   reconsider the stale frame either.

This patch addresses the issues in several ways:

1. the startup "discard" logic was fixed to not skip over kernel
   frames. Doing so would get us in a bad state at start up.

2. Instead of scanning the ring, we now enter a busy wait loop
   when encountering a kernel frame where we didn't expect one. This
   means that if we got a > 0 poll() result, we'll busy wait until
   we get at least one frame.

3. Error handling is unified and cleaned up. Any frame error now
   returns the frame to the kernel and progresses the frame pointer.

4. If we find a frame that is owned by us (TP_STATUS_USER_BUSY) we
   yield to poll() immediately, as the next expected status of that
   frame is TP_STATUS_KERNEL.

5. the ring is no longer processed until the "end" of the ring (so
   highest index), but instead we process at most one full ring size
   per run.

6. Work with a copy of `tp_status` instead of accessing original touched
   also by the kernel.

Bug: #4785.
3 years ago
Victor Julien 8b08b0343d af-packet: define all current TP_STATUS_* flags 3 years ago
Modupe Falodun fac33118cc detect-rfb-secresult: convert unittest to FAIL/PASS APIs
Bug: #4055
3 years ago
Modupe Falodun e9779b0fa0 detect-sameip: convert unittests to FAIL/PASS APIs
Bug: #4057
3 years ago
Sam Muhammed 025fd385cd detect/event: convert unittests to FAIL/PASS APIs
Task #4025
3 years ago
Victor Julien 07ce871da4 packetpool: reset PacketRelease on return to pool
Reset PacketRelease callback to make sure its not set to a capture
specific callback.

As an example:

  0x000055e00af09d35 in AFPReleaseDataFromRing (p=0x7f1d884cb830) at source-af-packet.c:653
  0x000055e00af09dd0 in AFPReleasePacket (p=0x7f1d884cb830) at source-af-packet.c:678
  0x000055e00ab53d7e in TmqhOutputPacketpool (t=0x55e00fb79250, p=0x7f1d884cb830) at tmqh-packetpool.c:465
  0x000055e00af08dec in TmThreadsSlotProcessPkt (tv=0x55e00fb79250, s=0x55e012134790, p=0x7f1d884cb830) at tm-threads.h:201
  0x000055e00af08e70 in TmThreadsCaptureInjectPacket (tv=0x55e00fb79250, p=0x7f1d884cb830) at tm-threads.h:221
  0x000055e00af08f2e in TmThreadsCaptureHandleTimeout (tv=0x55e00fb79250, p=0x0) at tm-threads.h:245
  0x000055e00af0ba76 in ReceiveAFPLoop (tv=0x55e00fb79250, data=0x7f1d884ccb60, slot=0x55e01198e4b0) at source-af-packet.c:1321
  0x000055e00ab55257 in TmThreadsSlotPktAcqLoop (td=0x55e00fb79250) at tm-threads.c:312
  0x00007f1dca9d5609 in start_thread (arg=<optimized out>) at pthread_create.c:477
  0x00007f1dca7c6293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

Here the packet was a pseudo packet to handle a timeout condition. But
the ReleasePacket callback was still set to AFPReleasePacket from a
previous use of the Packet.

Bug: #4807.
3 years ago
Sam Muhammed 214ea9bea5 detect/payload: convert unittests to FAIL/PASS APIs
Task #4026
3 years ago
Modupe Falodun a59299d128 detect-gid: convert unittests to FAIL/PASS APIs
Bug: #4041
3 years ago
Juliana Fajardini d581fc82b1 util/unittests: delete PASS_IF macro
The logic flow we want to achieve with unittests, where first we have
all FAIL statements and then just one PASS statement could become more
convoluted with the existence of the PASS_IF macro. Besides, what could
be written as a FAIL_IF might in some cases be written in not so clear
ways with the PASS_IF option available.

Also: fix inverted check values in documentation, update copyright year

Optimization: #4795
3 years ago
Juliana Fajardini f328ba527a detect/dsize: convert unittests to FAIL/PASS API
Also: change them to comply with the deletion of PASS_IF macro &
condense checks for invalid dsizes in one test, have all checks on same
valid dsize happen in a single test.

Task: #4021
3 years ago
Juliana Fajardini b3743cf5c0 unittests (assorted): remove PASS_IF macro
Also small documentation clean up and test adjusments where that
was needed.

affected: counters, decode-vntag, detect-mark

Related to #4795
3 years ago
Juliana Fajardini c6e97222b7 devguide: add page about rust unittests
Part of the task to offer better guidance on how and when to write
unit tests or suricata-verify tests
Also updated linking and index files, as well as testing page to refer
to the unit tests pages

Doc: #4590
3 years ago
Juliana Fajardini 747d225c84 devguide: repurpose unittests page to unittests-c
Part of ongoing task to add more guidance on how to create unittests
and suricata-verify tests for suri. There will also be a unittests-rust
page.

Doc: #4590
3 years ago
Juliana Fajardini 5b4c575f3b devguide: add page about testing
This page offers guidance about when to use unittests or s-v tests,
and how to create input for those. Also lists other common ways to test
Suri, such as fuzzing and the CI checks.

Doc: #4590
3 years ago
Pierre Chifflier ce652511bd rust/tftp: convert parser to nom7 functions 3 years ago
Pierre Chifflier c525a1337c rust/dns: convert parser to nom7 functions 3 years ago
Pierre Chifflier 74be8b94ec rust/ssh: convert parser to nom7 functions 3 years ago
Pierre Chifflier 8a584c211e rust/mqtt: convert parser to nom7 functions 3 years ago
Pierre Chifflier d27125d77a rust/sip: convert parser to nom7 functions 3 years ago
Pierre Chifflier 1046a7d1a3 rust/ftp: convert parser to nom7 functions 3 years ago
Pierre Chifflier ebd5883da8 rust/dhcp: convert parser to nom7 functions 3 years ago
Pierre Chifflier 17170c41aa rust: add nom7 dependency 3 years ago
Modupe Falodun a87c7e5c08 rust: remove unnecessary nested match
Bug: #4605
3 years ago
Modupe Falodun 74c39500c3 rust: fix inherent to string
Bug: OISF#4618
3 years ago
Sam Muhammed 922a453da5 rust(lint): use is_null() instead of ptr::null_mut()
Bug: #4594
3 years ago
Sam Muhammed 23768c7181 rust(lint): use is_null() instead of ptr::null()
Bug: #4594
3 years ago
Sam Muhammed da0a976e23 rust(lint): use let for binding single value
`match` is better used with binding to multiple variables,
for binding to a single value, `let` statement is recommended.

Bug: #4616
3 years ago
Sam Muhammed 42d4eb6943 detect-engine: convert unittests to FAIL/PASS APIs 3 years ago
Victor Julien 286c510ece flow: immediately evict tcp reused flows
Since we already know we're going to no longer use it, might as well
evict it right away.
3 years ago
Victor Julien 536291054c flow/bypass: clear memory on bypass
Previously the flow would hold on to the app-layer and segment data
until the end of the flow, even though it would never be accessed again.

This patch clears app-layer and stream data, but not stream ssn as its
used in flow logging.

Bug: #4778.
3 years ago
Victor Julien b19d1df69f flow/bypass: add util func to check if flow is bypassed
To hide the ifdefs for capture offload.
3 years ago
Victor Julien ab8f289bb6 flow/worker: run housekeeping for bypassed packets
Run flow eviction and flow inject queues for bypassed packets as well,
to avoid a scenario where these won't get run at all if too much of the
traffic is bypassed.

Bug: #4779.
3 years ago
Victor Julien 41fee41722 flow/manager: remove obsolete code 3 years ago
Victor Julien ec7e0561e8 flow/bypass: use_cnt desync'd on bypassed flows
Locally bypassed flows had unsafe updates to `Flow::use_cnt` leading to a race
issue. For a packet it would do the flow lookup, attach the flow to the packet,
increment the `use_cnt`. Then it would detect that the flow is in the bypass
state, and unlock it while holding a reference (so alos not decrementing the
`use_cnt`). When the packet was then returned to the packet pool, the flow would
be disconnected from the packet, which would decrement `use_cnt` without holding
the flow lock.

This patch addresses this issue by disconnecting the flow from the packet
immediately when the bypassed state is detected. This moves the `use_cnt`
decrement to within the lock.

Bug: #4766.
3 years ago
Philippe Antoine 416575ea02 pcrexform: use substring and not whole match 3 years ago