Class: Vivarium::Daemon

Inherits:
Object
  • Object
show all
Defined in:
lib/vivarium.rb

Constant Summary collapse

BPF_PROGRAM_TEMPLATE =
<<~CLANG
  struct path {
    void *mnt;
    void *dentry;
  };
  struct file {
    char __off[__VIVARIUM_F_PATH_OFFSET__];
    struct path f_path;
  };

  struct event_t {
    u32 pid;
    char event_name[16];
    char payload[#{EVENT_PAYLOAD_SIZE}];
  };

  BPF_HASH(config_root_targets, u32, u8, 1024);
  BPF_HASH(config_spawned_targets, u32, u8, 8192);
  BPF_ARRAY(event_invoked, struct event_t, 1024);
  BPF_ARRAY(event_write_pos, u32, 1);

  static __always_inline int target_enabled(u32 pid, u32 tid)
  {
    u8 *enabled_root = config_root_targets.lookup(&pid);
    if (enabled_root && *enabled_root == 1) {
      return 1;
    }

    u8 *enabled_spawned = config_spawned_targets.lookup(&tid);
    if (enabled_spawned && *enabled_spawned == 1) {
      return 1;
    }

    return 0;
  }

  TRACEPOINT_PROBE(sched, sched_process_fork)
  {
    u32 parent = args->parent_pid;
    u32 child = args->child_pid;
    u8 one = 1;

    u8 *enabled_root = config_root_targets.lookup(&parent);
    if (enabled_root && *enabled_root == 1) {
      config_spawned_targets.update(&child, &one);
      return 0;
    }

    u8 *enabled_spawned = config_spawned_targets.lookup(&parent);
    if (enabled_spawned && *enabled_spawned == 1) {
      config_spawned_targets.update(&child, &one);
    }

    return 0;
  }

  TRACEPOINT_PROBE(sched, sched_process_exit)
  {
    u32 tid = (u32)bpf_get_current_pid_tgid();
    config_spawned_targets.delete(&tid);
    return 0;
  }

  LSM_PROBE(file_open, struct file *file)
  {
    u64 pid_tgid = bpf_get_current_pid_tgid();
    u32 pid = pid_tgid >> 32;
    u32 tid = (u32)pid_tgid;
    bpf_trace_printk("vivarium: invoked pid=%d\\n", pid);
    if (!target_enabled(pid, tid)) {
      return 0;
    }

    u32 zero = 0;
    u32 *write_pos = event_write_pos.lookup(&zero);
    if (!write_pos) {
      return 0;
    }

    u32 idx = *write_pos & 1023;
    __sync_fetch_and_add(write_pos, 1);
    struct event_t ev = {};
    int path_ret;
    ev.pid = pid;
    __builtin_memcpy(ev.event_name, "path_open", 9);

    path_ret = bpf_d_path(&file->f_path, ev.payload, sizeof(ev.payload));
    if (path_ret < 0) {
      if (ev.payload[0] == 0) {
        __builtin_memcpy(ev.payload, "<path_error>", 13);
        bpf_trace_printk("vivarium: failed to obtain full path. pid=%d path=%s\\n", pid, ev.payload);
      }
    }

    bpf_trace_printk("vivarium: pid=%d path=%s\\n", pid, ev.payload);
    event_invoked.update(&idx, &ev);

    return 0;
  }
CLANG

Instance Method Summary collapse

Constructor Details

#initialize(pin_dir: Vivarium.bpf_pin_dir) ⇒ Daemon

Returns a new instance of Daemon.



235
236
237
# File 'lib/vivarium.rb', line 235

def initialize(pin_dir: Vivarium.bpf_pin_dir)
  @pin_dir = pin_dir
end

Instance Method Details

#runObject



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/vivarium.rb', line 239

def run
  ensure_root!
  FileUtils.mkdir_p(@pin_dir)

  f_path_offset = detect_f_path_offset
  program = BPF_PROGRAM_TEMPLATE.gsub("__VIVARIUM_F_PATH_OFFSET__", f_path_offset.to_s)

  bpf = RbBCC::BCC.new(text: program)
  kprint_thread = start_kprint_logger(bpf)

  config_root_targets = bpf["config_root_targets"]
  config_spawned_targets = bpf["config_spawned_targets"]
  event_invoked = bpf["event_invoked"]
  event_write_pos = bpf["event_write_pos"]

  clear_event_slots(event_invoked)
  event_write_pos[0] = 0
  config_spawned_targets.clear

  pin_map(config_root_targets, File.join(@pin_dir, "config_root_targets"))
  pin_map(config_spawned_targets, File.join(@pin_dir, "config_spawned_targets"))
  pin_map(event_invoked, File.join(@pin_dir, "event_invoked"))
  pin_map(event_write_pos, File.join(@pin_dir, "event_write_pos"))

  puts "[vivariumd] started"
  puts "[vivariumd] pinned maps in #{@pin_dir}"
  puts "[vivariumd] watching LSM file_open (f_path offset=#{f_path_offset})"
  puts "[vivariumd] kprint logger enabled"

  loop do
    sleep 1
  end
rescue Interrupt
  puts "\n[vivariumd] stopping"
ensure
  if kprint_thread
    kprint_thread.kill
    kprint_thread.join(0.2)
  end
end