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 <[email protected]> wrote:
> Hi,
>
> I have resumed work on issue https://github.com/iovisor/bcc/issues/1329.
> I just added the needed fields in this helper structure and also I updated
> the bcc code to use this helper, but I have a couple of questions,
> regarding my implementation.
>
> - Should I be reading /proc/self/ns/pid using vfst_stat?.
> - For Major/Minor I'm not sure if I should be getting the value from
> stat.dev or stat.rdev.
>
> I'm missing to put bcc in a container and replicate the actual issue, but
> I wanted to share what I have at this point and check if I'm in the right
> direction or something else is needed in this same helper.
>
>
> BPF_CALL_2(bpf_get_current_pidns_info, void *, buf, u32, size)
> {
> struct task_struct *ts = current;
> struct task_struct *ns_task = NULL;
> struct pid_namespace *pidns = NULL;
> pid_t pid = 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;
>
> ns_task = find_task_by_pid_ns(pid, pidns);
>
> if (unlikely(!ns_task))
> return -EINVAL;
>
> ((struct bpf_current_pidns_info*)buf)->tgid = (s32)ns_task->tgid;
> ((struct bpf_current_pidns_info*)buf)->pid = (s32) ns_task->pid;
>
> oldsegfs = get_fs();
> set_fs(KERNEL_DS);
> res = vfs_stat((const char __user*)&ppath[0], &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,
> };
>
>
>
>
>
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#1403): https://lists.iovisor.org/g/iovisor-dev/message/1403
Mute This Topic: https://lists.iovisor.org/mt/21386247/21656
Group Owner: [email protected]
Unsubscribe: https://lists.iovisor.org/g/iovisor-dev/unsub
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-