Created
September 30, 2020 08:32
-
-
Save mattnite/200973b660920d8ed87642223d03187a to your computer and use it in GitHub Desktop.
opensnoop zig
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: GPL-2.0 | |
// Copyright (c) 2020 Matt Knight | |
// | |
// Base on the opensnoop probe as part of libbpf-tools | |
// Copyright (c) 2019 Facebook | |
// Copyright (c) 2020 Netflix | |
usingnamespace BPF.kern; | |
const std = @import("std"); | |
const BPF = std.os.linux.BPF; | |
const c = @cImport({ | |
@cInclude("linux/version.h"); | |
@cInclude("linux/limits.h"); | |
}); | |
pub const TASK_COMM_LEN = 16; // not available from linux uapi | |
pub const NAME_MAX = c.NAME_MAX; | |
pub const Args = struct { | |
fname: [*:0]const u8, | |
flags: usize, | |
}; | |
pub const Event = struct { | |
ts: u64, | |
pid: u32, | |
uid: u32, | |
ret: isize, | |
flags: usize, | |
comm: [TASK_COMM_LEN]u8, | |
fname: [NAME_MAX]u8, | |
}; | |
pub const PidTidTag = enum { | |
pid, | |
tid, | |
}; | |
pub const PidTidFilter = union(PidTidTag) { | |
pid: i32, | |
tid: i32, | |
}; | |
pub const Config = struct { | |
pid_tid: ?PidTidFilter = null, | |
uid: ?u32 = null, | |
flags: u32 = 0, | |
failed: bool = false, | |
const Self = @This(); | |
pub fn filter(self: *const Self, pid: u32, tid: u32, uid: u32) !void { | |
if (self.pid_tid) |tag| { | |
switch (tag) { | |
.pid => |p| if (p != pid) return error.Filter, | |
.tid => |t| if (t != tid) return error.Filter, | |
} | |
} | |
if (self.uid) |u| { | |
if (u != uid) return error.Filter; | |
} | |
} | |
}; | |
export var config linksection(".rodata") = std.mem.zeroes(Config); | |
export const start linksection(".maps") = HashMap(u32, Args).init(10240, 0); | |
export const events linksection(".maps") = PerfEventArray.init(256, 0); | |
const open_enter = Tracepoint{ | |
.category = "syscalls", | |
.name = "sys_enter_open", | |
}; | |
const open_exit = Tracepoint{ | |
.category = "syscalls", | |
.name = "sys_exit_open", | |
}; | |
const OpenEnterCtx = comptime blk: { | |
@setEvalBranchQuota(10000); | |
break :blk open_enter.Ctx(); | |
}; | |
const OpenExitCtx = comptime blk: { | |
@setEvalBranchQuota(10000); | |
break :blk open_exit.Ctx(); | |
}; | |
fn trace_enter(ctx: *OpenEnterCtx) !void { | |
const id = get_current_pid_tgid(); | |
const tgid = @truncate(u32, id >> 32); | |
const pid = @truncate(u32, id); | |
try config.filter(pid, tgid, @truncate(u32, get_current_uid_gid())); | |
const args = Args{ | |
.fname = @intToPtr([*:0]u8, ctx.filename), | |
.flags = ctx.flags, | |
}; | |
try start.update(.any, pid, args); | |
} | |
fn trace_exit(ctx: *OpenExitCtx) !void { | |
const id = get_current_pid_tgid(); | |
const pid = @truncate(u32, id >> 32); | |
defer start.delete(pid) catch {}; | |
if (config.failed and ctx.ret >= 0) { | |
return; | |
} | |
const args = start.lookup(pid) orelse return error.NotFound; | |
var event = Event{ | |
.ts = ktime_get_ns(), | |
.pid = pid, | |
.uid = @truncate(u32, id), | |
.flags = args.flags, | |
.ret = ctx.ret, | |
.comm = undefined, | |
.fname = undefined, | |
}; | |
try get_current_comm(&event.comm); | |
_ = try probe_read_user_str(&event.fname, args.fname); | |
try events.event_output(ctx, BPF.F_CURRENT_CPU, std.mem.asBytes(&event)); | |
} | |
export fn enter_open(ctx: *OpenEnterCtx) linksection(open_enter.section()) c_int { | |
@call(.{ .modifier = .always_inline }, trace_enter, .{ctx}) catch {}; | |
return 0; | |
} | |
// TODO: openat3 | |
export fn exit_open(ctx: *OpenExitCtx) linksection(open_exit.section()) c_int { | |
@call(.{ .modifier = .always_inline }, trace_exit, .{ctx}) catch {}; | |
return 0; | |
} | |
export const _license linksection(".license") = "GPL"; | |
export const _version linksection(".version") = c.LINUX_VERSION_CODE; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment