bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V12 0/4] BPF: New helper to obtain namespace data from current task
@ 2019-10-01 21:41 Carlos Neira
  2019-10-01 21:41 ` [PATCH V12 1/4] fs/nsfs.c: added ns_match Carlos Neira
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Carlos Neira @ 2019-10-01 21:41 UTC (permalink / raw)
  To: netdev; +Cc: yhs, ebiederm, brouer, bpf, cneirabustos

Currently bpf_get_current_pid_tgid(), is used to do pid filtering in bcc's
scripts but this helper returns the pid as seen by the root namespace which is
fine when a bcc script is not executed inside a container.
When the process of interest is inside a container, pid filtering will not work
if bpf_get_current_pid_tgid() is used.
This helper addresses this limitation returning the pid as it's seen by the current
namespace where the script is executing.

In the future different pid_ns files may belong to different devices, according to the
discussion between Eric Biederman and Yonghong in 2017 Linux plumbers conference.
To address that situation the helper requires inum and dev_t from /proc/self/ns/pid.
This helper has the same use cases as bpf_get_current_pid_tgid() as it can be
used to do pid filtering even inside a container.

Changes from V11:

- helper: Input changed dev from u32 to u64.
- Moved self-test to test_progs.
- Remove unneeded maps in self-test.

Signed-off-by: Carlos Neira <cneirabustos@gmail.com>

Carlos Neira (4):
  fs/nsfs.c: added ns_match
  bpf: added new helper bpf_get_ns_current_pid_tgid
  tools: Added bpf_get_ns_current_pid_tgid helper
  tools/testing/selftests/bpf: Add self-tests for new helper.

 fs/nsfs.c                                     |  8 ++
 include/linux/bpf.h                           |  1 +
 include/linux/proc_ns.h                       |  2 +
 include/uapi/linux/bpf.h                      | 18 +++-
 kernel/bpf/core.c                             |  1 +
 kernel/bpf/helpers.c                          | 36 ++++++++
 kernel/trace/bpf_trace.c                      |  2 +
 tools/include/uapi/linux/bpf.h                | 18 +++-
 tools/testing/selftests/bpf/bpf_helpers.h     |  3 +
 .../bpf/prog_tests/get_ns_current_pid_tgid.c  | 85 +++++++++++++++++++
 .../bpf/progs/get_ns_current_pid_tgid_kern.c  | 47 ++++++++++
 11 files changed, 219 insertions(+), 2 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/get_ns_current_pid_tgid.c
 create mode 100644 tools/testing/selftests/bpf/progs/get_ns_current_pid_tgid_kern.c

-- 
2.20.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH V12 1/4] fs/nsfs.c: added ns_match
  2019-10-01 21:41 [PATCH V12 0/4] BPF: New helper to obtain namespace data from current task Carlos Neira
@ 2019-10-01 21:41 ` Carlos Neira
  2019-10-01 21:41 ` [PATCH V12 2/4] bpf: added new helper bpf_get_ns_current_pid_tgid Carlos Neira
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Carlos Neira @ 2019-10-01 21:41 UTC (permalink / raw)
  To: netdev; +Cc: yhs, ebiederm, brouer, bpf, cneirabustos

ns_match returns true if the namespace inode and dev_t matches the ones
provided by the caller.

Signed-off-by: Carlos Neira <cneirabustos@gmail.com>
---
 fs/nsfs.c               | 8 ++++++++
 include/linux/proc_ns.h | 2 ++
 2 files changed, 10 insertions(+)

diff --git a/fs/nsfs.c b/fs/nsfs.c
index a0431642c6b5..256f6295d33d 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -245,6 +245,14 @@ struct file *proc_ns_fget(int fd)
 	return ERR_PTR(-EINVAL);
 }
 
+/* Returns true if current namespace matches dev/ino.
+ */
+bool ns_match(const struct ns_common *ns, dev_t dev, ino_t ino)
+{
+	return ((ns->inum == ino) && (nsfs_mnt->mnt_sb->s_dev == dev));
+}
+
+
 static int nsfs_show_path(struct seq_file *seq, struct dentry *dentry)
 {
 	struct inode *inode = d_inode(dentry);
diff --git a/include/linux/proc_ns.h b/include/linux/proc_ns.h
index d31cb6215905..1da9f33489f3 100644
--- a/include/linux/proc_ns.h
+++ b/include/linux/proc_ns.h
@@ -82,6 +82,8 @@ typedef struct ns_common *ns_get_path_helper_t(void *);
 extern void *ns_get_path_cb(struct path *path, ns_get_path_helper_t ns_get_cb,
 			    void *private_data);
 
+extern bool ns_match(const struct ns_common *ns, dev_t dev, ino_t ino);
+
 extern int ns_get_name(char *buf, size_t size, struct task_struct *task,
 			const struct proc_ns_operations *ns_ops);
 extern void nsfs_init(void);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH V12 2/4] bpf: added new helper bpf_get_ns_current_pid_tgid
  2019-10-01 21:41 [PATCH V12 0/4] BPF: New helper to obtain namespace data from current task Carlos Neira
  2019-10-01 21:41 ` [PATCH V12 1/4] fs/nsfs.c: added ns_match Carlos Neira
@ 2019-10-01 21:41 ` Carlos Neira
  2019-10-02 10:52   ` Daniel Borkmann
  2019-10-01 21:41 ` [PATCH V12 3/4] tools: Added bpf_get_ns_current_pid_tgid helper Carlos Neira
  2019-10-01 21:41 ` [PATCH V12 4/4] tools/testing/selftests/bpf: Add self-tests for new helper Carlos Neira
  3 siblings, 1 reply; 9+ messages in thread
From: Carlos Neira @ 2019-10-01 21:41 UTC (permalink / raw)
  To: netdev; +Cc: yhs, ebiederm, brouer, bpf, cneirabustos

New bpf helper bpf_get_ns_current_pid_tgid,
This helper will return pid and tgid from current task
which namespace matches dev_t and inode number provided,
this will allows us to instrument a process inside a container.

Signed-off-by: Carlos Neira <cneirabustos@gmail.com>
---
 include/linux/bpf.h      |  1 +
 include/uapi/linux/bpf.h | 18 +++++++++++++++++-
 kernel/bpf/core.c        |  1 +
 kernel/bpf/helpers.c     | 36 ++++++++++++++++++++++++++++++++++++
 kernel/trace/bpf_trace.c |  2 ++
 5 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 5b9d22338606..231001475504 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1055,6 +1055,7 @@ extern const struct bpf_func_proto bpf_get_local_storage_proto;
 extern const struct bpf_func_proto bpf_strtol_proto;
 extern const struct bpf_func_proto bpf_strtoul_proto;
 extern const struct bpf_func_proto bpf_tcp_sock_proto;
+extern const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto;
 
 /* Shared helpers among cBPF and eBPF. */
 void bpf_user_rnd_init_once(void);
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 77c6be96d676..ea8145d7f897 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -2750,6 +2750,21 @@ union bpf_attr {
  *		**-EOPNOTSUPP** kernel configuration does not enable SYN cookies
  *
  *		**-EPROTONOSUPPORT** IP packet version is not 4 or 6
+ *
+ * u64 bpf_get_ns_current_pid_tgid(u64 dev, u64 inum)
+ *	Return
+ *		A 64-bit integer containing the current tgid and pid from current task
+ *              which namespace inode and dev_t matches , and is create as such:
+ *		*current_task*\ **->tgid << 32 \|**
+ *		*current_task*\ **->pid**.
+ *
+ *		On failure, the returned value is one of the following:
+ *
+ *		**-EINVAL** if dev and inum supplied don't match dev_t and inode number
+ *              with nsfs of current task, or if dev conversion to dev_t lost high bits.
+ *
+ *		**-ENOENT** if /proc/self/ns does not exists.
+ *
  */
 #define __BPF_FUNC_MAPPER(FN)		\
 	FN(unspec),			\
@@ -2862,7 +2877,8 @@ union bpf_attr {
 	FN(sk_storage_get),		\
 	FN(sk_storage_delete),		\
 	FN(send_signal),		\
-	FN(tcp_gen_syncookie),
+	FN(tcp_gen_syncookie),          \
+	FN(get_ns_current_pid_tgid),
 
 /* 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 66088a9e9b9e..b2fd5358f472 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2042,6 +2042,7 @@ const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak;
 const struct bpf_func_proto bpf_get_current_comm_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_ns_current_pid_tgid_proto __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 5e28718928ca..8777181d1717 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -11,6 +11,8 @@
 #include <linux/uidgid.h>
 #include <linux/filter.h>
 #include <linux/ctype.h>
+#include <linux/pid_namespace.h>
+#include <linux/proc_ns.h>
 
 #include "../../lib/kstrtox.h"
 
@@ -487,3 +489,37 @@ const struct bpf_func_proto bpf_strtoul_proto = {
 	.arg4_type	= ARG_PTR_TO_LONG,
 };
 #endif
+
+BPF_CALL_2(bpf_get_ns_current_pid_tgid, u64, dev, u64, inum)
+{
+	struct task_struct *task = current;
+	struct pid_namespace *pidns;
+	pid_t pid, tgid;
+
+	if ((u64)(dev_t)dev != dev)
+		return -EINVAL;
+
+	if (unlikely(!task))
+		return -EINVAL;
+
+	pidns = task_active_pid_ns(task);
+	if (unlikely(!pidns))
+		return -ENOENT;
+
+
+	if (!ns_match(&pidns->ns, (dev_t)dev, inum))
+		return -EINVAL;
+
+	pid = task_pid_nr_ns(task, pidns);
+	tgid = task_tgid_nr_ns(task, pidns);
+
+	return (u64) tgid << 32 | pid;
+}
+
+const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto = {
+	.func		= bpf_get_ns_current_pid_tgid,
+	.gpl_only	= false,
+	.ret_type	= RET_INTEGER,
+	.arg1_type	= ARG_ANYTHING,
+	.arg2_type	= ARG_ANYTHING,
+};
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 44bd08f2443b..32331a1dcb6d 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -735,6 +735,8 @@ tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 #endif
 	case BPF_FUNC_send_signal:
 		return &bpf_send_signal_proto;
+	case BPF_FUNC_get_ns_current_pid_tgid:
+		return &bpf_get_ns_current_pid_tgid_proto;
 	default:
 		return NULL;
 	}
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH V12 3/4] tools: Added bpf_get_ns_current_pid_tgid helper
  2019-10-01 21:41 [PATCH V12 0/4] BPF: New helper to obtain namespace data from current task Carlos Neira
  2019-10-01 21:41 ` [PATCH V12 1/4] fs/nsfs.c: added ns_match Carlos Neira
  2019-10-01 21:41 ` [PATCH V12 2/4] bpf: added new helper bpf_get_ns_current_pid_tgid Carlos Neira
@ 2019-10-01 21:41 ` Carlos Neira
  2019-10-01 21:41 ` [PATCH V12 4/4] tools/testing/selftests/bpf: Add self-tests for new helper Carlos Neira
  3 siblings, 0 replies; 9+ messages in thread
From: Carlos Neira @ 2019-10-01 21:41 UTC (permalink / raw)
  To: netdev; +Cc: yhs, ebiederm, brouer, bpf, cneirabustos

sync tools/include/uapi/linux/bpf.h to include new helper.

Signed-off-by: Carlos Neira <cneirabustos@gmail.com>
---
 tools/include/uapi/linux/bpf.h | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 77c6be96d676..ea8145d7f897 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -2750,6 +2750,21 @@ union bpf_attr {
  *		**-EOPNOTSUPP** kernel configuration does not enable SYN cookies
  *
  *		**-EPROTONOSUPPORT** IP packet version is not 4 or 6
+ *
+ * u64 bpf_get_ns_current_pid_tgid(u64 dev, u64 inum)
+ *	Return
+ *		A 64-bit integer containing the current tgid and pid from current task
+ *              which namespace inode and dev_t matches , and is create as such:
+ *		*current_task*\ **->tgid << 32 \|**
+ *		*current_task*\ **->pid**.
+ *
+ *		On failure, the returned value is one of the following:
+ *
+ *		**-EINVAL** if dev and inum supplied don't match dev_t and inode number
+ *              with nsfs of current task, or if dev conversion to dev_t lost high bits.
+ *
+ *		**-ENOENT** if /proc/self/ns does not exists.
+ *
  */
 #define __BPF_FUNC_MAPPER(FN)		\
 	FN(unspec),			\
@@ -2862,7 +2877,8 @@ union bpf_attr {
 	FN(sk_storage_get),		\
 	FN(sk_storage_delete),		\
 	FN(send_signal),		\
-	FN(tcp_gen_syncookie),
+	FN(tcp_gen_syncookie),          \
+	FN(get_ns_current_pid_tgid),
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
  * function eBPF program intends to call
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH V12 4/4] tools/testing/selftests/bpf: Add self-tests for new helper.
  2019-10-01 21:41 [PATCH V12 0/4] BPF: New helper to obtain namespace data from current task Carlos Neira
                   ` (2 preceding siblings ...)
  2019-10-01 21:41 ` [PATCH V12 3/4] tools: Added bpf_get_ns_current_pid_tgid helper Carlos Neira
@ 2019-10-01 21:41 ` Carlos Neira
  3 siblings, 0 replies; 9+ messages in thread
From: Carlos Neira @ 2019-10-01 21:41 UTC (permalink / raw)
  To: netdev; +Cc: yhs, ebiederm, brouer, bpf, cneirabustos

Self tests added for new helper

Signed-off-by: Carlos Neira <cneirabustos@gmail.com>
---
 tools/testing/selftests/bpf/bpf_helpers.h     |  3 +
 .../bpf/prog_tests/get_ns_current_pid_tgid.c  | 85 +++++++++++++++++++
 .../bpf/progs/get_ns_current_pid_tgid_kern.c  | 47 ++++++++++
 3 files changed, 135 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/get_ns_current_pid_tgid.c
 create mode 100644 tools/testing/selftests/bpf/progs/get_ns_current_pid_tgid_kern.c

diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index 54a50699bbfd..19c03ba066b1 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -233,6 +233,9 @@ static int (*bpf_send_signal)(unsigned sig) = (void *)BPF_FUNC_send_signal;
 static long long (*bpf_tcp_gen_syncookie)(struct bpf_sock *sk, void *ip,
 					  int ip_len, void *tcp, int tcp_len) =
 	(void *) BPF_FUNC_tcp_gen_syncookie;
+static unsigned long long (*bpf_get_ns_current_pid_tgid)(__u64 dev, __u64 inum) =
+	(void *) BPF_FUNC_get_ns_current_pid_tgid;
+
 
 /* llvm builtin functions that eBPF C program may use to
  * emit BPF_LD_ABS and BPF_LD_IND instructions
diff --git a/tools/testing/selftests/bpf/prog_tests/get_ns_current_pid_tgid.c b/tools/testing/selftests/bpf/prog_tests/get_ns_current_pid_tgid.c
new file mode 100644
index 000000000000..4d8ec524d373
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/get_ns_current_pid_tgid.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2019 Carlos Neira cneirabustos@gmail.com */
+#include <test_progs.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+void test_get_ns_current_pid_tgid(void)
+{
+	const char *probe_name = "syscalls/sys_enter_nanosleep";
+	const char *file = "get_ns_current_pid_tgid_kern.o";
+	int ns_data_map_fd, duration = 0;
+	struct perf_event_attr attr = {};
+	int err, efd, prog_fd, pmu_fd;
+	__u64 ino, dev, id, nspid;
+	struct bpf_object *obj;
+	struct stat st;
+	__u32 key = 0;
+	char buf[256];
+
+	err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
+	if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
+		return;
+
+	ns_data_map_fd = bpf_find_map(__func__, obj, "ns_data_map");
+	if (CHECK_FAIL(ns_data_map_fd < 0))
+		goto close_prog;
+
+	pid_t tid = syscall(SYS_gettid);
+	pid_t pid = getpid();
+
+	id = (__u64) tid << 32 | pid;
+	bpf_map_update_elem(ns_data_map_fd, &key, &id, 0);
+
+	if (stat("/proc/self/ns/pid", &st))
+		goto close_prog;
+
+	dev = st.st_dev;
+	ino = st.st_ino;
+	key = 1;
+	bpf_map_update_elem(ns_data_map_fd, &key, &dev, 0);
+	key = 2;
+	bpf_map_update_elem(ns_data_map_fd, &key, &ino, 0);
+
+	snprintf(buf, sizeof(buf),
+		 "/sys/kernel/debug/tracing/events/%s/id", probe_name);
+	efd = open(buf, O_RDONLY, 0);
+	read(efd, buf, sizeof(buf));
+	close(efd);
+	attr.config = strtol(buf, NULL, 0);
+	attr.type = PERF_TYPE_TRACEPOINT;
+	attr.sample_type = PERF_SAMPLE_RAW;
+	attr.sample_period = 1;
+	attr.wakeup_events = 1;
+
+	pmu_fd = syscall(__NR_perf_event_open, &attr, getpid(), -1, -1, 0);
+	if (CHECK_FAIL(pmu_fd < 0))
+		goto cleanup;
+
+	err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
+	if (CHECK_FAIL(err))
+		goto cleanup;
+
+	err = ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);
+	if (CHECK_FAIL(err))
+		goto cleanup;
+
+	/* trigger some syscalls */
+	sleep(1);
+	key = 3;
+	err = bpf_map_lookup_elem(ns_data_map_fd, &key, &nspid);
+	if (CHECK_FAIL(err))
+		goto cleanup;
+
+	if (CHECK(id != nspid, "Compare user pid/tgid %llu vs. bpf pid/tgid %llu",
+		  "Userspace pid/tgid %llu EBPF pid/tgid %llu\n", id, nspid))
+		goto cleanup;
+
+cleanup:
+	close(pmu_fd);
+close_prog:
+	bpf_object__close(obj);
+}
diff --git a/tools/testing/selftests/bpf/progs/get_ns_current_pid_tgid_kern.c b/tools/testing/selftests/bpf/progs/get_ns_current_pid_tgid_kern.c
new file mode 100644
index 000000000000..00a325e85e8c
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/get_ns_current_pid_tgid_kern.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2019 Carlos Neira cneirabustos@gmail.com */
+
+#include <linux/bpf.h>
+#include "bpf_helpers.h"
+
+struct {
+	__uint(type, BPF_MAP_TYPE_ARRAY);
+	__uint(max_entries, 4);
+	__type(key, __u32);
+	__type(value, __u64);
+} ns_data_map SEC(".maps");
+
+
+SEC("tracepoint/syscalls/sys_enter_nanosleep")
+int trace(void *ctx)
+{
+	__u64 *val, *inum, *dev, nspid, *expected_pid;
+	__u32 key = 1;
+
+	dev = bpf_map_lookup_elem(&ns_data_map, &key);
+	if (!dev)
+		return 0;
+	key = 2;
+	inum = bpf_map_lookup_elem(&ns_data_map, &key);
+
+	if (!inum)
+		return 0;
+
+	nspid =  bpf_get_ns_current_pid_tgid(*dev, *inum);
+	key = 0;
+	expected_pid = bpf_map_lookup_elem(&ns_data_map, &key);
+
+	if (!expected_pid || *expected_pid != nspid)
+		return 0;
+
+	key = 3;
+	val = bpf_map_lookup_elem(&ns_data_map, &key);
+
+	if (val)
+		*val = nspid;
+
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";
+__u32 _version SEC("version") = 1;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH V12 2/4] bpf: added new helper bpf_get_ns_current_pid_tgid
  2019-10-01 21:41 ` [PATCH V12 2/4] bpf: added new helper bpf_get_ns_current_pid_tgid Carlos Neira
@ 2019-10-02 10:52   ` Daniel Borkmann
  2019-10-03 14:52     ` Carlos Antonio Neira Bustos
  0 siblings, 1 reply; 9+ messages in thread
From: Daniel Borkmann @ 2019-10-02 10:52 UTC (permalink / raw)
  To: Carlos Neira, netdev; +Cc: yhs, ebiederm, brouer, bpf

On 10/1/19 11:41 PM, Carlos Neira wrote:
> New bpf helper bpf_get_ns_current_pid_tgid,
> This helper will return pid and tgid from current task
> which namespace matches dev_t and inode number provided,
> this will allows us to instrument a process inside a container.
> 
> Signed-off-by: Carlos Neira <cneirabustos@gmail.com>
> ---
>   include/linux/bpf.h      |  1 +
>   include/uapi/linux/bpf.h | 18 +++++++++++++++++-
>   kernel/bpf/core.c        |  1 +
>   kernel/bpf/helpers.c     | 36 ++++++++++++++++++++++++++++++++++++
>   kernel/trace/bpf_trace.c |  2 ++
>   5 files changed, 57 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index 5b9d22338606..231001475504 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -1055,6 +1055,7 @@ extern const struct bpf_func_proto bpf_get_local_storage_proto;
>   extern const struct bpf_func_proto bpf_strtol_proto;
>   extern const struct bpf_func_proto bpf_strtoul_proto;
>   extern const struct bpf_func_proto bpf_tcp_sock_proto;
> +extern const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto;
>   
>   /* Shared helpers among cBPF and eBPF. */
>   void bpf_user_rnd_init_once(void);
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index 77c6be96d676..ea8145d7f897 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -2750,6 +2750,21 @@ union bpf_attr {
>    *		**-EOPNOTSUPP** kernel configuration does not enable SYN cookies
>    *
>    *		**-EPROTONOSUPPORT** IP packet version is not 4 or 6
> + *
> + * u64 bpf_get_ns_current_pid_tgid(u64 dev, u64 inum)
> + *	Return
> + *		A 64-bit integer containing the current tgid and pid from current task
> + *              which namespace inode and dev_t matches , and is create as such:
> + *		*current_task*\ **->tgid << 32 \|**
> + *		*current_task*\ **->pid**.
> + *
> + *		On failure, the returned value is one of the following:
> + *
> + *		**-EINVAL** if dev and inum supplied don't match dev_t and inode number
> + *              with nsfs of current task, or if dev conversion to dev_t lost high bits.
> + *
> + *		**-ENOENT** if /proc/self/ns does not exists.
> + *
>    */
>   #define __BPF_FUNC_MAPPER(FN)		\
>   	FN(unspec),			\
> @@ -2862,7 +2877,8 @@ union bpf_attr {
>   	FN(sk_storage_get),		\
>   	FN(sk_storage_delete),		\
>   	FN(send_signal),		\
> -	FN(tcp_gen_syncookie),
> +	FN(tcp_gen_syncookie),          \
> +	FN(get_ns_current_pid_tgid),
>   
>   /* 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 66088a9e9b9e..b2fd5358f472 100644
> --- a/kernel/bpf/core.c
> +++ b/kernel/bpf/core.c
> @@ -2042,6 +2042,7 @@ const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak;
>   const struct bpf_func_proto bpf_get_current_comm_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_ns_current_pid_tgid_proto __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 5e28718928ca..8777181d1717 100644
> --- a/kernel/bpf/helpers.c
> +++ b/kernel/bpf/helpers.c
> @@ -11,6 +11,8 @@
>   #include <linux/uidgid.h>
>   #include <linux/filter.h>
>   #include <linux/ctype.h>
> +#include <linux/pid_namespace.h>
> +#include <linux/proc_ns.h>
>   
>   #include "../../lib/kstrtox.h"
>   
> @@ -487,3 +489,37 @@ const struct bpf_func_proto bpf_strtoul_proto = {
>   	.arg4_type	= ARG_PTR_TO_LONG,
>   };
>   #endif
> +
> +BPF_CALL_2(bpf_get_ns_current_pid_tgid, u64, dev, u64, inum)
> +{
> +	struct task_struct *task = current;
> +	struct pid_namespace *pidns;
> +	pid_t pid, tgid;
> +
> +	if ((u64)(dev_t)dev != dev)
> +		return -EINVAL;
> +
> +	if (unlikely(!task))
> +		return -EINVAL;
> +
> +	pidns = task_active_pid_ns(task);
> +	if (unlikely(!pidns))
> +		return -ENOENT;
> +
> +
> +	if (!ns_match(&pidns->ns, (dev_t)dev, inum))
> +		return -EINVAL;
> +
> +	pid = task_pid_nr_ns(task, pidns);
> +	tgid = task_tgid_nr_ns(task, pidns);
> +
> +	return (u64) tgid << 32 | pid;

Basically here you are overlapping the 64-bit return value for the valid
outcome with the error codes above for the invalid case. If you look at
bpf_perf_event_read() we already had such broken occasion that bit us in
the past, and needed to introduce bpf_perf_event_read_value() instead.
Lets not go there again and design it similarly to the latter.

> +}
> +
> +const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto = {
> +	.func		= bpf_get_ns_current_pid_tgid,
> +	.gpl_only	= false,
> +	.ret_type	= RET_INTEGER,
> +	.arg1_type	= ARG_ANYTHING,
> +	.arg2_type	= ARG_ANYTHING,
> +};
> diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> index 44bd08f2443b..32331a1dcb6d 100644
> --- a/kernel/trace/bpf_trace.c
> +++ b/kernel/trace/bpf_trace.c
> @@ -735,6 +735,8 @@ tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
>   #endif
>   	case BPF_FUNC_send_signal:
>   		return &bpf_send_signal_proto;
> +	case BPF_FUNC_get_ns_current_pid_tgid:
> +		return &bpf_get_ns_current_pid_tgid_proto;
>   	default:
>   		return NULL;
>   	}
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH V12 2/4] bpf: added new helper bpf_get_ns_current_pid_tgid
  2019-10-02 10:52   ` Daniel Borkmann
@ 2019-10-03 14:52     ` Carlos Antonio Neira Bustos
  2019-10-03 17:30       ` Andrii Nakryiko
  0 siblings, 1 reply; 9+ messages in thread
From: Carlos Antonio Neira Bustos @ 2019-10-03 14:52 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: netdev, yhs, ebiederm, brouer, bpf

On Wed, Oct 02, 2019 at 12:52:29PM +0200, Daniel Borkmann wrote:
> On 10/1/19 11:41 PM, Carlos Neira wrote:
> > New bpf helper bpf_get_ns_current_pid_tgid,
> > This helper will return pid and tgid from current task
> > which namespace matches dev_t and inode number provided,
> > this will allows us to instrument a process inside a container.
> > 
> > Signed-off-by: Carlos Neira <cneirabustos@gmail.com>
> > ---
> >   include/linux/bpf.h      |  1 +
> >   include/uapi/linux/bpf.h | 18 +++++++++++++++++-
> >   kernel/bpf/core.c        |  1 +
> >   kernel/bpf/helpers.c     | 36 ++++++++++++++++++++++++++++++++++++
> >   kernel/trace/bpf_trace.c |  2 ++
> >   5 files changed, 57 insertions(+), 1 deletion(-)
> > 
> > diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> > index 5b9d22338606..231001475504 100644
> > --- a/include/linux/bpf.h
> > +++ b/include/linux/bpf.h
> > @@ -1055,6 +1055,7 @@ extern const struct bpf_func_proto bpf_get_local_storage_proto;
> >   extern const struct bpf_func_proto bpf_strtol_proto;
> >   extern const struct bpf_func_proto bpf_strtoul_proto;
> >   extern const struct bpf_func_proto bpf_tcp_sock_proto;
> > +extern const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto;
> >   /* Shared helpers among cBPF and eBPF. */
> >   void bpf_user_rnd_init_once(void);
> > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > index 77c6be96d676..ea8145d7f897 100644
> > --- a/include/uapi/linux/bpf.h
> > +++ b/include/uapi/linux/bpf.h
> > @@ -2750,6 +2750,21 @@ union bpf_attr {
> >    *		**-EOPNOTSUPP** kernel configuration does not enable SYN cookies
> >    *
> >    *		**-EPROTONOSUPPORT** IP packet version is not 4 or 6
> > + *
> > + * u64 bpf_get_ns_current_pid_tgid(u64 dev, u64 inum)
> > + *	Return
> > + *		A 64-bit integer containing the current tgid and pid from current task
> > + *              which namespace inode and dev_t matches , and is create as such:
> > + *		*current_task*\ **->tgid << 32 \|**
> > + *		*current_task*\ **->pid**.
> > + *
> > + *		On failure, the returned value is one of the following:
> > + *
> > + *		**-EINVAL** if dev and inum supplied don't match dev_t and inode number
> > + *              with nsfs of current task, or if dev conversion to dev_t lost high bits.
> > + *
> > + *		**-ENOENT** if /proc/self/ns does not exists.
> > + *
> >    */
> >   #define __BPF_FUNC_MAPPER(FN)		\
> >   	FN(unspec),			\
> > @@ -2862,7 +2877,8 @@ union bpf_attr {
> >   	FN(sk_storage_get),		\
> >   	FN(sk_storage_delete),		\
> >   	FN(send_signal),		\
> > -	FN(tcp_gen_syncookie),
> > +	FN(tcp_gen_syncookie),          \
> > +	FN(get_ns_current_pid_tgid),
> >   /* 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 66088a9e9b9e..b2fd5358f472 100644
> > --- a/kernel/bpf/core.c
> > +++ b/kernel/bpf/core.c
> > @@ -2042,6 +2042,7 @@ const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak;
> >   const struct bpf_func_proto bpf_get_current_comm_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_ns_current_pid_tgid_proto __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 5e28718928ca..8777181d1717 100644
> > --- a/kernel/bpf/helpers.c
> > +++ b/kernel/bpf/helpers.c
> > @@ -11,6 +11,8 @@
> >   #include <linux/uidgid.h>
> >   #include <linux/filter.h>
> >   #include <linux/ctype.h>
> > +#include <linux/pid_namespace.h>
> > +#include <linux/proc_ns.h>
> >   #include "../../lib/kstrtox.h"
> > @@ -487,3 +489,37 @@ const struct bpf_func_proto bpf_strtoul_proto = {
> >   	.arg4_type	= ARG_PTR_TO_LONG,
> >   };
> >   #endif
> > +
> > +BPF_CALL_2(bpf_get_ns_current_pid_tgid, u64, dev, u64, inum)
> > +{
> > +	struct task_struct *task = current;
> > +	struct pid_namespace *pidns;
> > +	pid_t pid, tgid;
> > +
> > +	if ((u64)(dev_t)dev != dev)
> > +		return -EINVAL;
> > +
> > +	if (unlikely(!task))
> > +		return -EINVAL;
> > +
> > +	pidns = task_active_pid_ns(task);
> > +	if (unlikely(!pidns))
> > +		return -ENOENT;
> > +
> > +
> > +	if (!ns_match(&pidns->ns, (dev_t)dev, inum))
> > +		return -EINVAL;
> > +
> > +	pid = task_pid_nr_ns(task, pidns);
> > +	tgid = task_tgid_nr_ns(task, pidns);
> > +
> > +	return (u64) tgid << 32 | pid;
> 
> Basically here you are overlapping the 64-bit return value for the valid
> outcome with the error codes above for the invalid case. If you look at
> bpf_perf_event_read() we already had such broken occasion that bit us in
> the past, and needed to introduce bpf_perf_event_read_value() instead.
> Lets not go there again and design it similarly to the latter.
> 
> > +}
> > +
> > +const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto = {
> > +	.func		= bpf_get_ns_current_pid_tgid,
> > +	.gpl_only	= false,
> > +	.ret_type	= RET_INTEGER,
> > +	.arg1_type	= ARG_ANYTHING,
> > +	.arg2_type	= ARG_ANYTHING,
> > +};
> > diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> > index 44bd08f2443b..32331a1dcb6d 100644
> > --- a/kernel/trace/bpf_trace.c
> > +++ b/kernel/trace/bpf_trace.c
> > @@ -735,6 +735,8 @@ tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
> >   #endif
> >   	case BPF_FUNC_send_signal:
> >   		return &bpf_send_signal_proto;
> > +	case BPF_FUNC_get_ns_current_pid_tgid:
> > +		return &bpf_get_ns_current_pid_tgid_proto;
> >   	default:
> >   		return NULL;
> >   	}
> > 
> 
Daniel,
If I understand correctly, to avoid problems I need to change the helper's function signature to something like the following:

struct bpf_ns_current_pid_tgid_storage {
	__u64 dev;
	__u64 inum;
	__u64 pidtgid;
};

BPF_CALL_2(bpf_get_ns_current_pid_tgid,
	   struct bpf_ns_current_pid_tgid_storage *, buf, u32, size);  

then use dev and inum provided by the user and return the requested
value into pidtgid of the struct. Would that work?

Thanks for your help. 
 




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH V12 2/4] bpf: added new helper bpf_get_ns_current_pid_tgid
  2019-10-03 14:52     ` Carlos Antonio Neira Bustos
@ 2019-10-03 17:30       ` Andrii Nakryiko
  2019-10-03 18:12         ` Carlos Antonio Neira Bustos
  0 siblings, 1 reply; 9+ messages in thread
From: Andrii Nakryiko @ 2019-10-03 17:30 UTC (permalink / raw)
  To: Carlos Antonio Neira Bustos
  Cc: Daniel Borkmann, Networking, Yonghong Song, ebiederm,
	Jesper Dangaard Brouer, bpf

On Thu, Oct 3, 2019 at 8:01 AM Carlos Antonio Neira Bustos
<cneirabustos@gmail.com> wrote:
>
> On Wed, Oct 02, 2019 at 12:52:29PM +0200, Daniel Borkmann wrote:
> > On 10/1/19 11:41 PM, Carlos Neira wrote:
> > > New bpf helper bpf_get_ns_current_pid_tgid,
> > > This helper will return pid and tgid from current task
> > > which namespace matches dev_t and inode number provided,
> > > this will allows us to instrument a process inside a container.
> > >
> > > Signed-off-by: Carlos Neira <cneirabustos@gmail.com>
> > > ---
> > >   include/linux/bpf.h      |  1 +
> > >   include/uapi/linux/bpf.h | 18 +++++++++++++++++-
> > >   kernel/bpf/core.c        |  1 +
> > >   kernel/bpf/helpers.c     | 36 ++++++++++++++++++++++++++++++++++++
> > >   kernel/trace/bpf_trace.c |  2 ++
> > >   5 files changed, 57 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> > > index 5b9d22338606..231001475504 100644
> > > --- a/include/linux/bpf.h
> > > +++ b/include/linux/bpf.h
> > > @@ -1055,6 +1055,7 @@ extern const struct bpf_func_proto bpf_get_local_storage_proto;
> > >   extern const struct bpf_func_proto bpf_strtol_proto;
> > >   extern const struct bpf_func_proto bpf_strtoul_proto;
> > >   extern const struct bpf_func_proto bpf_tcp_sock_proto;
> > > +extern const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto;
> > >   /* Shared helpers among cBPF and eBPF. */
> > >   void bpf_user_rnd_init_once(void);
> > > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > > index 77c6be96d676..ea8145d7f897 100644
> > > --- a/include/uapi/linux/bpf.h
> > > +++ b/include/uapi/linux/bpf.h
> > > @@ -2750,6 +2750,21 @@ union bpf_attr {
> > >    *                **-EOPNOTSUPP** kernel configuration does not enable SYN cookies
> > >    *
> > >    *                **-EPROTONOSUPPORT** IP packet version is not 4 or 6
> > > + *
> > > + * u64 bpf_get_ns_current_pid_tgid(u64 dev, u64 inum)
> > > + * Return
> > > + *         A 64-bit integer containing the current tgid and pid from current task
> > > + *              which namespace inode and dev_t matches , and is create as such:
> > > + *         *current_task*\ **->tgid << 32 \|**
> > > + *         *current_task*\ **->pid**.
> > > + *
> > > + *         On failure, the returned value is one of the following:
> > > + *
> > > + *         **-EINVAL** if dev and inum supplied don't match dev_t and inode number
> > > + *              with nsfs of current task, or if dev conversion to dev_t lost high bits.
> > > + *
> > > + *         **-ENOENT** if /proc/self/ns does not exists.
> > > + *
> > >    */
> > >   #define __BPF_FUNC_MAPPER(FN)             \
> > >     FN(unspec),                     \
> > > @@ -2862,7 +2877,8 @@ union bpf_attr {
> > >     FN(sk_storage_get),             \
> > >     FN(sk_storage_delete),          \
> > >     FN(send_signal),                \
> > > -   FN(tcp_gen_syncookie),
> > > +   FN(tcp_gen_syncookie),          \
> > > +   FN(get_ns_current_pid_tgid),
> > >   /* 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 66088a9e9b9e..b2fd5358f472 100644
> > > --- a/kernel/bpf/core.c
> > > +++ b/kernel/bpf/core.c
> > > @@ -2042,6 +2042,7 @@ const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak;
> > >   const struct bpf_func_proto bpf_get_current_comm_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_ns_current_pid_tgid_proto __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 5e28718928ca..8777181d1717 100644
> > > --- a/kernel/bpf/helpers.c
> > > +++ b/kernel/bpf/helpers.c
> > > @@ -11,6 +11,8 @@
> > >   #include <linux/uidgid.h>
> > >   #include <linux/filter.h>
> > >   #include <linux/ctype.h>
> > > +#include <linux/pid_namespace.h>
> > > +#include <linux/proc_ns.h>
> > >   #include "../../lib/kstrtox.h"
> > > @@ -487,3 +489,37 @@ const struct bpf_func_proto bpf_strtoul_proto = {
> > >     .arg4_type      = ARG_PTR_TO_LONG,
> > >   };
> > >   #endif
> > > +
> > > +BPF_CALL_2(bpf_get_ns_current_pid_tgid, u64, dev, u64, inum)
> > > +{
> > > +   struct task_struct *task = current;
> > > +   struct pid_namespace *pidns;
> > > +   pid_t pid, tgid;
> > > +
> > > +   if ((u64)(dev_t)dev != dev)
> > > +           return -EINVAL;
> > > +
> > > +   if (unlikely(!task))
> > > +           return -EINVAL;
> > > +
> > > +   pidns = task_active_pid_ns(task);
> > > +   if (unlikely(!pidns))
> > > +           return -ENOENT;
> > > +
> > > +
> > > +   if (!ns_match(&pidns->ns, (dev_t)dev, inum))
> > > +           return -EINVAL;
> > > +
> > > +   pid = task_pid_nr_ns(task, pidns);
> > > +   tgid = task_tgid_nr_ns(task, pidns);
> > > +
> > > +   return (u64) tgid << 32 | pid;
> >
> > Basically here you are overlapping the 64-bit return value for the valid
> > outcome with the error codes above for the invalid case. If you look at
> > bpf_perf_event_read() we already had such broken occasion that bit us in
> > the past, and needed to introduce bpf_perf_event_read_value() instead.
> > Lets not go there again and design it similarly to the latter.
> >
> > > +}
> > > +
> > > +const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto = {
> > > +   .func           = bpf_get_ns_current_pid_tgid,
> > > +   .gpl_only       = false,
> > > +   .ret_type       = RET_INTEGER,
> > > +   .arg1_type      = ARG_ANYTHING,
> > > +   .arg2_type      = ARG_ANYTHING,
> > > +};
> > > diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> > > index 44bd08f2443b..32331a1dcb6d 100644
> > > --- a/kernel/trace/bpf_trace.c
> > > +++ b/kernel/trace/bpf_trace.c
> > > @@ -735,6 +735,8 @@ tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
> > >   #endif
> > >     case BPF_FUNC_send_signal:
> > >             return &bpf_send_signal_proto;
> > > +   case BPF_FUNC_get_ns_current_pid_tgid:
> > > +           return &bpf_get_ns_current_pid_tgid_proto;
> > >     default:
> > >             return NULL;
> > >     }
> > >
> >
> Daniel,
> If I understand correctly, to avoid problems I need to change the helper's function signature to something like the following:
>
> struct bpf_ns_current_pid_tgid_storage {
>         __u64 dev;
>         __u64 inum;
>         __u64 pidtgid;

if you do it this way, please do

__u32 pid;
__u34 tgid;

I have to look up where pid and tgid is in that 64-bit number every
single time, let's not do it here for no good reason.

> };
>
> BPF_CALL_2(bpf_get_ns_current_pid_tgid,
>            struct bpf_ns_current_pid_tgid_storage *, buf, u32, size);
>
> then use dev and inum provided by the user and return the requested
> value into pidtgid of the struct. Would that work?
>
> Thanks for your help.
>
>
>
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH V12 2/4] bpf: added new helper bpf_get_ns_current_pid_tgid
  2019-10-03 17:30       ` Andrii Nakryiko
@ 2019-10-03 18:12         ` Carlos Antonio Neira Bustos
  0 siblings, 0 replies; 9+ messages in thread
From: Carlos Antonio Neira Bustos @ 2019-10-03 18:12 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Daniel Borkmann, Networking, Yonghong Song, ebiederm,
	Jesper Dangaard Brouer, bpf

On Thu, Oct 03, 2019 at 10:30:06AM -0700, Andrii Nakryiko wrote:
> On Thu, Oct 3, 2019 at 8:01 AM Carlos Antonio Neira Bustos
> <cneirabustos@gmail.com> wrote:
> >
> > On Wed, Oct 02, 2019 at 12:52:29PM +0200, Daniel Borkmann wrote:
> > > On 10/1/19 11:41 PM, Carlos Neira wrote:
> > > > New bpf helper bpf_get_ns_current_pid_tgid,
> > > > This helper will return pid and tgid from current task
> > > > which namespace matches dev_t and inode number provided,
> > > > this will allows us to instrument a process inside a container.
> > > >
> > > > Signed-off-by: Carlos Neira <cneirabustos@gmail.com>
> > > > ---
> > > >   include/linux/bpf.h      |  1 +
> > > >   include/uapi/linux/bpf.h | 18 +++++++++++++++++-
> > > >   kernel/bpf/core.c        |  1 +
> > > >   kernel/bpf/helpers.c     | 36 ++++++++++++++++++++++++++++++++++++
> > > >   kernel/trace/bpf_trace.c |  2 ++
> > > >   5 files changed, 57 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> > > > index 5b9d22338606..231001475504 100644
> > > > --- a/include/linux/bpf.h
> > > > +++ b/include/linux/bpf.h
> > > > @@ -1055,6 +1055,7 @@ extern const struct bpf_func_proto bpf_get_local_storage_proto;
> > > >   extern const struct bpf_func_proto bpf_strtol_proto;
> > > >   extern const struct bpf_func_proto bpf_strtoul_proto;
> > > >   extern const struct bpf_func_proto bpf_tcp_sock_proto;
> > > > +extern const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto;
> > > >   /* Shared helpers among cBPF and eBPF. */
> > > >   void bpf_user_rnd_init_once(void);
> > > > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > > > index 77c6be96d676..ea8145d7f897 100644
> > > > --- a/include/uapi/linux/bpf.h
> > > > +++ b/include/uapi/linux/bpf.h
> > > > @@ -2750,6 +2750,21 @@ union bpf_attr {
> > > >    *                **-EOPNOTSUPP** kernel configuration does not enable SYN cookies
> > > >    *
> > > >    *                **-EPROTONOSUPPORT** IP packet version is not 4 or 6
> > > > + *
> > > > + * u64 bpf_get_ns_current_pid_tgid(u64 dev, u64 inum)
> > > > + * Return
> > > > + *         A 64-bit integer containing the current tgid and pid from current task
> > > > + *              which namespace inode and dev_t matches , and is create as such:
> > > > + *         *current_task*\ **->tgid << 32 \|**
> > > > + *         *current_task*\ **->pid**.
> > > > + *
> > > > + *         On failure, the returned value is one of the following:
> > > > + *
> > > > + *         **-EINVAL** if dev and inum supplied don't match dev_t and inode number
> > > > + *              with nsfs of current task, or if dev conversion to dev_t lost high bits.
> > > > + *
> > > > + *         **-ENOENT** if /proc/self/ns does not exists.
> > > > + *
> > > >    */
> > > >   #define __BPF_FUNC_MAPPER(FN)             \
> > > >     FN(unspec),                     \
> > > > @@ -2862,7 +2877,8 @@ union bpf_attr {
> > > >     FN(sk_storage_get),             \
> > > >     FN(sk_storage_delete),          \
> > > >     FN(send_signal),                \
> > > > -   FN(tcp_gen_syncookie),
> > > > +   FN(tcp_gen_syncookie),          \
> > > > +   FN(get_ns_current_pid_tgid),
> > > >   /* 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 66088a9e9b9e..b2fd5358f472 100644
> > > > --- a/kernel/bpf/core.c
> > > > +++ b/kernel/bpf/core.c
> > > > @@ -2042,6 +2042,7 @@ const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak;
> > > >   const struct bpf_func_proto bpf_get_current_comm_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_ns_current_pid_tgid_proto __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 5e28718928ca..8777181d1717 100644
> > > > --- a/kernel/bpf/helpers.c
> > > > +++ b/kernel/bpf/helpers.c
> > > > @@ -11,6 +11,8 @@
> > > >   #include <linux/uidgid.h>
> > > >   #include <linux/filter.h>
> > > >   #include <linux/ctype.h>
> > > > +#include <linux/pid_namespace.h>
> > > > +#include <linux/proc_ns.h>
> > > >   #include "../../lib/kstrtox.h"
> > > > @@ -487,3 +489,37 @@ const struct bpf_func_proto bpf_strtoul_proto = {
> > > >     .arg4_type      = ARG_PTR_TO_LONG,
> > > >   };
> > > >   #endif
> > > > +
> > > > +BPF_CALL_2(bpf_get_ns_current_pid_tgid, u64, dev, u64, inum)
> > > > +{
> > > > +   struct task_struct *task = current;
> > > > +   struct pid_namespace *pidns;
> > > > +   pid_t pid, tgid;
> > > > +
> > > > +   if ((u64)(dev_t)dev != dev)
> > > > +           return -EINVAL;
> > > > +
> > > > +   if (unlikely(!task))
> > > > +           return -EINVAL;
> > > > +
> > > > +   pidns = task_active_pid_ns(task);
> > > > +   if (unlikely(!pidns))
> > > > +           return -ENOENT;
> > > > +
> > > > +
> > > > +   if (!ns_match(&pidns->ns, (dev_t)dev, inum))
> > > > +           return -EINVAL;
> > > > +
> > > > +   pid = task_pid_nr_ns(task, pidns);
> > > > +   tgid = task_tgid_nr_ns(task, pidns);
> > > > +
> > > > +   return (u64) tgid << 32 | pid;
> > >
> > > Basically here you are overlapping the 64-bit return value for the valid
> > > outcome with the error codes above for the invalid case. If you look at
> > > bpf_perf_event_read() we already had such broken occasion that bit us in
> > > the past, and needed to introduce bpf_perf_event_read_value() instead.
> > > Lets not go there again and design it similarly to the latter.
> > >
> > > > +}
> > > > +
> > > > +const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto = {
> > > > +   .func           = bpf_get_ns_current_pid_tgid,
> > > > +   .gpl_only       = false,
> > > > +   .ret_type       = RET_INTEGER,
> > > > +   .arg1_type      = ARG_ANYTHING,
> > > > +   .arg2_type      = ARG_ANYTHING,
> > > > +};
> > > > diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> > > > index 44bd08f2443b..32331a1dcb6d 100644
> > > > --- a/kernel/trace/bpf_trace.c
> > > > +++ b/kernel/trace/bpf_trace.c
> > > > @@ -735,6 +735,8 @@ tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
> > > >   #endif
> > > >     case BPF_FUNC_send_signal:
> > > >             return &bpf_send_signal_proto;
> > > > +   case BPF_FUNC_get_ns_current_pid_tgid:
> > > > +           return &bpf_get_ns_current_pid_tgid_proto;
> > > >     default:
> > > >             return NULL;
> > > >     }
> > > >
> > >
> > Daniel,
> > If I understand correctly, to avoid problems I need to change the helper's function signature to something like the following:
> >
> > struct bpf_ns_current_pid_tgid_storage {
> >         __u64 dev;
> >         __u64 inum;
> >         __u64 pidtgid;
> 
> if you do it this way, please do
> 
> __u32 pid;
> __u34 tgid;
> 
> I have to look up where pid and tgid is in that 64-bit number every
> single time, let's not do it here for no good reason.
> 
> > };
> >
> > BPF_CALL_2(bpf_get_ns_current_pid_tgid,
> >            struct bpf_ns_current_pid_tgid_storage *, buf, u32, size);
> >
> > then use dev and inum provided by the user and return the requested
> > value into pidtgid of the struct. Would that work?
> >
> > Thanks for your help.
> >
> >
> >
> >
Andrii,

You are right, I'll do so.

Bests.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2019-10-03 18:12 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-01 21:41 [PATCH V12 0/4] BPF: New helper to obtain namespace data from current task Carlos Neira
2019-10-01 21:41 ` [PATCH V12 1/4] fs/nsfs.c: added ns_match Carlos Neira
2019-10-01 21:41 ` [PATCH V12 2/4] bpf: added new helper bpf_get_ns_current_pid_tgid Carlos Neira
2019-10-02 10:52   ` Daniel Borkmann
2019-10-03 14:52     ` Carlos Antonio Neira Bustos
2019-10-03 17:30       ` Andrii Nakryiko
2019-10-03 18:12         ` Carlos Antonio Neira Bustos
2019-10-01 21:41 ` [PATCH V12 3/4] tools: Added bpf_get_ns_current_pid_tgid helper Carlos Neira
2019-10-01 21:41 ` [PATCH V12 4/4] tools/testing/selftests/bpf: Add self-tests for new helper Carlos Neira

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).