Harden BCC syscall probe attachment
This commit is contained in:
parent
2d23e8b878
commit
93ac47dd82
2 changed files with 44 additions and 6 deletions
|
|
@ -22,7 +22,7 @@ _BPF_PROGRAM = r"""
|
||||||
#include <uapi/linux/ptrace.h>
|
#include <uapi/linux/ptrace.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
|
||||||
#define ARGLEN 160
|
#define ARGLEN 128
|
||||||
|
|
||||||
struct data_t {
|
struct data_t {
|
||||||
u32 pid;
|
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]:
|
def available() -> tuple[bool, str]:
|
||||||
"""Return (ok, reason). ok=True means the probe can be loaded."""
|
"""Return (ok, reason). ok=True means the probe can be loaded."""
|
||||||
if os.geteuid() != 0:
|
if os.geteuid() != 0:
|
||||||
|
|
@ -91,11 +127,14 @@ class BccExecSource:
|
||||||
from bcc import BPF
|
from bcc import BPF
|
||||||
|
|
||||||
self._bpf = BPF(text=_BPF_PROGRAM)
|
self._bpf = BPF(text=_BPF_PROGRAM)
|
||||||
fnname = self._bpf.get_syscall_fnname("execve")
|
fnname = self._attach_execve_probe()
|
||||||
self._bpf.attach_kprobe(event=fnname, fn_name="syscall__execve")
|
|
||||||
self._bpf["events"].open_perf_buffer(self._handle, page_cnt=64)
|
self._bpf["events"].open_perf_buffer(self._handle, page_cnt=64)
|
||||||
self._running = True
|
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:
|
def poll(self, timeout_ms: int = 200) -> None:
|
||||||
if self._bpf is not None:
|
if self._bpf is not None:
|
||||||
self._bpf.perf_buffer_poll(timeout=timeout_ms)
|
self._bpf.perf_buffer_poll(timeout=timeout_ms)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Callable
|
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
|
from .syscall_event import SyscallEvent
|
||||||
|
|
||||||
_BPF_PROGRAM = r"""
|
_BPF_PROGRAM = r"""
|
||||||
|
|
@ -180,8 +180,7 @@ class BccSyscallSource:
|
||||||
attached = 0
|
attached = 0
|
||||||
for syscall, fn_name in _PROBES.items():
|
for syscall, fn_name in _PROBES.items():
|
||||||
try:
|
try:
|
||||||
event = self._bpf.get_syscall_fnname(syscall)
|
attach_kprobe_candidates(self._bpf, syscall, fn_name)
|
||||||
self._bpf.attach_kprobe(event=event, fn_name=fn_name)
|
|
||||||
attached += 1
|
attached += 1
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
self.attach_errors.append(f"{syscall}: {exc!r}")
|
self.attach_errors.append(f"{syscall}: {exc!r}")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue