在BPF程序中始终获得0会话ID [英] Always get 0 session ID in BPF program
问题描述
我正在尝试编写一个BPF程序,该程序检查调用 tty_write
内核函数的任何进程的会话ID。我试图通过从当前 task_struct
结构中检索一个字段来做到这一点。我的代码如下:
I am trying to write a BPF program that examines the session ID of any process that calls the tty_write
kernel function. I am trying to do this by retrieving a field from the current task_struct
struct. My code is as follows:
SEC("kprobe/tty_write")
int kprobe__tty_write(struct pt_regs *ctx)
{
struct task_struct *task;
struct task_struct *group_leader;
struct pid_link pid_link;
struct pid pid;
int sessionid;
// get current sessionid
task = (struct task_struct *)bpf_get_current_task();
bpf_probe_read(&group_leader, sizeof(group_leader), &task->group_leader);
bpf_probe_read(&pid_link, sizeof(pid_link), group_leader->pids + PIDTYPE_SID);
bpf_probe_read(&pid, sizeof(pid), pid_link.pid);
sessionid = pid.numbers[0].nr;
// do stuff with sessionid
return 0;
}
请注意,我正在使用 clang编译BPF程序
到ELF文件中,并使用 gobpf的 ELF软件包加载。不幸的是, sessionid
的值始终为0。为什么?我认为在使用 bcc 之前,我并没有错误地访问会话ID。一个4.11内核(由于bcc重写BPF程序的方式,当我想自己编译该程序时,我不能简单地使用相同的代码)。用于访问 sessionid
的等效工作密件抄送代码如下。请注意,这仅适用于4.11内核,以下代码不适用于4.13内核。
Note that I am compiling my BPF program using clang
into an ELF file and loading it with gobpf's ELF package. Unfortunately, the value of sessionid
is always 0. Why is this? I don't think I'm accessing the session ID incorrectly as I have done this before using bcc on a 4.11 kernel (due to the how bcc rewrite's BPF programs, I cannot simply use the same code when I want to compile the program myself). The equivalent working bcc code for accessing the sessionid
is as follows. Note that this only works on a 4.11 kernel, the following code did not work on a 4.13 kernel. The code above works on neither kernel however.
#!/usr/bin/python
from bcc import BPF
import ctypes as ct
import os
import threading
import time
import sys
prog=r"""
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/nsproxy.h>
#include <linux/ns_common.h>
#define BUFSIZE 256
struct tty_write_t {
int count;
char buf[BUFSIZE];
unsigned int sessionid;
};
// define maps
BPF_PERF_OUTPUT(tty_writes);
int kprobe__tty_write(struct pt_regs *ctx, struct file *file,
const char __user *buf, size_t count)
{
struct task_struct *task;
struct pid_link pid_link;
struct pid pid;
int sessionid;
// get current sessionid
task = (struct task_struct *)bpf_get_current_task();
bpf_probe_read(&pid_link, sizeof(pid_link), (void *)&task->group_leader->pids[PIDTYPE_SID]);
bpf_probe_read(&pid, sizeof(pid), (void *)pid_link.pid);
sessionid = pid.numbers[0].nr;
// bpf_probe_read() can only use a fixed size, so truncate to count
// in user space:
struct tty_write_t tty_write = {};
bpf_probe_read(&tty_write.buf, BUFSIZE, (void *)buf);
if (count > BUFSIZE) {
tty_write.count = BUFSIZE;
} else {
tty_write.count = count;
}
// add sessionid to tty_write structure and submit
tty_write.sessionid = sessionid;
tty_writes.perf_submit(ctx, &tty_write, sizeof(tty_write));
return 0;
}
"""
b = BPF(text=prog)
BUFSIZE = 256
class TTYWrite(ct.Structure):
_fields_ = [
("count", ct.c_int),
("buf", ct.c_char * BUFSIZE),
("sessionid", ct.c_int)
]
# process tty_write
def print_tty_write(cpu, data, size):
tty_write = ct.cast(data, ct.POINTER(TTYWrite)).contents
print(str(tty_write.sessionid))
b["tty_writes"].open_perf_buffer(print_tty_write)
while 1:
b.kprobe_poll()
4.11内核:
uname -a
:Linux ubuntu16 4.11.0-14-generic#20〜16.04.1-Ubuntu SMP Wed Aug 9 09:06:22 UTC 2017 x86_64 x86_64 x86_64 GNU / Linux
uname -a
:Linux ubuntu16 4.11.0-14-generic #20~16.04.1-Ubuntu SMP Wed Aug 9 09:06:22 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
4.13内核:
uname -a
: Linux ubuntu1710 4.13.0-32-generic#35-Ubuntu SMP Thu Jan 25 09:13:46 UTC 2018 x86_64 x86_64 x86_64 GNU / Linux
uname -a
: Linux ubuntu1710 4.13.0-32-generic #35-Ubuntu SMP Thu Jan 25 09:13:46 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
推荐答案
这是由于我不明白关于如何为特定的内核版本编译BPF程序-我正在使用Docker容器进行编译,该容器安装了针对4.15内核的内核标头,但是试图在4.11内核上运行该程序。
This was due to me not understanding how to compile a BPF program for a specific kernel version - I was compiling using a Docker container with kernel headers installed for the 4.15 kernel, but was trying to run the program on a 4.11 kernel.
要解决此问题,我使用4.11内核标头编译了程序。
To fix this I compiled my program using the 4.11 kernel headers.
这篇关于在BPF程序中始终获得0会话ID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!