Hi All,

I have applied changes to add thenew helper: bpf_get_current_pidns_info using 
bpf-next branch.
Let me know if what you think.



>From 932f55d885bf34443bb73ec4b24f9dd4b95b64c7 Mon Sep 17 00:00:00 2001
From: cneira <[email protected]>
Date: Fri, 3 Aug 2018 13:36:55 -0400
Subject: [PATCH] BPF: helpers: New helper to obtain namespace data from
 current.

This helper obtains the active namespace from current and returns
pid, tgid, device major/minor and namespace as seen from that ns,
allowing to instrument process inside a container. Major and minor
are obtained from /proc/self/pid, the reason behind is that in the
future, it is possible that different pid_ns files may belong
to different devices according to Eric Biederman as [email protected]
found out in last linux plumbers conference.
---
 include/linux/bpf.h                       |  1 +
 include/uapi/linux/bpf.h                  | 20 +++++++++-
 kernel/bpf/core.c                         |  1 +
 kernel/bpf/helpers.c                      | 65 +++++++++++++++++++++++++++++++
 kernel/trace/bpf_trace.c                  |  2 +
 samples/bpf/Makefile                      |  3 ++
 samples/bpf/trace_ns_info_user.c          | 25 ++++++++++++
 samples/bpf/trace_ns_info_user_kern.c     | 40 +++++++++++++++++++
 tools/include/uapi/linux/bpf.h            |  3 +-
 tools/testing/selftests/bpf/bpf_helpers.h |  3 ++
 10 files changed, 161 insertions(+), 2 deletions(-)
 create mode 100644 samples/bpf/trace_ns_info_user.c
 create mode 100644 samples/bpf/trace_ns_info_user_kern.c

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index cd8790d2c6ed..3f4b999f7c99 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -787,6 +787,7 @@ extern const struct bpf_func_proto bpf_get_stack_proto;
 extern const struct bpf_func_proto bpf_sock_map_update_proto;
 extern const struct bpf_func_proto bpf_sock_hash_update_proto;
 extern const struct bpf_func_proto bpf_get_current_cgroup_id_proto;
+extern const struct bpf_func_proto bpf_get_current_pidns_info_proto;
 
 extern const struct bpf_func_proto bpf_get_local_storage_proto;
 
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index dd5758dc35d3..b53e5c21805a 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -173,6 +173,16 @@ enum bpf_attach_type {
        __MAX_BPF_ATTACH_TYPE
 };
 
+/* helper bpf_get_current_pidns_info will store the following
+ * data, dev will contain major/minor from /proc/self/pid.
+ */
+struct bpf_pidns_info {
+       __u32 dev;
+       __u32 nsid;
+       __u32 tgid;
+       __u32 pid;
+};
+
 #define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
 
 /* cgroup-bpf attach flags used in BPF_PROG_ATTACH command
@@ -2113,7 +2123,14 @@ union bpf_attr {
  *             the shared data.
  *     Return
  *             Pointer to the local storage area.
+ * int bpf_get_current_pidns(struct bpf_pidns_info *pidns, u32 size_of_pidns)
+ *     Description
+ *             Obtains from current task values for pid, namespace, tgid and
+ *             device  major/minor  from /proc/self/ns/pid
+ *     Return
+ *             0 on success -EINVAL on error.
  */
+
 #define __BPF_FUNC_MAPPER(FN)          \
        FN(unspec),                     \
        FN(map_lookup_elem),            \
@@ -2196,7 +2213,8 @@ union bpf_attr {
        FN(rc_keydown),                 \
        FN(skb_cgroup_id),              \
        FN(get_current_cgroup_id),      \
-       FN(get_local_storage),
+       FN(get_local_storage),          \
+       FN(get_current_pidns_info),
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
  * function eBPF program intends to call
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 4d09e610777f..98ce53ce2ea6 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -1796,6 +1796,7 @@ const struct bpf_func_proto bpf_sock_map_update_proto 
__weak;
 const struct bpf_func_proto bpf_sock_hash_update_proto __weak;
 const struct bpf_func_proto bpf_get_current_cgroup_id_proto __weak;
 const struct bpf_func_proto bpf_get_local_storage_proto __weak;
+const struct bpf_func_proto bpf_get_current_pidns_info __weak;
 
 const struct bpf_func_proto * __weak bpf_get_trace_printk_proto(void)
 {
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 1991466b8327..44367a5208b1 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -18,6 +18,9 @@
 #include <linux/sched.h>
 #include <linux/uidgid.h>
 #include <linux/filter.h>
+#include <linux/pid_namespace.h>
+#include <linux/major.h>
+#include <linux/stat.h>
 
 /* If kernel subsystem is allowing eBPF programs to call this function,
  * inside its own verifier_ops->get_func_proto() callback it should return
@@ -214,3 +217,65 @@ const struct bpf_func_proto bpf_get_local_storage_proto = {
        .arg2_type      = ARG_ANYTHING,
 };
 #endif
+
+BPF_CALL_2(bpf_get_current_pidns_info, struct bpf_pidns_info *, pidns_info, 
u32,
+        size)
+{
+       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(!pidns_info))
+               goto error;
+
+       pidns = task_active_pid_ns(current);
+
+       if (unlikely(!pidns))
+               goto error;
+
+       pidns_info->nsid = (u32) pidns->ns.inum;
+
+       pid = task_pid_nr_ns(current, pidns);
+
+       if (unlikely(!pid))
+               goto error;
+
+       tgid = task_tgid_nr_ns(current, pidns);
+
+       if (unlikely(!tgid))
+               goto error;
+
+       pidns_info->tgid = (u32) tgid;
+       pidns_info->pid = (u32) pid;
+
+       oldsegfs = get_fs();
+       set_fs(KERNEL_DS);
+       res = vfs_stat((const char __user *)ppath, &stat);
+       set_fs(oldsegfs);
+
+       if (unlikely(res))
+               goto error;
+
+       pidns_info->dev = (u32) stat.dev;
+
+       return 0;
+
+error:
+       if (pidns_info)
+               memset((void *)pidns, 0, (size_t) size);
+
+       return -EINVAL;
+}
+
+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_UNINIT_MEM,
+       .arg2_type      = ARG_CONST_SIZE,
+};
+
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 0ae6829804bc..f70be29e49ab 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -568,6 +568,8 @@ tracing_func_proto(enum bpf_func_id func_id, const struct 
bpf_prog *prog)
        case BPF_FUNC_get_current_cgroup_id:
                return &bpf_get_current_cgroup_id_proto;
 #endif
+       case BPF_FUNC_get_current_pidns_info:
+               return &bpf_get_current_pidns_info_proto;
        default:
                return NULL;
        }
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index f88d5683d6ee..fdcde00554ce 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -53,6 +53,7 @@ hostprogs-y += xdpsock
 hostprogs-y += xdp_fwd
 hostprogs-y += task_fd_query
 hostprogs-y += xdp_sample_pkts
+hostprogs-y += trace_ns_info
 
 # Libbpf dependencies
 LIBBPF = $(TOOLS_PATH)/lib/bpf/libbpf.a
@@ -109,6 +110,7 @@ xdpsock-objs := xdpsock_user.o
 xdp_fwd-objs := xdp_fwd_user.o
 task_fd_query-objs := bpf_load.o task_fd_query_user.o $(TRACE_HELPERS)
 xdp_sample_pkts-objs := xdp_sample_pkts_user.o $(TRACE_HELPERS)
+trace_ns_info-objs := bpf_load.o trace_ns_info_user.o
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
@@ -166,6 +168,7 @@ always += xdpsock_kern.o
 always += xdp_fwd_kern.o
 always += task_fd_query_kern.o
 always += xdp_sample_pkts_kern.o
+always += trace_ns_info_user_kern.o
 
 HOSTCFLAGS += -I$(objtree)/usr/include
 HOSTCFLAGS += -I$(srctree)/tools/lib/
diff --git a/samples/bpf/trace_ns_info_user.c b/samples/bpf/trace_ns_info_user.c
new file mode 100644
index 000000000000..e5754558a06f
--- /dev/null
+++ b/samples/bpf/trace_ns_info_user.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <linux/bpf.h>
+#include <unistd.h>
+#include "bpf/libbpf.h"
+#include "bpf_load.h"
+
+int main(int ac, char **argv)
+{
+       FILE *f;
+       char filename[256];
+
+       snprintf(filename, sizeof(filename), "%s_user_kern.o", argv[0]);
+       printf("loading %s\n", filename);
+
+
+       if (load_bpf_file(filename)) {
+               printf("%s", bpf_log_buf);
+               return 1;
+       }
+
+       f = popen("taskset 1 ping  localhost", "r");
+       (void) f;
+       read_trace_pipe();
+       return 0;
+}
diff --git a/samples/bpf/trace_ns_info_user_kern.c 
b/samples/bpf/trace_ns_info_user_kern.c
new file mode 100644
index 000000000000..8fa40351eebd
--- /dev/null
+++ b/samples/bpf/trace_ns_info_user_kern.c
@@ -0,0 +1,40 @@
+/* Copyright (c) 2017 [email protected]
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/version.h>
+#include <uapi/linux/bpf.h>
+#include "bpf_helpers.h"
+
+typedef __u64 u64;
+typedef __u32 u32;
+
+
+/* kprobe is NOT a stable ABI
+ * kernel functions can be removed, renamed or completely change semantics.
+ * Number of arguments and their positions can change, etc.
+ * In such case this bpf+kprobe example will no longer be meaningful
+ */
+SEC("kprobe/__netif_receive_skb_core")
+int bpf_prog1(struct pt_regs *ctx)
+{
+       struct bpf_pidns_info nsinfo;
+       int ok = 0;
+
+       ok = bpf_get_current_pidns_info(&nsinfo, sizeof nsinfo);
+       if ( ok == 0 ) {
+       char fmt[] = "nsid:%u, dev: %u,  pid:%u\n";
+
+       bpf_trace_printk(fmt, sizeof(fmt), (u32)nsinfo.nsid, (u32) nsinfo.dev,
+                       (u32)nsinfo.pid);
+       }
+
+       return 0;
+}
+
+char _license[] SEC("license") = "GPL";
+u32 _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index dd5758dc35d3..643174e5fc9e 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -2196,7 +2196,8 @@ union bpf_attr {
        FN(rc_keydown),                 \
        FN(skb_cgroup_id),              \
        FN(get_current_cgroup_id),      \
-       FN(get_local_storage),
+       FN(get_local_storage),          \
+       FN(get_current_pidns_info),
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
  * function eBPF program intends to call
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h 
b/tools/testing/selftests/bpf/bpf_helpers.h
index cb9fcfbc9307..fbc807620839 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -137,6 +137,9 @@ static unsigned long long 
(*bpf_get_current_cgroup_id)(void) =
        (void *) BPF_FUNC_get_current_cgroup_id;
 static void *(*bpf_get_local_storage)(void *map, unsigned long long flags) =
        (void *) BPF_FUNC_get_local_storage;
+static int (*bpf_get_current_pidns_info)(struct bpf_pidns_info* buf,
+                                        unsigned int buf_size) =
+       (void *) BPF_FUNC_get_current_pidns_info;
 
 /* llvm builtin functions that eBPF C program may use to
  * emit BPF_LD_ABS and BPF_LD_IND instructions
-- 
2.11.0


-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#1423): https://lists.iovisor.org/g/iovisor-dev/message/1423
Mute This Topic: https://lists.iovisor.org/mt/24162025/21656
Group Owner: [email protected]
Unsubscribe: https://lists.iovisor.org/g/iovisor-dev/unsub  
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to