ローファイ日記

出てくるコード片、ぼくが書いたものは断りがない場合 MIT License としています http://udzura.mit-license.org/

eBPF的な意味で使えるcgroup idを取る方法

メモ程度に。


追記 @ 2021/04/20 12:41

inode番号と同じになるようになっているらしい。なので、

cgpath = ARGV[0]
puts File::Stat.new(cgpath).ino

これだけでいいです... 以下は、構造体キャストの例として残す。


github.com

この実装によると

struct cgid_file_handle
{
  unsigned int handle_bytes;
  int handle_type;
  uint64_t cgid;
};
  • そうすると handle->cgid に入ってる

という感じっぽい。なので言語を選ばず実装できる。Rubyのようなスクリプト言語ならffi(fiddle)を使ってこういう感じ:

require 'fiddle/import'

module Glibc
  extend Fiddle::Importer
  dlload 'libc.so.6'
  extern 'int name_to_handle_at(int dirfd, const char *pathname, vod *handle, int *mount_id, int flags)'
end

AT_FDCWD = -100 # この値らしい。そうなの...
cgpath = ARGV[0]
handle = Fiddle::Pointer.malloc(16)
handle[0, 16] = [8, 0, 0].pack("I I Q")
mount_id = Fiddle::Pointer.malloc(4)

if Glibc.name_to_handle_at(-100, cgpath, handle, mount_id, 0) < 0
  raise SystemCallError.new Fiddle.last_error
end

cgid = handle[0, 16].unpack("I I Q").last
puts "cgid of #{cgpath}: #{cgid}"

取れてそう。

$ sudo ruby /tmp/getcgid.rb /sys/fs/cgroup/unified/system.slice/docker-af6e1e860a07152351fc3b549479b08f45d0e484564dbbb3330a43d8c7686e94.scope
cgid of /sys/fs/cgroup/unified/system.slice/docker-af6e1e860a07152351fc3b549479b08f45d0e484564dbbb3330a43d8c7686e94.scope: 4863

実際このIDで絞り込んだら、ちゃんとそのコンテナのイベントだけ取れてるみたい。

$ sudo bpftrace -e \
    'tracepoint:syscalls:sys_enter_clone / cgroup == 4863 / { printf("Hola!\n"); } '
Attaching 1 probe...
Hola!
Hola!
...