diff --git a/enodia_sentinel/events/bcc_source.py b/enodia_sentinel/events/bcc_source.py index 830a9ee..82cb830 100644 --- a/enodia_sentinel/events/bcc_source.py +++ b/enodia_sentinel/events/bcc_source.py @@ -22,7 +22,7 @@ _BPF_PROGRAM = r""" #include #include -#define ARGLEN 160 +#define ARGLEN 128 struct data_t { u32 pid; @@ -64,6 +64,42 @@ int syscall__execve(struct pt_regs *ctx, """ +def attach_kprobe_candidates(bpf, syscall: str, fn_name: str, + extra: tuple[str, ...] = ()) -> str: + """Attach a kprobe to the first syscall symbol that exists on this kernel.""" + candidates = [] + try: + candidates.append(bpf.get_syscall_fnname(syscall)) + except Exception: + pass + candidates.extend(extra) + candidates.extend([ + f"__x64_sys_{syscall}", + f"__x64_sys_{syscall}at", + f"__arm64_sys_{syscall}", + f"__arm64_sys_{syscall}at", + f"__ia32_sys_{syscall}", + f"__ia32_sys_{syscall}at", + f"__sys_{syscall}", + f"sys_{syscall}", + ]) + seen: set[str] = set() + last_exc: Exception | None = None + for fnname in candidates: + if not fnname or fnname in seen: + continue + seen.add(fnname) + try: + bpf.attach_kprobe(event=fnname, fn_name=fn_name) + return fnname + except Exception as exc: + last_exc = exc + continue + raise RuntimeError( + f"could not attach {syscall} kprobe (tried {', '.join(sorted(seen))})" + ) from last_exc + + def available() -> tuple[bool, str]: """Return (ok, reason). ok=True means the probe can be loaded.""" if os.geteuid() != 0: @@ -91,11 +127,14 @@ class BccExecSource: from bcc import BPF self._bpf = BPF(text=_BPF_PROGRAM) - fnname = self._bpf.get_syscall_fnname("execve") - self._bpf.attach_kprobe(event=fnname, fn_name="syscall__execve") + fnname = self._attach_execve_probe() self._bpf["events"].open_perf_buffer(self._handle, page_cnt=64) self._running = True + def _attach_execve_probe(self) -> str: + assert self._bpf is not None + return attach_kprobe_candidates(self._bpf, "execve", "syscall__execve") + def poll(self, timeout_ms: int = 200) -> None: if self._bpf is not None: self._bpf.perf_buffer_poll(timeout=timeout_ms) diff --git a/enodia_sentinel/events/bcc_syscall_source.py b/enodia_sentinel/events/bcc_syscall_source.py index 5b48a19..44e2eb6 100644 --- a/enodia_sentinel/events/bcc_syscall_source.py +++ b/enodia_sentinel/events/bcc_syscall_source.py @@ -4,7 +4,7 @@ from __future__ import annotations from collections.abc import Callable -from .bcc_source import _decode, available +from .bcc_source import _decode, attach_kprobe_candidates, available from .syscall_event import SyscallEvent _BPF_PROGRAM = r""" @@ -180,8 +180,7 @@ class BccSyscallSource: attached = 0 for syscall, fn_name in _PROBES.items(): try: - event = self._bpf.get_syscall_fnname(syscall) - self._bpf.attach_kprobe(event=event, fn_name=fn_name) + attach_kprobe_candidates(self._bpf, syscall, fn_name) attached += 1 except Exception as exc: self.attach_errors.append(f"{syscall}: {exc!r}")