文字列処理の追加
第690回ではPIDとPPIDだけでなく,execve()
を呼び出したプログラム名
まずexecsnoop.
にデータ送受信用のメンバーであるcomm
とfname
を追加します。今回は単なる固定長の文字列です。comm
のほうはカーネルのタスク構造体に合わせたサイズにし,fname
のほうは適当な長さに決めました。
#define TASK_COMM_LEN 16 /* from linux/sched.h */
struct event {
pid_t pid;
pid_t ppid;
char comm[TASK_COMM_LEN];
char fname[32];
};
BPFプログラムであるexecsnoop.
は,
int syscalls__execve(struct trace_event_raw_sys_enter *ctx)
(中略)
if (bpf_get_current_comm(&event->comm, sizeof(event->comm)) < 0)
goto err;
if (bpf_core_read_user_str(event->fname, sizeof(event->fname), (const char*)ctx->args[0]) < 0)
goto err;
bpf_ringbuf_submit(event, 0);
return 0;
err:
bpf_ringbuf_discard(event, 0);
return 0;
bpf_
はBCCでも使っていたAPIがそのまま使えます。bpf_
は初出ですが,bpf_
と同じで,_str
」ctx->args[0]
」execve()
の第一引数という意味です。
- ※2
bpf_
は内部でcore_ read_ user_ str() bpf_
を呼び出しています。probe_ read_ user_ str()
どちらのAPIも失敗時には負の値が返ってきます。そこでその際は何もせずに確保したバッファーをbpf_
だけの処理にしました。
ユーザーランドプログラムであるexecsnoop.
のほうは,
/* データの出力側 */
fprintf(stdout, "% 8d % 8d %-16s %-32s\n", event->pid, event->ppid, event->comm, event->fname);
/* 実行時に最初に表示されるヘッダー */
fprintf(stdout, "%-8s %-8s %-16s %-32s\n", "PID", "PPID", "COMM", "FNAME");
このあたりは好みに合わせて調整してください。毎度のことながら,v1.
タグを付けています。
$ git checkout r695/4 v1.4 $ make $ sudo ./execsnoop PID PPID COMM FNAME 547716 2276 tmux: server /bin/sh 547717 547716 sh /usr/bin/byobu-status 547718 2276 tmux: server /bin/sh 547719 547717 byobu-status /usr/bin/sed 547720 547718 sh /usr/bin/byobu-status
これでほぼBCC/