This patch resets the AFPPacketVar linked to a Packet in the release
function to avoid any side effect when the packet is reused. To do
so a new AFPV_CLEANUP macro has been introduced.
This patch cleans the code were two almost identical treatment on
the packet we're made. It may be linked by a merge error I've done
or to a simple mistake on my side.
There was an inversion in code resulting as all sockets being seen
as non IPS mode when doing the peering. This resulted in a crash at
first packet because it has no peer.
This patch changes the policy of the timeout function by cleaning
every timeouted trackers.
Previous code was only freeing the first tracker and this was resulting
in calling the timeout function continuously. One of my previous patch
has modified the function to avoid to run it more than twice a second.
But as it was not taken into account the fact only the first tracker was
freed, the result was that a lot of tracker could not be allocated.
When nothing can be fetch from the pool, this can repeat frequently.
Thus displaying a message in the log will not help. This patch
uses a counter instead of a log message. As this is a sort of memcap
this is conformed to what is done for other issues of the same type.
In some setup, suricata may receive broadcast packets and the call
to sendto may fail if the wrong interface is choosen by kernel.
This patch change the error treatment to avoid to leave when
this problem occurs.
A crash can occurs in the following conditions:
* Suricata running in other mode than "workers"
* Kernel fill in the ring buffer
Under this conditions, it is possible that the capture thread reads
a packet that has not yet released by one of the treatment threads
because there is no modification done on the ring buffer entry when
a packet is read. Doing, this it access to memory which can be
released to the kernel and modified. This results in a kind of memory
corruption.
This bug has only been seen recently and this has to be linked with the
read speed improvement recently made in AF_PACKET support.
The patch fixes the issue by modifying the tp_status bitmask in the
ring buffer. It sets the TP_STATUS_USER_BUSY flag when it is confirmed
that the packet will be treated. And at the start of the read, it exits
from the reading loop (returning to poll) when it reaches a packet with
the flag set. As tp_status is set to 0 during packet release the flag
is destroyed when releasing the packet.
Regarding concurrency, we've got a sequence of modification. The
capture thread read the packet and set the flag, then it passes the
queue and the packet get processed by other threads. The change on
tp_status are thus made at different time.
Regarding the value of the flag, the patch uses the last bit of
tp_status to avoid be impacting by a change in kernel. I will
propose a patch to have TP_STATUS_USER_BUSY included in kernel
as this is a generic issue for multithreading application using
AF_PACKET mechanism.