3 Commits

6 changed files with 170 additions and 31 deletions

View File

@ -41,14 +41,14 @@ repos:
- id: ruff - id: ruff
args: ["--fix", "--show-fixes"] args: ["--fix", "--show-fixes"]
- id: ruff-format - id: ruff-format
exclude: ^(docs)|^(tests)|^(examples) exclude: ^(tests/|examples/|docs/)
# Checking static types # Checking static types
- repo: https://github.com/pre-commit/mirrors-mypy - repo: https://github.com/pre-commit/mirrors-mypy
rev: "v1.10.0" rev: "v1.10.0"
hooks: hooks:
- id: mypy - id: mypy
exclude: ^(tests)|^(examples) exclude: ^(tests/|examples/)
additional_dependencies: [types-setuptools] additional_dependencies: [types-setuptools]
# Changes tabs to spaces # Changes tabs to spaces

View File

@ -22,9 +22,5 @@ def LICENSE() -> str:
b = BPF() b = BPF()
b.load_and_attach() b.load_and_attach()
if b.is_loaded() and b.is_attached():
print("Successfully loaded and attached")
else:
print("Could not load successfully")
# Now cat /sys/kernel/debug/tracing/trace_pipe to see results of the execve syscall. # Now cat /sys/kernel/debug/tracing/trace_pipe to see results of the execve syscall.

View File

@ -19,6 +19,8 @@ class BPFHelperID(Enum):
BPF_PRINTK = 6 BPF_PRINTK = 6
BPF_GET_CURRENT_PID_TGID = 14 BPF_GET_CURRENT_PID_TGID = 14
BPF_PERF_EVENT_OUTPUT = 25 BPF_PERF_EVENT_OUTPUT = 25
BPF_RINGBUF_RESERVE = 131
BPF_RINGBUF_SUBMIT = 132
@HelperHandlerRegistry.register("ktime") @HelperHandlerRegistry.register("ktime")
@ -180,6 +182,114 @@ def bpf_map_update_elem_emitter(
return result, None return result, None
@HelperHandlerRegistry.register("submit")
def bpf_ringbuf_submit_emitter(
call,
map_ptr,
module,
builder,
func,
local_sym_tab=None,
struct_sym_tab=None,
local_var_metadata=None,
):
"""
Emit LLVM IR for bpf_ringbuf_submit helper function call.
Expected call signature: ringbuf.submit(data, flags=0)
"""
if not call.args or len(call.args) < 1 or len(call.args) > 2:
raise ValueError(
"Ringbuf submit expects 1 or 2 args (data, flags), "
f"got {len(call.args)}"
)
data_arg = call.args[0]
data_ptr = get_or_create_ptr_from_arg(data_arg, builder, local_sym_tab)
# Get flags argument (default to 0)
flags_arg = call.args[1] if len(call.args) > 1 else None
flags_val = get_flags_val(flags_arg, builder, local_sym_tab)
# Returns: void
# Args: (void* data, u64 flags)
fn_type = ir.FunctionType(
ir.VoidType(),
[ir.PointerType(), ir.IntType(64)],
var_arg=False,
)
fn_ptr_type = ir.PointerType(fn_type)
fn_addr = ir.Constant(ir.IntType(64), BPFHelperID.BPF_RINGBUF_SUBMIT.value)
fn_ptr = builder.inttoptr(fn_addr, fn_ptr_type)
if isinstance(flags_val, int):
flags_const = ir.Constant(ir.IntType(64), flags_val)
else:
flags_const = flags_val
builder.call(fn_ptr, [data_ptr, flags_const], tail=True)
return None
@HelperHandlerRegistry.register("reserve")
def bpf_ringbuf_reserve_emitter(
call,
map_ptr,
module,
builder,
func,
local_sym_tab=None,
struct_sym_tab=None,
local_var_metadata=None,
):
"""
Emit LLVM IR for bpf_ringbuf_reserve helper function call.
Expected call signature: ringbuf.reserve(size, flags=0)
"""
if not call.args or len(call.args) < 1 or len(call.args) > 2:
raise ValueError(
"Ringbuf reserve expects 1 or 2 args (size, flags), "
f"got {len(call.args)}"
)
# TODO: here, getting length of stuff does not actually work. need to fix this.
size_arg = call.args[0]
if isinstance(size_arg, ast.Constant):
size_val = ir.Constant(ir.IntType(64), size_arg.value)
elif isinstance(size_arg, ast.Name):
if size_arg.id not in local_sym_tab:
raise ValueError(
f"Variable '{size_arg.id}' not found in local symbol table"
)
size_val = builder.load(local_sym_tab[size_arg.id])
else:
raise NotImplementedError(f"Unsupported size argument type: {type(size_arg)}")
flags_arg = call.args[1] if len(call.args) > 1 else None
flags_val = get_flags_val(flags_arg, builder, local_sym_tab)
map_void_ptr = builder.bitcast(map_ptr, ir.PointerType())
# Args: (void* ringbuf, u64 size, u64 flags)
fn_type = ir.FunctionType(
ir.PointerType(),
[ir.PointerType(), ir.IntType(64), ir.IntType(64)],
var_arg=False,
)
fn_ptr_type = ir.PointerType(fn_type)
fn_addr = ir.Constant(ir.IntType(64), BPFHelperID.BPF_RINGBUF_RESERVE.value)
fn_ptr = builder.inttoptr(fn_addr, fn_ptr_type)
if isinstance(flags_val, int):
flags_const = ir.Constant(ir.IntType(64), flags_val)
else:
flags_const = flags_val
result = builder.call(fn_ptr, [map_void_ptr, size_val, flags_const], tail=True)
return result, ir.PointerType()
@HelperHandlerRegistry.register("delete") @HelperHandlerRegistry.register("delete")
def bpf_map_delete_elem_emitter( def bpf_map_delete_elem_emitter(

View File

@ -22,27 +22,29 @@ struct {
SEC("tracepoint/syscalls/sys_enter_execve") SEC("tracepoint/syscalls/sys_enter_execve")
int trace_execve(void *ctx) int trace_execve(void *ctx)
{ {
struct event *e; // struct event *e;
__u64 pid_tgid; // __u64 pid_tgid;
__u64 uid_gid; // __u64 uid_gid;
__u32 *e;
// Reserve space in the ringbuffer // Reserve space in the ringbuffer
e = bpf_ringbuf_reserve(&events, sizeof(*e), 0); e = bpf_ringbuf_reserve(&events, sizeof(*e), 0);
if (!e) if (!e)
return 0; return 0;
//
// // Fill the struct with data
// pid_tgid = bpf_get_current_pid_tgid();
// e->pid = pid_tgid >> 32;
//
// uid_gid = bpf_get_current_uid_gid();
// e->uid = uid_gid & 0xFFFFFFFF;
//
// e->timestamp = bpf_ktime_get_ns();
// Fill the struct with data // bpf_get_current_comm(&e->comm, sizeof(e->comm));
pid_tgid = bpf_get_current_pid_tgid(); //
e->pid = pid_tgid >> 32; // // Submit the event to ringbuffer
__u32 temp = 32;
uid_gid = bpf_get_current_uid_gid(); e = &temp;
e->uid = uid_gid & 0xFFFFFFFF;
e->timestamp = bpf_ktime_get_ns();
bpf_get_current_comm(&e->comm, sizeof(e->comm));
// Submit the event to ringbuffer
bpf_ringbuf_submit(e, 0); bpf_ringbuf_submit(e, 0);
return 0; return 0;

View File

@ -0,0 +1,33 @@
from pythonbpf import bpf, map, bpfglobal, section, compile, compile_to_ir, BPF
from pythonbpf.maps import RingBuf
from ctypes import c_int32, c_void_p
# Define a map
@bpf
@map
def mymap() -> RingBuf:
return RingBuf(max_entries=(1024))
@bpf
@section("tracepoint/syscalls/sys_enter_clone")
def random_section(ctx: c_void_p) -> c_int32:
e: c_int32 = mymap().reserve(64)
if e == 0: # here is the issue i think
return c_int32(0)
mymap().submit(e)
return c_int32(0)
@bpf
@bpfglobal
def LICENSE() -> str:
return "GPL"
compile_to_ir("ringbuf.py", "ringbuf.ll")
compile()
b = BPF()
b.load_and_attach()
while True:
print("running")

View File

@ -1,5 +1,5 @@
from pythonbpf import bpf, BPF, map, bpfglobal, section, compile, compile_to_ir from pythonbpf import bpf, map, bpfglobal, section, compile, compile_to_ir, BPF
from pythonbpf.maps import RingBuf, HashMap from pythonbpf.maps import RingBuf
from ctypes import c_int32, c_void_p from ctypes import c_int32, c_void_p
@ -9,17 +9,13 @@ from ctypes import c_int32, c_void_p
def mymap() -> RingBuf: def mymap() -> RingBuf:
return RingBuf(max_entries=(1024)) return RingBuf(max_entries=(1024))
@bpf
@map
def mymap2() -> HashMap:
return HashMap(key=c_int32, value=c_int32, max_entries=1024)
@bpf @bpf
@section("tracepoint/syscalls/sys_enter_clone") @section("tracepoint/syscalls/sys_enter_clone")
def random_section(ctx: c_void_p) -> c_int32: def random_section(ctx: c_void_p) -> c_int32:
print("Hello") print("Hello")
e = mymap().reserve(6)
if e:
mymap().submit(e)
return c_int32(0) return c_int32(0)
@ -33,3 +29,5 @@ compile_to_ir("ringbuf.py", "ringbuf.ll")
compile() compile()
b = BPF() b = BPF()
b.load_and_attach() b.load_and_attach()
while True:
print("running")