Re: New helper bpf_get_current_pidns_info
Hi All, Just tested the code last night, and it did not work. Now I have fixed it and tested in a container, it's finally working except for the the device major and minor info. Here is the updated code for helper get_current_pidns_info BPF_CALL_2(bpf_get_current_pidns_info, void *, buf, u32, size) { struct task_struct *ts = current; struct pid_namespace *pidns = NULL; pid_t pid = 0; pid_t tgid = 0; int res = 0; const char *ppath = "/proc/self/ns/pid"; mm_segment_t oldsegfs; struct kstat stat; if (unlikely(!ts)) return -EINVAL; pidns = task_active_pid_ns(ts); if (unlikely(!pidns)) return -EINVAL; ((struct bpf_current_pidns_info*)buf)->ns_id = (u64) pidns->ns.inum; pid = task_pid_nr_ns(ts, pidns); if (unlikely(!pid)) return -EINVAL; tgid = task_tgid_nr_ns(ts, pidns); if (unlikely(!tgid)) return -EINVAL; ((struct bpf_current_pidns_info*)buf)->tgid = (s32)tgid; ((struct bpf_current_pidns_info*)buf)->pid = (s32) pid; oldsegfs = get_fs(); set_fs(KERNEL_DS); res = vfs_stat((const char __user*)ppath, &stat); set_fs(oldsegfs); if(unlikely(res)) return -EINVAL; ((struct bpf_current_pidns_info*)buf)->major = (u32) MAJOR(stat.dev); ((struct bpf_current_pidns_info*)buf)->minor = (u32) MINOR(stat.dev); return 0; } const struct bpf_func_proto bpf_get_current_pidns_info_proto = { .func = bpf_get_current_pidns_info, .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_RAW_STACK, .arg2_type = ARG_CONST_STACK_SIZE, }; And a BCC test program #!/usr/bin/python from bcc import BPF from os import getpid import sys, os devinfo= os.lstat('/proc/self/ns/pid'); # Get major and minor device number # define BPF program prog = """ struct nsinfo_t { u64 ns; s32 pid; s32 tgid; s32 major; s32 minor; }; BPF_HASH(nsdata,struct nsinfo_t); int collect_ns(void *ctx) { struct nsinfo_t ns = {}; u64 zero=0, *val; bpf_get_current_pidns_info(&ns,sizeof (ns)); val = nsdata.lookup_or_init(&ns,&zero); (*val)++; return 0; } """ # load BPF program b = BPF(text=prog) b.attach_kprobe(event="sys_read", fn_name="collect_ns") fo = open("./test.py", "r") minor = os.minor(devinfo.st_dev) major = os.major(devinfo.st_dev) pid = getpid(); pidns = os.readlink('/proc/%d/ns/pid' % pid).split('[')[-1][:-1] print ('STARTING: user space pid %s ns %s major %s minor %s' % (pid, pidns, major , minor)) #exit() while 1: try: fo.read(20) nsdata = b.get_table('nsdata'); for k, v in nsdata.items(): if k.pid == pid : print ( 'OK : reading matched pid %s ns %s major %s minor %s' % (k.pid, k.ns, k.major, k.minor )) exit() else: print ( 'MAP: pid %s and ns %s' % (k.pid, k.ns)) except ValueError: continue For testing I created a container using lxd, and copy bcc and kernel modules needed to it, the output of this test inside the container is : root@test:~# ./test.py STARTING: user space pid 403 ns 4026532211 major 0 minor 49 MAP: pid 1569 and ns 4026531836 MAP: pid 935 and ns 4026531836 MAP: pid 1596 and ns 4026531836 OK : reading matched pid 403 ns 4026532211 major 0 minor 3 it also works in root namespace neirac@debian-dev:~$ sudo ./test2.py STARTING: user space pid 1708 ns 4026531836 major 0 minor 4 MAP: pid 1553 and ns 4026531836 OK : reading matched pid 1708 ns 4026531836 major 0 minor 3 But I still I have the following doubts - Should I be reading /proc/self/ns/pid using vfst_stat?. - I'm using the Major/Minor macros but it seems it's not working Am I pointing to the wrong dev_t ?. I'll put the full patch on the github issue for further analysis. Bests On Thu, Jul 26, 2018 at 6:20 PM, cnb <cneirabustos@...> wrote:
|
|