Crisis response for server operators

The situation

Trigger a CPU-hogging process and a service that keeps hitting its memory limit, then learn to read the alerts, tell a miner apart, and limit or stop in the right order.

  • Level: Basics
  • About 35 min
  • 2026-11-12

#The situation

Shortly after 11 a.m., two alerts arrive

Both are RoamSwitch alerts: "Resource Exhaustion Guard: sustained high CPU". Then a colleague writes: "The server is so slow that pages barely load."

CPU or memory runs out for many reasons. A nightly report may simply be running long. A service may hit its memory limit and keep crashing and coming back. Or an intruder may have planted a cryptocurrency miner.

The operator has three things to decide. Which process is the cause. Whether it is legitimate work or something planted. Whether to stop it or limit it.

This playbook walks through those decisions and steps, triggered for real inside a disposable VM.

StepWhat you doWhat you use
1. TriggerRun three harmless loadssystemd-run, Python
2. LookRead the alerts and the recordsResource exhaustion and crash detection, Notification history, Incident timeline
3. InvestigateDecide which process, which parent, and since whenps, ss, Process execution recording and attack-technique detection
4. RespondStop, limit, and prevent a repeatsystemctl, kill, unit settings
5. UndoClean up the practice setup

How the detection works, and how to trigger memory growth and a container crash loop, are covered in Containers and servers. This module focuses on the decisions and steps after an alert arrives.

Practice in a disposable environment

This module deliberately runs a process that uses up CPU and a service that uses up memory. The memory service gets a MemoryMax=100M limit. It stops inside that limit, so the VM as a whole does not run out of memory. Every load runs inside the VM only, and nothing is sent outside it.

#Prepare the practice setup

Resource exhaustion and crash detection only notifies. It never stops a process. The CPU check defaults are as follows (from /etc/roamswitch/server.conf.example and the defaults in the source).

KeyDefaultMeaning
resource_guard_cpu_enabledtrueWatch for processes that keep using CPU
resource_guard_cpu_sample_interval_secs60How often CPU is measured (seconds)
resource_guard_cpu_window_secs600The window that is judged (seconds)
resource_guard_cpu_min_samples8Measurements needed before judging
resource_guard_cpu_pct_threshold80Per core, this % or more counts as "high"

An alert fires when at least 90% of the measurements in the window are at 80% or more. Unlike the memory check, processes that do not listen on a port are included. A miner only connects out and never listens.

Shorten the measuring interval

By default a verdict takes about 8 minutes. For the exercise, the interval goes down to 10 seconds. The log audit, which is what reads crash loops, goes down to its minimum of 300 seconds (this changes the machine; the last lab puts it back). Each change needs a restart to apply.

sudo roamswitch server config set resource_guard_rss_sample_interval_secs 10
sudo roamswitch server config set resource_guard_cpu_sample_interval_secs 10
sudo roamswitch server config set log_audit_interval_secs 300
sudo roamswitch server restart
Output excerpt
  ✓ Server configuration updated and saved. (resource_guard_rss_sample_interval_secs = 10)
  To apply: sudo systemctl restart roamswitch-server or sudo roamswitch server restart

  ✓ Server configuration updated and saved. (resource_guard_cpu_sample_interval_secs = 10)
  ✓ Server configuration updated and saved. (log_audit_interval_secs = 300)
  🔄 Restarting roamswitch-server service...
  ✓ roamswitch-server service successfully restarted.

Shorten both the memory and the CPU interval. Right after a restart, the execution record may not have started yet. Wait about 30 seconds before the next lab.

Do not leave the intervals short

A short interval makes the daemon read /proc more often. Short spikes, such as a build, also become more likely to alert. Put the defaults back after the exercise.

#Find the process that keeps using CPU

Two harmless loads run, in two shapes.

  • A nightly report: runs as lab-report.service, as nobody. It only spins the CPU
  • A planted miner: python3 copied to /var/tmp/.cache/kswapd0. Its name imitates a kernel thread, and it stays connected to 127.0.0.1:3333. If it is stopped, its parent shell starts it again 5 seconds later

Port 3333 is one that mining pools commonly use. A lab-pool.service inside the VM only accepts connections and stands in for an outside pool.

Start the loads and read the alerts

This starts processes (it changes the machine). How to stop them is in the labs of the following chapters.

sudo mkdir -p /opt/lab
sudo tee /opt/lab/busy.py >/dev/null <<'PY'
import socket, sys
if len(sys.argv) > 1:
    conn = socket.create_connection(("127.0.0.1", int(sys.argv[1])))
while True:
    pass
PY
sudo tee /opt/lab/pool.py >/dev/null <<'PY'
import socket
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(("127.0.0.1", 3333)); s.listen()
held = []
while True:
    c, _ = s.accept(); held.append(c)
PY
sudo systemd-run --unit=lab-report -p User=nobody python3 /opt/lab/busy.py
sudo systemd-run --unit=lab-pool python3 /opt/lab/pool.py
mkdir -p /var/tmp/.cache
cp /usr/bin/python3 /var/tmp/.cache/kswapd0
setsid sh -c 'while true; do /var/tmp/.cache/kswapd0 /opt/lab/busy.py 3333; sleep 5; done' </dev/null >/dev/null 2>&1 &
Output
Running as unit: lab-report.service; invocation ID: 6deadc33aad94898b3bd398bb584c29d
Running as unit: lab-pool.service; invocation ID: 85a1340921cd45d5bb62c005e3bab6b1

In this VM, two alerts appeared after about a minute and a half.

sudo roamswitch notifications | grep -A11 "sustained high CPU"
Output excerpt
  [CORRELATED] Resource Exhaustion Guard: sustained high CPU — kswapd0
    🚨 Process has stayed near-saturated CPU for a sustained period (possible cryptominer)
    Host: ubuntu (IP: 192.168.64.33)
    Process: kswapd0 (PID: 1562)
    Container: not a container process
    Average CPU in window: 100%
    Correlated signals: mining_port_signature
    Timestamp: 2026-11-12 02:12:24
    Process: admin / /var/tmp/.cache/kswapd0 / command: /var/tmp/.cache/kswapd0 /opt/lab/busy.py 3333 (pid 1562)
    Parent processes: dash ← dash ← tart-guest-agent ← systemd / Service: tart-guest-agent.service

  2026-11-12T02:12:24.868630820+00:00
  [POSSIBLE] Resource Exhaustion Guard: sustained high CPU — python3
    ⚠️ Process has used sustained high CPU for an extended period (common for compiles, scans, or batch jobs — review if unexpected)
    Host: ubuntu (IP: 192.168.64.33)
    Process: python3 (PID: 1550)
    Container: not a container process
    Average CPU in window: 100%
    Correlated signals: none
    Timestamp: 2026-11-12 02:12:24
    Process: nobody / /usr/bin/python3.12 / command: /usr/bin/python3 /opt/lab/busy.py (pid 1550)
    Parent processes: systemd / Service: lab-report.service

The CPU use is the same, but the two headlines differ.

  • [POSSIBLE] and "common for compiles, scans, or batch jobs": nothing backs it up apart from the CPU use
  • [CORRELATED] and "possible cryptominer": mining_port_signature was added. The process held a connection to a port that pools commonly use
  • Timestamp: it is in UTC (11:12 in Japan time)

Besides the alerts, the unified timeline lists the same detections.

sudo roamswitch timeline | head -22
Output excerpt
  2026-11-12T02:12:24.913354996+00:00  [Resource Guard]  recorded only
    cpu_saturation: avg CPU 100% sustained over window
    process: kswapd0 (pid 1562)
    process ancestry: dash ← dash ← tart-guest-agent ← systemd
    action taken: Logged & Monitored (notify-only)

  2026-11-12T02:12:24.869087652+00:00  [Resource Guard]  recorded only
    cpu_saturation: avg CPU 100% sustained over window
    process: python3 (pid 1550)
    process ancestry: systemd
    action taken: Logged & Monitored (notify-only)

  2026-11-12T02:10:55.916215869+00:00  [Exec Recorder]  recorded only
    EXR-002: execution from a world-writable directory, category: tmp, path: /var/tmp/.cache/kswapd0
    process: /var/tmp/.cache/kswapd0 (pid 1562)
    process ancestry: dash ← dash ← tart-guest-agent ← systemd
    MITRE ATT&CK: T1059 (Command and Scripting Interpreter)
    action taken: notify

kswapd0 has one more detection, about 90 seconds earlier at 02:10:55, right after it started. It is from the Process execution recording and attack-technique detection: the program ran from /var/tmp, which anyone can write to. As the "action taken" lines show, neither guard stopped the process.

#Find out which process it is and where it came from

Start from the PIDs in the alerts and check four things: where the executable is, the parent, the connections, and when it started. All of these only read; nothing changes.

Investigate the processes

Look at the two PIDs side by side.

uptime
ps -o pid,ppid,user,lstart,pcpu,args -p 1550,1562
sudo ls -l /proc/1550/exe /proc/1562/exe
sudo ss -tnpH state established '( dport = :3333 )'
cat /proc/1550/cgroup /proc/1562/cgroup
Output
 02:12:27 up 2 min,  0 user,  load average: 1.83, 0.62, 0.22
    PID    PPID USER                      STARTED %CPU COMMAND
   1550       1 nobody   Thu Nov 12 02:10:55 2026 99.9 /usr/bin/python3 /opt/lab/busy.py
   1562    1557 admin    Thu Nov 12 02:10:55 2026 99.9 /var/tmp/.cache/kswapd0 /opt/lab/busy.py 3333
lrwxrwxrwx 1 nobody nogroup 0 Nov 12 02:12 /proc/1550/exe -> /usr/bin/python3.12
lrwxrwxrwx 1 admin  admin   0 Nov 12 02:12 /proc/1562/exe -> /var/tmp/.cache/kswapd0
0      0      127.0.0.1:45344 127.0.0.1:3333 users:(("kswapd0",pid=1562,fd=3))
0::/system.slice/lab-report.service
0::/system.slice/tart-guest-agent.service

How to read it:

  • load average: 1.83: in this 4-core VM, two processes each use up one core. They started about 90 seconds ago, so the 1-minute average has not reached 2 yet
  • 1550: the executable is /usr/bin/python3.12, and it belongs to lab-report.service. It is a named service that systemd runs
  • 1562: the executable is /var/tmp/.cache/kswapd0. It is connected to port 3333, and its parent is PID 1557. tart-guest-agent.service is the service in this VM that receives tart exec. On a real host, it would show up under an SSH session or cron

The real kswapd0 is a kernel thread. Searching by name shows the difference.

ps -C kswapd0 -o pid,ppid,user,args
Output
    PID    PPID USER     COMMAND
     65       2 root     [kswapd0]
   1562    1557 admin    /var/tmp/.cache/kswapd0 /opt/lab/busy.py 3333

A kernel thread has PID 2 as its parent, and its name is shown in [ ]. A kswapd0 with an executable is an imitation.

The execution record shows how the parent, PID 1557, started.

sudo roamswitch events tree 1562
sudo roamswitch events search --since 1h --exe kswapd0
sudo roamswitch events search --since 1h --pid 1557
Output excerpt
1 /usr/lib/systemd/systemd
697 /usr/bin/tart-guest-agent
878 /usr/bin/dash
1557 /usr/bin/dash
          1562 /var/tmp/.cache/kswapd0 /opt/lab/busy.py 3333
2026-11-12T02:10:55.846Z pid=1562 ppid=1557 admin /var/tmp/.cache/kswapd0 /opt/lab/busy.py 3333
2026-11-12T02:10:55.846Z pid=1557 ppid=878 admin /usr/bin/dash -c while true; do /var/tmp/.cache/kswapd0 /opt/lab/busy.py 3333; sleep 5; done
2026-11-12T02:10:55.845Z pid=1557 ppid=878 admin /usr/bin/setsid sh -c while true; do /var/tmp/.cache/kswapd0 /opt/lab/busy.py 3333; sleep 5; done

Searching with --pid 1557 shows the parent's arguments. It was a shell repeating while true; do /var/tmp/.cache/kswapd0 …; sleep 5; done. Stopping the child is not enough: it starts again 5 seconds later.

Legitimate work, or something planted?

Decide from the alerts and what you found.

  • It belongs to a systemd unit or cron, its executable is where packages install, and you know who owns it: it is most likely legitimate. Choose "limit" in the next chapter
  • Its executable is in /tmp, /var/tmp or /dev/shm, its name imitates a kernel thread or a system process, or mining_port_signature was added: treat it as planted. Keep evidence, then stop it
  • You cannot tell: limit it and wait until you can ask the owner. Stopping it may lose the results of legitimate work

mining_port_signature is added for a TCP connection to port 3333, 4444, 5555, 7777, 9999, 14444, 17777, 19999 or 45560 (the list in the source). Port 8080 is left out, because application servers and upstreams commonly use it. The listed ports can have other uses too. Do not decide on this mark alone; look at the executable's location and the parent as well.

#Stop it or limit it

Legitimate work gets a CPU limit. Something planted is stopped from the parent down, after keeping evidence.

Limit the report, and stop the miner from its parent

This limits and stops processes (it changes the machine). A --runtime limit disappears on reboot.

First, limit the report's lab-report.service to 25% of one core. It is not stopped, so the report keeps running.

sudo systemctl set-property --runtime lab-report.service CPUQuota=25%
systemctl show lab-report.service -p CPUQuotaPerSecUSec
top -b -n 2 -d 3 -p 1550 | tail -2
Output
CPUQuotaPerSecUSec=250ms
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   1550 nobody    20   0   17836  10368   6116 R  25.0   0.3   1:33.48 python3

It dropped to 25.0% right away.

Next, the miner. Before stopping it, keep its executable and arguments. Even if the executable is deleted, it can still be copied from /proc/<PID>/exe.

sudo mkdir -p /root/evidence
sudo cp /proc/1562/exe /root/evidence/kswapd0.bin
sudo sha256sum /root/evidence/kswapd0.bin /usr/bin/python3.12
tr '\0' ' ' < /proc/1562/cmdline; echo
Output
c86f21d0da9290ece2d7d49a3f7ed52aed59cb029abdf0ea25c79634f6cbe960  /root/evidence/kswapd0.bin
c86f21d0da9290ece2d7d49a3f7ed52aed59cb029abdf0ea25c79634f6cbe960  /usr/bin/python3.12
/var/tmp/.cache/kswapd0 /opt/lab/busy.py 3333 

The hash matches python3.12, because this exercise uses a copy of python3. On a real host, record this hash. Now stop only the child.

kill 1562
sleep 6
ps -C kswapd0 -o pid,ppid,user,args
Output
    PID    PPID USER     COMMAND
     65       2 root     [kswapd0]
   2351    1557 admin    /var/tmp/.cache/kswapd0 /opt/lab/busy.py 3333

It came back as PID 2351 under the same parent. Stop the parent first, then the child.

kill 1557
pkill -x kswapd0 -u admin
sleep 6
ps -C kswapd0 -o pid,ppid,user,args
crontab -l
sudo find /etc/systemd/system /etc/cron.d /home/admin/.config/systemd -type f -mmin -30 2>/dev/null
Output
    PID    PPID USER     COMMAND
     65       2 root     [kswapd0]
no crontab for admin

This time it does not come back. No cron or systemd file changed in the last 30 minutes either. On a real host, look for anything that brings it back after a reboot with the steps in Persistence and tampering.

Stopping only the child and calling it done

As shown above, with the parent still alive it came back in 5 seconds. Also avoid reaching for kill -9 first. If the process disappears before you keep its executable and arguments, you can no longer copy it from /proc/<PID>/exe. The order is: record, stop the parent, stop the child, confirm it does not return.

Limit it, or stop it?
  • Legitimate and not urgent: set a CPUQuota= limit and let it keep running. To make it permanent, run set-property without --runtime, or write it into the unit settings
  • Legitimate, but it is starving other services: stop it for now, and start it again after you decide on a time slot or a limit
  • Planted: keep evidence and stop it. Until you have checked the way in (passwords, the web application, keys), treat that user's sessions and keys as suspect

#A service that runs out of memory and keeps crashing

Next, memory. A service with MemoryMax=100M allocates 5 MB every 0.1 seconds. When it reaches the limit, the kernel stops only that service's process. With Restart=always, systemd starts it again 10 seconds later, and it stops again.

Resource exhaustion and crash detection counts this systemd loop from the "Scheduled restart job" lines in the journal. By default it alerts on 3 restarts within 300 seconds (resource_guard_crash_loop_window_secs, resource_guard_crash_loop_min_restarts). The journal is read at each log audit interval (log_audit_interval_secs, default 1800 seconds). With log_audit_enabled=false, this count does not run.

Run a service that keeps hitting its limit, then stop it

This starts and stops a service (it changes the machine).

sudo tee /opt/lab/hog.py >/dev/null <<'PY'
import time
hold = []
while True:
    hold.append(bytearray(5 * 1024 * 1024))
    time.sleep(0.1)
PY
sudo systemd-run --unit=lab-cache -p MemoryMax=100M -p MemorySwapMax=0 -p Restart=always -p RestartSec=10 python3 /opt/lab/hog.py
sleep 30
sudo journalctl -u lab-cache --no-pager | tail -4
Output
Nov 12 02:24:02 ubuntu systemd[1]: lab-cache.service: Scheduled restart job, restart counter is at 2.
Nov 12 02:24:02 ubuntu systemd[1]: Started lab-cache.service - /usr/bin/python3 /opt/lab/hog.py.
Nov 12 02:24:04 ubuntu systemd[1]: lab-cache.service: Main process exited, code=killed, status=9/KILL
Nov 12 02:24:04 ubuntu systemd[1]: lab-cache.service: Failed with result 'signal'.

It stops after 2 seconds and comes back 10 seconds later, over and over. The systemd lines only say it was killed by signal 9 (status=9/KILL). The kernel log, checked below, tells you who killed it. The alert appeared after the next log audit, about 4 and a half minutes after the service started in this VM.

sudo roamswitch notifications | grep -A8 "crash loop"
Output
  [POSSIBLE] Resource Exhaustion Guard: crash loop — lab-cache.service
    ⚠️ The OOM killer keeps stopping the unit's process and it keeps restarting (the unit's memory limit such as MemoryMax, or the host running out of memory; not the shape of an attack. Check the limit and the usage)
    Host: ubuntu (IP: 192.168.64.35)
    Unit/container: lab-cache.service
    Process: unknown (PID: none)
    Restarts in window: 3 (window: 300s)
    Correlated signals: unit_oom_killed
    Timestamp: 2026-11-12 02:28:08

The alert names the unit and has no PID, because the process keeps being replaced. The correlated signal unit_oom_killed means the OOM killer was stopping that unit's process, and the headline itself says it is not the shape of an attack. Confirm it from the unit and the kernel log.

systemctl show lab-cache.service -p NRestarts -p Result
sudo journalctl -k --no-pager | grep "Memory cgroup out of memory" | tail -1
Output
Result=signal
NRestarts=22
Nov 12 02:28:06 ubuntu kernel: Memory cgroup out of memory: Killed process 3056 (python3) total-vm:120116kB, anon-rss:102100kB, file-rss:5936kB, shmem-rss:0kB, UID:0 pgtables:276kB oom_score_adj:0
  • NRestarts=22: it came back 22 times in about 4 and a half minutes. The "3" in the alert is the count at the moment the threshold was reached
  • Memory cgroup out of memory: the kernel stopped it at the limit set on the service (its memory cgroup). The VM as a whole did not run out of memory

Stop it.

sudo systemctl stop lab-cache.service
systemctl is-active lab-cache.service
Output
inactive
How to read a crash loop

The alert's correlated signal and headline are the first clue. With unit_oom_killed, it is a memory limit or a shortage. Without it too, do not decide on the headline alone; use the kernel log to tell the cases apart.

  • Memory cgroup out of memory appears for that unit: it is hitting its limit. Suspect how it uses memory (a leak, a sudden load) or a limit that is too small
  • No Memory cgroup line for that unit, and other processes are being stopped too: suspect competition for the host's memory. Find the large processes with ps -eo pid,rss,args --sort=-rss
  • No memory record, and it exits with code=dumped or status=11/SEGV: it may be crashing on abnormal input. Look at the access logs for that service together with other detections at the same time

After stopping it, prevent a repeat. Keep the limit, and stop the service from coming back endlessly.

Write settings that prevent a repeat, and clean up

This places a unit file (it changes the machine). The end of this lab puts everything back.

StartLimitIntervalSec=300 and StartLimitBurst=3 allow at most 3 starts within 300 seconds.

sudo tee /etc/systemd/system/lab-cache.service >/dev/null <<'UNIT'
[Unit]
Description=lab cache (practice)
StartLimitIntervalSec=300
StartLimitBurst=3

[Service]
ExecStart=/usr/bin/python3 /opt/lab/hog.py
MemoryMax=100M
MemorySwapMax=0
Restart=on-failure
RestartSec=10
UNIT
sudo systemctl daemon-reload
sudo systemctl start lab-cache.service
sleep 50
systemctl show lab-cache.service -p NRestarts -p Result -p ActiveState
sudo journalctl -u lab-cache.service --no-pager --since "-1min" | tail -3
Output
Result=signal
NRestarts=3
ActiveState=failed
Nov 12 02:20:54 ubuntu systemd[1]: lab-cache.service: Start request repeated too quickly.
Nov 12 02:20:54 ubuntu systemd[1]: lab-cache.service: Failed with result 'signal'.
Nov 12 02:20:54 ubuntu systemd[1]: Failed to start lab-cache.service - lab cache (practice).

After 3 restarts, systemd gave up and left it failed. It no longer keeps crashing and using CPU and log space. On a real host, add systemctl --failed to your routine checks so a failed unit is not missed.

Finally, clean up the practice setup and put the settings back to the defaults.

sudo systemctl stop lab-report.service lab-pool.service
sudo rm /etc/systemd/system/lab-cache.service
sudo systemctl daemon-reload
sudo systemctl reset-failed
rm -rf /var/tmp/.cache
sudo rm -rf /opt/lab /root/evidence
sudo roamswitch server config set resource_guard_rss_sample_interval_secs 60
sudo roamswitch server config set resource_guard_cpu_sample_interval_secs 60
sudo roamswitch server config set log_audit_interval_secs 1800
sudo roamswitch server restart
systemctl list-units --all 'lab-*' --no-legend
ps -eo pid,pcpu,args --sort=-pcpu | head -3
Output excerpt
  ✓ Server configuration updated and saved. (resource_guard_rss_sample_interval_secs = 60)
  ✓ Server configuration updated and saved. (resource_guard_cpu_sample_interval_secs = 60)
  ✓ Server configuration updated and saved. (log_audit_interval_secs = 1800)
  🔄 Restarting roamswitch-server service...
  ✓ roamswitch-server service successfully restarted.

    PID %CPU COMMAND
   5332 55.9 /usr/lib/roamswitch/roamswitch-server-daemon
   1502  0.1 /usr/libexec/fwupd/fwupd

No lab- units remain. The top CPU user is the daemon that has just started, followed by fwupd, which checks for firmware updates. The %CPU of ps is an average since the process started, so it reads high right after a start. On a real host, keep the evidence (/root/evidence); do not delete it.

#What this does not show

What was checked, and what was not

Checked on a disposable Ubuntu 24.04 VM (4 cores, 4 GB of memory):

  • Resource exhaustion and crash detection only notifies and records. Stopping a process or limiting it is done by the operator with systemctl or kill
  • The CPU check is per process. A load split across many small processes, none of which reaches 80% of a core, is outside this check. This module did not trigger that shape
  • mining_port_signature comes from a list of port numbers. It is not added for a pool on a port outside the list, or for mining over web port 443
  • Crash loop alerts arrive once per log audit interval. With the default 1800 seconds, an alert can take up to about 30 minutes
  • The trend of the load average and of the zombie count (resource_guard_load_enabled, resource_guard_zombie_min_count) is also watched, per the notes in the settings file. This module did not trigger them
  • When a server really stops responding, SSH becomes slow too. This VM was driven with tart exec. On a real host, check a way in that is not SSH, such as a console, in advance
Check yourself

A [CORRELATED] CPU alert fires. The executable is /dev/shm/.x/sshd, and after kill it comes back a few seconds later under a different PID. What do you do first?

Show the explanation

It comes back because a parent restarts it. Stopping only the child does not end it. Before stopping, copy the executable from /proc/<PID>/exe and record its hash. Raising the threshold also hides the next miner.

Check yourself

A crash loop alert fires. journalctl -k shows repeated Memory cgroup out of memory lines for that unit. How do you read it?

Show the explanation

A Memory cgroup line shows that it stopped at the limit set on the service. The alert's correlated signal is unit_oom_killed too, and its headline says it is not the shape of an attack. Neither a reboot nor isolation is needed. Suspect an attack when there is no memory record and it crashes abnormally (with SEGV and the like).

#Next steps

Features covered

Related techniques (ATT&CK): T1059.004 T1027 T1105 T1553.001

What was verified

Verified on 2026-11-12. Target: Linux 1.17.39. On disposable Ubuntu 24.04 VMs with the published 1.17.39, with shorter sampling intervals, a harmless CPU load, a miner-named copy of python3 and a service crashing at MemoryMax were run in order, and the alerts, timeline, exec record, systemd and kernel output were taken in Japanese and English on separate VMs.

Command output varies with the product version and the environment. If yours differs, check the version first.