8 Commits

6 changed files with 86 additions and 51 deletions

View File

@ -1,34 +1,47 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include <linux/bpf.h> #include <linux/bpf.h>
#include <bpf/bpf_helpers.h> #include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h> #include <bpf/bpf_tracing.h>
struct trace_entry {
short unsigned int type;
unsigned char flags;
unsigned char preempt_count;
int pid;
};
struct trace_event_raw_sys_enter {
struct trace_entry ent;
long int id;
long unsigned int args[6];
char __data[0];
};
struct event { struct event {
__u32 pid; __u32 pid;
__u32 uid; __u32 uid;
__u64 ts; __u64 ts;
}; };
struct { struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
__uint(key_size, sizeof(int)); __uint(key_size, sizeof(int));
__uint(value_size, sizeof(int)); __uint(value_size, sizeof(int));
} events SEC(".maps"); } events SEC(".maps");
SEC("tp/syscalls/sys_enter_setuid") SEC("tp/syscalls/sys_enter_setuid")
int handle_setuid_entry(struct trace_event_raw_sys_enter *ctx) int handle_setuid_entry(struct trace_event_raw_sys_enter *ctx) {
{ struct event data = {};
struct event data = {};
// Extract UID from the syscall arguments // Extract UID from the syscall arguments
data.uid = (unsigned int)ctx->args[0]; data.uid = (unsigned int)ctx->args[0];
data.ts = bpf_ktime_get_ns(); data.ts = bpf_ktime_get_ns();
data.pid = bpf_get_current_pid_tgid() >> 32; data.pid = bpf_get_current_pid_tgid() >> 32;
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &data, sizeof(data)); bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &data, sizeof(data));
return 0; return 0;
} }
char LICENSE[] SEC("license") = "GPL"; char LICENSE[] SEC("license") = "GPL";

View File

@ -21,6 +21,7 @@ def events() -> PerfEventArray:
@bpf @bpf
@section("tracepoint/syscalls/sys_enter_clone") @section("tracepoint/syscalls/sys_enter_clone")
def hello(ctx: c_void_p) -> c_int32: def hello(ctx: c_void_p) -> c_int32:
strobj = "Hi"
dataobj = data_t() dataobj = data_t()
ts = ktime() ts = ktime()
process_id = pid() process_id = pid()

View File

@ -15,6 +15,7 @@ def recursive_dereferencer(var, builder):
else: else:
raise TypeError(f"Unsupported type for dereferencing: {var.type}") raise TypeError(f"Unsupported type for dereferencing: {var.type}")
def handle_binary_op(rval, module, builder, var_name, local_sym_tab, map_sym_tab, func): def handle_binary_op(rval, module, builder, var_name, local_sym_tab, map_sym_tab, func):
print(module) print(module)
left = rval.left left = rval.left
@ -24,7 +25,7 @@ def handle_binary_op(rval, module, builder, var_name, local_sym_tab, map_sym_tab
# Handle left operand # Handle left operand
if isinstance(left, ast.Name): if isinstance(left, ast.Name):
if left.id in local_sym_tab: if left.id in local_sym_tab:
left = recursive_dereferencer(local_sym_tab[left.id], builder) left = recursive_dereferencer(local_sym_tab[left.id][0], builder)
else: else:
raise SyntaxError(f"Undefined variable: {left.id}") raise SyntaxError(f"Undefined variable: {left.id}")
elif isinstance(left, ast.Constant): elif isinstance(left, ast.Constant):
@ -34,7 +35,7 @@ def handle_binary_op(rval, module, builder, var_name, local_sym_tab, map_sym_tab
if isinstance(right, ast.Name): if isinstance(right, ast.Name):
if right.id in local_sym_tab: if right.id in local_sym_tab:
right = recursive_dereferencer(local_sym_tab[right.id], builder) right = recursive_dereferencer(local_sym_tab[right.id][0], builder)
else: else:
raise SyntaxError(f"Undefined variable: {right.id}") raise SyntaxError(f"Undefined variable: {right.id}")
elif isinstance(right, ast.Constant): elif isinstance(right, ast.Constant):
@ -46,36 +47,36 @@ def handle_binary_op(rval, module, builder, var_name, local_sym_tab, map_sym_tab
if isinstance(op, ast.Add): if isinstance(op, ast.Add):
builder.store(builder.add(left, right), builder.store(builder.add(left, right),
local_sym_tab[var_name]) local_sym_tab[var_name][0])
elif isinstance(op, ast.Sub): elif isinstance(op, ast.Sub):
builder.store(builder.sub(left, right), builder.store(builder.sub(left, right),
local_sym_tab[var_name]) local_sym_tab[var_name][0])
elif isinstance(op, ast.Mult): elif isinstance(op, ast.Mult):
builder.store(builder.mul(left, right), builder.store(builder.mul(left, right),
local_sym_tab[var_name]) local_sym_tab[var_name][0])
elif isinstance(op, ast.Div): elif isinstance(op, ast.Div):
builder.store(builder.sdiv(left, right), builder.store(builder.sdiv(left, right),
local_sym_tab[var_name]) local_sym_tab[var_name][0])
elif isinstance(op, ast.Mod): elif isinstance(op, ast.Mod):
builder.store(builder.srem(left, right), builder.store(builder.srem(left, right),
local_sym_tab[var_name]) local_sym_tab[var_name][0])
elif isinstance(op, ast.LShift): elif isinstance(op, ast.LShift):
builder.store(builder.shl(left, right), builder.store(builder.shl(left, right),
local_sym_tab[var_name]) local_sym_tab[var_name][0])
elif isinstance(op, ast.RShift): elif isinstance(op, ast.RShift):
builder.store(builder.lshr(left, right), builder.store(builder.lshr(left, right),
local_sym_tab[var_name]) local_sym_tab[var_name][0])
elif isinstance(op, ast.BitOr): elif isinstance(op, ast.BitOr):
builder.store(builder.or_(left, right), builder.store(builder.or_(left, right),
local_sym_tab[var_name]) local_sym_tab[var_name][0])
elif isinstance(op, ast.BitXor): elif isinstance(op, ast.BitXor):
builder.store(builder.xor(left, right), builder.store(builder.xor(left, right),
local_sym_tab[var_name]) local_sym_tab[var_name][0])
elif isinstance(op, ast.BitAnd): elif isinstance(op, ast.BitAnd):
builder.store(builder.and_(left, right), builder.store(builder.and_(left, right),
local_sym_tab[var_name]) local_sym_tab[var_name][0])
elif isinstance(op, ast.FloorDiv): elif isinstance(op, ast.FloorDiv):
builder.store(builder.udiv(left, right), builder.store(builder.udiv(left, right),
local_sym_tab[var_name]) local_sym_tab[var_name][0])
else: else:
raise SyntaxError("Unsupported binary operation") raise SyntaxError("Unsupported binary operation")

View File

@ -27,7 +27,7 @@ def bpf_map_lookup_elem_emitter(call, map_ptr, module, builder, func, local_sym_
if isinstance(key_arg, ast.Name): if isinstance(key_arg, ast.Name):
key_name = key_arg.id key_name = key_arg.id
if local_sym_tab and key_name in local_sym_tab: if local_sym_tab and key_name in local_sym_tab:
key_ptr = local_sym_tab[key_name] key_ptr = local_sym_tab[key_name][0]
else: else:
raise ValueError( raise ValueError(
f"Key variable {key_name} not found in local symbol table.") f"Key variable {key_name} not found in local symbol table.")
@ -85,6 +85,7 @@ def bpf_printk_emitter(call, map_ptr, module, builder, func, local_sym_tab=None,
raise NotImplementedError( raise NotImplementedError(
"Only string and integer constants are supported in f-string.") "Only string and integer constants are supported in f-string.")
elif isinstance(value, ast.FormattedValue): elif isinstance(value, ast.FormattedValue):
print("Formatted value:", ast.dump(value))
# Assume int for now # Assume int for now
fmt_parts.append("%lld") fmt_parts.append("%lld")
if isinstance(value.value, ast.Name): if isinstance(value.value, ast.Name):
@ -189,7 +190,7 @@ def bpf_map_update_elem_emitter(call, map_ptr, module, builder, func, local_sym_
if isinstance(key_arg, ast.Name): if isinstance(key_arg, ast.Name):
key_name = key_arg.id key_name = key_arg.id
if local_sym_tab and key_name in local_sym_tab: if local_sym_tab and key_name in local_sym_tab:
key_ptr = local_sym_tab[key_name] key_ptr = local_sym_tab[key_name][0]
else: else:
raise ValueError( raise ValueError(
f"Key variable {key_name} not found in local symbol table.") f"Key variable {key_name} not found in local symbol table.")
@ -208,7 +209,7 @@ def bpf_map_update_elem_emitter(call, map_ptr, module, builder, func, local_sym_
if isinstance(value_arg, ast.Name): if isinstance(value_arg, ast.Name):
value_name = value_arg.id value_name = value_arg.id
if local_sym_tab and value_name in local_sym_tab: if local_sym_tab and value_name in local_sym_tab:
value_ptr = local_sym_tab[value_name] value_ptr = local_sym_tab[value_name][0]
else: else:
raise ValueError( raise ValueError(
f"Value variable {value_name} not found in local symbol table.") f"Value variable {value_name} not found in local symbol table.")
@ -231,7 +232,7 @@ def bpf_map_update_elem_emitter(call, map_ptr, module, builder, func, local_sym_
flags_name = flags_arg.id flags_name = flags_arg.id
if local_sym_tab and flags_name in local_sym_tab: if local_sym_tab and flags_name in local_sym_tab:
# Assume it's a stored integer value, load it # Assume it's a stored integer value, load it
flags_ptr = local_sym_tab[flags_name] flags_ptr = local_sym_tab[flags_name][0]
flags_val = builder.load(flags_ptr) flags_val = builder.load(flags_ptr)
else: else:
raise ValueError( raise ValueError(
@ -284,7 +285,7 @@ def bpf_map_delete_elem_emitter(call, map_ptr, module, builder, func, local_sym_
if isinstance(key_arg, ast.Name): if isinstance(key_arg, ast.Name):
key_name = key_arg.id key_name = key_arg.id
if local_sym_tab and key_name in local_sym_tab: if local_sym_tab and key_name in local_sym_tab:
key_ptr = local_sym_tab[key_name] key_ptr = local_sym_tab[key_name][0]
else: else:
raise ValueError( raise ValueError(
f"Key variable {key_name} not found in local symbol table.") f"Key variable {key_name} not found in local symbol table.")
@ -350,7 +351,7 @@ def bpf_perf_event_output_handler(call, map_ptr, module, builder, func, local_sy
if isinstance(data_arg, ast.Name): if isinstance(data_arg, ast.Name):
data_name = data_arg.id data_name = data_arg.id
if local_sym_tab and data_name in local_sym_tab: if local_sym_tab and data_name in local_sym_tab:
data_ptr = local_sym_tab[data_name] data_ptr = local_sym_tab[data_name][0]
else: else:
raise ValueError( raise ValueError(
f"Data variable {data_name} not found in local symbol table.") f"Data variable {data_name} not found in local symbol table.")

View File

@ -6,7 +6,7 @@ def eval_expr(func, module, builder, expr, local_sym_tab, map_sym_tab, structs_s
print(f"Evaluating expression: {expr}") print(f"Evaluating expression: {expr}")
if isinstance(expr, ast.Name): if isinstance(expr, ast.Name):
if expr.id in local_sym_tab: if expr.id in local_sym_tab:
var = local_sym_tab[expr.id] var = local_sym_tab[expr.id][0]
val = builder.load(var) val = builder.load(var)
return val return val
else: else:
@ -37,7 +37,7 @@ def eval_expr(func, module, builder, expr, local_sym_tab, map_sym_tab, structs_s
return None return None
if isinstance(arg, ast.Name): if isinstance(arg, ast.Name):
if arg.id in local_sym_tab: if arg.id in local_sym_tab:
arg = local_sym_tab[arg.id] arg = local_sym_tab[arg.id][0]
else: else:
print(f"Undefined variable {arg.id}") print(f"Undefined variable {arg.id}")
return None return None

View File

@ -51,7 +51,7 @@ def handle_assign(func, module, builder, stmt, map_sym_tab, local_sym_tab, struc
if field_name in struct_info["fields"]: if field_name in struct_info["fields"]:
field_idx = struct_info["fields"][field_name] field_idx = struct_info["fields"][field_name]
struct_ptr = local_sym_tab[var_name] struct_ptr = local_sym_tab[var_name][0]
field_ptr = builder.gep( field_ptr = builder.gep(
struct_ptr, [ir.Constant(ir.IntType(32), 0), struct_ptr, [ir.Constant(ir.IntType(32), 0),
ir.Constant(ir.IntType(32), field_idx)], ir.Constant(ir.IntType(32), field_idx)],
@ -68,19 +68,32 @@ def handle_assign(func, module, builder, stmt, map_sym_tab, local_sym_tab, struc
if isinstance(rval.value, bool): if isinstance(rval.value, bool):
if rval.value: if rval.value:
builder.store(ir.Constant(ir.IntType(1), 1), builder.store(ir.Constant(ir.IntType(1), 1),
local_sym_tab[var_name]) local_sym_tab[var_name][0])
else: else:
builder.store(ir.Constant(ir.IntType(1), 0), builder.store(ir.Constant(ir.IntType(1), 0),
local_sym_tab[var_name]) local_sym_tab[var_name][0])
print(f"Assigned constant {rval.value} to {var_name}") print(f"Assigned constant {rval.value} to {var_name}")
elif isinstance(rval.value, int): elif isinstance(rval.value, int):
# Assume c_int64 for now # Assume c_int64 for now
# var = builder.alloca(ir.IntType(64), name=var_name) # var = builder.alloca(ir.IntType(64), name=var_name)
# var.align = 8 # var.align = 8
builder.store(ir.Constant(ir.IntType(64), rval.value), builder.store(ir.Constant(ir.IntType(64), rval.value),
local_sym_tab[var_name]) local_sym_tab[var_name][0])
# local_sym_tab[var_name] = var # local_sym_tab[var_name] = var
print(f"Assigned constant {rval.value} to {var_name}") print(f"Assigned constant {rval.value} to {var_name}")
elif isinstance(rval.value, str):
str_val = rval.value.encode('utf-8') + b'\x00'
str_const = ir.Constant(ir.ArrayType(
ir.IntType(8), len(str_val)), bytearray(str_val))
global_str = ir.GlobalVariable(
module, str_const.type, name=f"{var_name}_str")
global_str.linkage = 'internal'
global_str.global_constant = True
global_str.initializer = str_const
str_ptr = builder.bitcast(
global_str, ir.PointerType(ir.IntType(8)))
builder.store(str_ptr, local_sym_tab[var_name][0])
print(f"Assigned string constant '{rval.value}' to {var_name}")
else: else:
print("Unsupported constant type") print("Unsupported constant type")
elif isinstance(rval, ast.Call): elif isinstance(rval, ast.Call):
@ -92,7 +105,7 @@ def handle_assign(func, module, builder, stmt, map_sym_tab, local_sym_tab, struc
# var = builder.alloca(ir_type, name=var_name) # var = builder.alloca(ir_type, name=var_name)
# var.align = ir_type.width // 8 # var.align = ir_type.width // 8
builder.store(ir.Constant( builder.store(ir.Constant(
ir_type, rval.args[0].value), local_sym_tab[var_name]) ir_type, rval.args[0].value), local_sym_tab[var_name][0])
print(f"Assigned {call_type} constant " print(f"Assigned {call_type} constant "
f"{rval.args[0].value} to {var_name}") f"{rval.args[0].value} to {var_name}")
# local_sym_tab[var_name] = var # local_sym_tab[var_name] = var
@ -101,7 +114,7 @@ def handle_assign(func, module, builder, stmt, map_sym_tab, local_sym_tab, struc
# var.align = 8 # var.align = 8
val = handle_helper_call( val = handle_helper_call(
rval, module, builder, func, local_sym_tab, map_sym_tab, structs_sym_tab, local_var_metadata) rval, module, builder, func, local_sym_tab, map_sym_tab, structs_sym_tab, local_var_metadata)
builder.store(val, local_sym_tab[var_name]) builder.store(val, local_sym_tab[var_name][0])
# local_sym_tab[var_name] = var # local_sym_tab[var_name] = var
print(f"Assigned constant {rval.func.id} to {var_name}") print(f"Assigned constant {rval.func.id} to {var_name}")
elif call_type == "deref" and len(rval.args) == 1: elif call_type == "deref" and len(rval.args) == 1:
@ -112,7 +125,7 @@ def handle_assign(func, module, builder, stmt, map_sym_tab, local_sym_tab, struc
print("Failed to evaluate deref argument") print("Failed to evaluate deref argument")
return return
print(f"Dereferenced value: {val}, storing in {var_name}") print(f"Dereferenced value: {val}, storing in {var_name}")
builder.store(val, local_sym_tab[var_name]) builder.store(val, local_sym_tab[var_name][0])
# local_sym_tab[var_name] = var # local_sym_tab[var_name] = var
print(f"Dereferenced and assigned to {var_name}") print(f"Dereferenced and assigned to {var_name}")
elif call_type in structs_sym_tab and len(rval.args) == 0: elif call_type in structs_sym_tab and len(rval.args) == 0:
@ -121,7 +134,7 @@ def handle_assign(func, module, builder, stmt, map_sym_tab, local_sym_tab, struc
# var = builder.alloca(ir_type, name=var_name) # var = builder.alloca(ir_type, name=var_name)
# Null init # Null init
builder.store(ir.Constant(ir_type, None), builder.store(ir.Constant(ir_type, None),
local_sym_tab[var_name]) local_sym_tab[var_name][0])
local_var_metadata[var_name] = call_type local_var_metadata[var_name] = call_type
print(f"Assigned struct {call_type} to {var_name}") print(f"Assigned struct {call_type} to {var_name}")
# local_sym_tab[var_name] = var # local_sym_tab[var_name] = var
@ -142,7 +155,7 @@ def handle_assign(func, module, builder, stmt, map_sym_tab, local_sym_tab, struc
rval, module, builder, func, local_sym_tab, map_sym_tab, structs_sym_tab, local_var_metadata) rval, module, builder, func, local_sym_tab, map_sym_tab, structs_sym_tab, local_var_metadata)
# var = builder.alloca(ir.IntType(64), name=var_name) # var = builder.alloca(ir.IntType(64), name=var_name)
# var.align = 8 # var.align = 8
builder.store(val, local_sym_tab[var_name]) builder.store(val, local_sym_tab[var_name][0])
# local_sym_tab[var_name] = var # local_sym_tab[var_name] = var
else: else:
print("Unsupported assignment call structure") print("Unsupported assignment call structure")
@ -166,7 +179,7 @@ def handle_cond(func, module, builder, cond, local_sym_tab, map_sym_tab):
return None return None
elif isinstance(cond, ast.Name): elif isinstance(cond, ast.Name):
if cond.id in local_sym_tab: if cond.id in local_sym_tab:
var = local_sym_tab[cond.id] var = local_sym_tab[cond.id][0]
val = builder.load(var) val = builder.load(var)
if val.type != ir.IntType(1): if val.type != ir.IntType(1):
# Convert nonzero values to true, zero to false # Convert nonzero values to true, zero to false
@ -370,8 +383,14 @@ def allocate_mem(module, builder, body, func, ret_type, map_sym_tab, local_sym_t
var.align = ir_type.width // 8 var.align = ir_type.width // 8
print( print(
f"Pre-allocated variable {var_name} of type c_int64") f"Pre-allocated variable {var_name} of type c_int64")
elif isinstance(rval.value, str):
ir_type = ir.PointerType(ir.IntType(8))
var = builder.alloca(ir_type, name=var_name)
var.align = 8
print(
f"Pre-allocated variable {var_name} of type string")
else: else:
print("Unsupported constant type") print(f"Unsupported constant type")
continue continue
elif isinstance(rval, ast.BinOp): elif isinstance(rval, ast.BinOp):
# Assume c_int64 for now # Assume c_int64 for now
@ -383,7 +402,7 @@ def allocate_mem(module, builder, body, func, ret_type, map_sym_tab, local_sym_t
else: else:
print("Unsupported assignment value type") print("Unsupported assignment value type")
continue continue
local_sym_tab[var_name] = var local_sym_tab[var_name] = (var, ir_type)
return local_sym_tab return local_sym_tab