Netdev Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH v9 bpf-next 00/14] bpf: Add d_path helper
@ 2020-08-01 17:03 Jiri Olsa
  2020-08-01 17:03 ` [PATCH v9 bpf-next 01/14] tools resolve_btfids: Add size check to get_id function Jiri Olsa
                   ` (13 more replies)
  0 siblings, 14 replies; 38+ messages in thread
From: Jiri Olsa @ 2020-08-01 17:03 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: netdev, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

hi,
adding d_path helper function that returns full path for
given 'struct path' object, which needs to be the kernel
BTF 'path' object. The path is returned in buffer provided
'buf' of size 'sz' and is zero terminated.

  int bpf_d_path(struct path *path, char *buf, u32 sz);

The helper calls directly d_path function, so there's only
limited set of function it can be called from.

The patchset also adds support to add set of BTF IDs for
a helper to define functions that the helper is allowed
to be called from.

Also available at:
  https://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
  bpf/d_path

v9 changes:
  - added few acks
  - added symbol length check to add_set/get_id functions in resolve_btfids [Andrii]
  - used CHECK instead of CHECK_FAIL [Andrii]
  - zero-initialized variables in progs/test_d_path.c [Andrii]
  - simplify d_path test, removed unneeded code [Andrii]
  - added BTF_SET_START_GLOBAL [Andrii]
  - removed "autoconf.h" include in resolve_btfids test [Andrii]
  - simplified resolve_btfids test exit conditions [Andrii]
  - flow changes in btf_struct_ids_match/btf_struct_access
    plus extra check to btf_struct_ids_match [Andrii]
  - changed bpf_d_path code [Al Viro]
  - changed whitelist to allowlist [Andrii]
  - used ARG_CONST_SIZE_OR_ZERO for d_path helper [Andrii]

thanks,
jirka


---
Jiri Olsa (14):
      tools resolve_btfids: Add size check to get_id function
      tools resolve_btfids: Add support for set symbols
      bpf: Move btf_resolve_size into __btf_resolve_size
      bpf: Add elem_id pointer as argument to __btf_resolve_size
      bpf: Add type_id pointer as argument to __btf_resolve_size
      bpf: Remove recursion call in btf_struct_access
      bpf: Factor btf_struct_access function
      bpf: Add btf_struct_ids_match function
      bpf: Add BTF_SET_START/END macros
      bpf: Add d_path helper
      bpf: Update .BTF_ids section in btf.rst with sets info
      selftests/bpf: Add verifier test for d_path helper
      selftests/bpf: Add test for d_path helper
      selftests/bpf: Add set test to resolve_btfids

 Documentation/bpf/btf.rst                               |  25 +++++++++++++++
 include/linux/bpf.h                                     |   6 ++++
 include/linux/btf.h                                     |   3 +-
 include/linux/btf_ids.h                                 |  51 +++++++++++++++++++++++++++++-
 include/uapi/linux/bpf.h                                |  13 ++++++++
 kernel/bpf/bpf_struct_ops.c                             |   6 ++--
 kernel/bpf/btf.c                                        | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
 kernel/bpf/verifier.c                                   |  25 ++++++++++-----
 kernel/trace/bpf_trace.c                                |  48 ++++++++++++++++++++++++++++
 scripts/bpf_helpers_doc.py                              |   2 ++
 tools/bpf/resolve_btfids/main.c                         |  29 +++++++++++++++--
 tools/include/linux/btf_ids.h                           |  51 +++++++++++++++++++++++++++++-
 tools/include/uapi/linux/bpf.h                          |  13 ++++++++
 tools/testing/selftests/bpf/prog_tests/d_path.c         | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/testing/selftests/bpf/prog_tests/resolve_btfids.c |  39 ++++++++++++++++++++++-
 tools/testing/selftests/bpf/progs/test_d_path.c         |  64 +++++++++++++++++++++++++++++++++++++
 tools/testing/selftests/bpf/test_verifier.c             |  19 ++++++++++-
 tools/testing/selftests/bpf/verifier/d_path.c           |  37 ++++++++++++++++++++++
 18 files changed, 698 insertions(+), 43 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/d_path.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_d_path.c
 create mode 100644 tools/testing/selftests/bpf/verifier/d_path.c


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

* [PATCH v9 bpf-next 01/14] tools resolve_btfids: Add size check to get_id function
  2020-08-01 17:03 [PATCH v9 bpf-next 00/14] bpf: Add d_path helper Jiri Olsa
@ 2020-08-01 17:03 ` Jiri Olsa
  2020-08-05  6:00   ` Andrii Nakryiko
  2020-08-01 17:03 ` [PATCH v9 bpf-next 02/14] tools resolve_btfids: Add support for set symbols Jiri Olsa
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 38+ messages in thread
From: Jiri Olsa @ 2020-08-01 17:03 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: netdev, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

To make sure we don't crash on malformed symbols.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/bpf/resolve_btfids/main.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/main.c
index 6956b6350cad..e0929620abc6 100644
--- a/tools/bpf/resolve_btfids/main.c
+++ b/tools/bpf/resolve_btfids/main.c
@@ -199,9 +199,16 @@ static char *get_id(const char *prefix_end)
 	/*
 	 * __BTF_ID__func__vfs_truncate__0
 	 * prefix_end =  ^
+	 * pos        =    ^
 	 */
-	char *p, *id = strdup(prefix_end + sizeof("__") - 1);
+	int len = strlen(prefix_end);
+	int pos = sizeof("__") - 1;
+	char *p, *id;
 
+	if (pos >= len)
+		return NULL;
+
+	id = strdup(prefix_end + pos);
 	if (id) {
 		/*
 		 * __BTF_ID__func__vfs_truncate__0
-- 
2.25.4


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

* [PATCH v9 bpf-next 02/14] tools resolve_btfids: Add support for set symbols
  2020-08-01 17:03 [PATCH v9 bpf-next 00/14] bpf: Add d_path helper Jiri Olsa
  2020-08-01 17:03 ` [PATCH v9 bpf-next 01/14] tools resolve_btfids: Add size check to get_id function Jiri Olsa
@ 2020-08-01 17:03 ` Jiri Olsa
  2020-08-05  6:04   ` Andrii Nakryiko
  2020-08-01 17:03 ` [PATCH v9 bpf-next 03/14] bpf: Move btf_resolve_size into __btf_resolve_size Jiri Olsa
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 38+ messages in thread
From: Jiri Olsa @ 2020-08-01 17:03 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: netdev, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

The set symbol does not have the unique number suffix,
so we need to give it a special parsing function.

This was omitted in the first batch, because there was
no set support yet, so it slipped in the testing.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/bpf/resolve_btfids/main.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/main.c
index e0929620abc6..5ad15ac61aa1 100644
--- a/tools/bpf/resolve_btfids/main.c
+++ b/tools/bpf/resolve_btfids/main.c
@@ -227,6 +227,24 @@ static char *get_id(const char *prefix_end)
 	return id;
 }
 
+static struct btf_id *add_set(struct object *obj, char *name)
+{
+	/*
+	 * __BTF_ID__set__name
+	 * name =    ^
+	 * id   =         ^
+	 */
+	char *id = name + sizeof(BTF_SET "__") - 1;
+	int len = strlen(name);
+
+	if (id >= name + len) {
+		pr_err("FAILED to parse set name: %s\n", name);
+		return NULL;
+	}
+
+	return btf_id__add(&obj->sets, id, true);
+}
+
 static struct btf_id *add_symbol(struct rb_root *root, char *name, size_t size)
 {
 	char *id;
@@ -383,7 +401,7 @@ static int symbols_collect(struct object *obj)
 			id = add_symbol(&obj->funcs, prefix, sizeof(BTF_FUNC) - 1);
 		/* set */
 		} else if (!strncmp(prefix, BTF_SET, sizeof(BTF_SET) - 1)) {
-			id = add_symbol(&obj->sets, prefix, sizeof(BTF_SET) - 1);
+			id = add_set(obj, prefix);
 			/*
 			 * SET objects store list's count, which is encoded
 			 * in symbol's size, together with 'cnt' field hence
-- 
2.25.4


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

* [PATCH v9 bpf-next 03/14] bpf: Move btf_resolve_size into __btf_resolve_size
  2020-08-01 17:03 [PATCH v9 bpf-next 00/14] bpf: Add d_path helper Jiri Olsa
  2020-08-01 17:03 ` [PATCH v9 bpf-next 01/14] tools resolve_btfids: Add size check to get_id function Jiri Olsa
  2020-08-01 17:03 ` [PATCH v9 bpf-next 02/14] tools resolve_btfids: Add support for set symbols Jiri Olsa
@ 2020-08-01 17:03 ` Jiri Olsa
  2020-08-01 17:03 ` [PATCH v9 bpf-next 04/14] bpf: Add elem_id pointer as argument to __btf_resolve_size Jiri Olsa
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 38+ messages in thread
From: Jiri Olsa @ 2020-08-01 17:03 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: netdev, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

Moving btf_resolve_size into __btf_resolve_size and
keeping btf_resolve_size public with just first 3
arguments, because the rest of the arguments are not
used by outside callers.

Following changes are adding more arguments, which
are not useful to outside callers. They will be added
to the __btf_resolve_size function.

Acked-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 include/linux/btf.h         |  3 +--
 kernel/bpf/bpf_struct_ops.c |  6 ++----
 kernel/bpf/btf.c            | 21 ++++++++++++++-------
 3 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/include/linux/btf.h b/include/linux/btf.h
index 8b81fbb4497c..a9af5e7a7ece 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -64,8 +64,7 @@ const struct btf_type *btf_type_resolve_func_ptr(const struct btf *btf,
 						 u32 id, u32 *res_id);
 const struct btf_type *
 btf_resolve_size(const struct btf *btf, const struct btf_type *type,
-		 u32 *type_size, const struct btf_type **elem_type,
-		 u32 *total_nelems);
+		 u32 *type_size);
 
 #define for_each_member(i, struct_type, member)			\
 	for (i = 0, member = btf_type_member(struct_type);	\
diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c
index 969c5d47f81f..4c3b543bb33b 100644
--- a/kernel/bpf/bpf_struct_ops.c
+++ b/kernel/bpf/bpf_struct_ops.c
@@ -298,8 +298,7 @@ static int check_zero_holes(const struct btf_type *t, void *data)
 			return -EINVAL;
 
 		mtype = btf_type_by_id(btf_vmlinux, member->type);
-		mtype = btf_resolve_size(btf_vmlinux, mtype, &msize,
-					 NULL, NULL);
+		mtype = btf_resolve_size(btf_vmlinux, mtype, &msize);
 		if (IS_ERR(mtype))
 			return PTR_ERR(mtype);
 		prev_mend = moff + msize;
@@ -396,8 +395,7 @@ static int bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,
 			u32 msize;
 
 			mtype = btf_type_by_id(btf_vmlinux, member->type);
-			mtype = btf_resolve_size(btf_vmlinux, mtype, &msize,
-						 NULL, NULL);
+			mtype = btf_resolve_size(btf_vmlinux, mtype, &msize);
 			if (IS_ERR(mtype)) {
 				err = PTR_ERR(mtype);
 				goto reset_unlock;
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 0fd6bb62be3a..3c14c9b6676c 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -1088,10 +1088,10 @@ static const struct resolve_vertex *env_stack_peak(struct btf_verifier_env *env)
  * *elem_type: same as return type ("struct X")
  * *total_nelems: 1
  */
-const struct btf_type *
-btf_resolve_size(const struct btf *btf, const struct btf_type *type,
-		 u32 *type_size, const struct btf_type **elem_type,
-		 u32 *total_nelems)
+static const struct btf_type *
+__btf_resolve_size(const struct btf *btf, const struct btf_type *type,
+		   u32 *type_size, const struct btf_type **elem_type,
+		   u32 *total_nelems)
 {
 	const struct btf_type *array_type = NULL;
 	const struct btf_array *array;
@@ -1150,6 +1150,13 @@ btf_resolve_size(const struct btf *btf, const struct btf_type *type,
 	return array_type ? : type;
 }
 
+const struct btf_type *
+btf_resolve_size(const struct btf *btf, const struct btf_type *type,
+		 u32 *type_size)
+{
+	return __btf_resolve_size(btf, type, type_size, NULL, NULL);
+}
+
 /* The input param "type_id" must point to a needs_resolve type */
 static const struct btf_type *btf_type_id_resolve(const struct btf *btf,
 						  u32 *type_id)
@@ -3976,8 +3983,8 @@ int btf_struct_access(struct bpf_verifier_log *log,
 		mtype = btf_type_by_id(btf_vmlinux, member->type);
 		mname = __btf_name_by_offset(btf_vmlinux, member->name_off);
 
-		mtype = btf_resolve_size(btf_vmlinux, mtype, &msize,
-					 &elem_type, &total_nelems);
+		mtype = __btf_resolve_size(btf_vmlinux, mtype, &msize,
+					   &elem_type, &total_nelems);
 		if (IS_ERR(mtype)) {
 			bpf_log(log, "field %s doesn't have size\n", mname);
 			return -EFAULT;
@@ -3991,7 +3998,7 @@ int btf_struct_access(struct bpf_verifier_log *log,
 		if (btf_type_is_array(mtype)) {
 			u32 elem_idx;
 
-			/* btf_resolve_size() above helps to
+			/* __btf_resolve_size() above helps to
 			 * linearize a multi-dimensional array.
 			 *
 			 * The logic here is treating an array
-- 
2.25.4


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

* [PATCH v9 bpf-next 04/14] bpf: Add elem_id pointer as argument to __btf_resolve_size
  2020-08-01 17:03 [PATCH v9 bpf-next 00/14] bpf: Add d_path helper Jiri Olsa
                   ` (2 preceding siblings ...)
  2020-08-01 17:03 ` [PATCH v9 bpf-next 03/14] bpf: Move btf_resolve_size into __btf_resolve_size Jiri Olsa
@ 2020-08-01 17:03 ` Jiri Olsa
  2020-08-01 17:03 ` [PATCH v9 bpf-next 05/14] bpf: Add type_id " Jiri Olsa
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 38+ messages in thread
From: Jiri Olsa @ 2020-08-01 17:03 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: netdev, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

If the resolved type is array, make btf_resolve_size return also
ID of the elem type. It will be needed in following changes.

Acked-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 kernel/bpf/btf.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 3c14c9b6676c..e43aeb80fd91 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -1079,6 +1079,7 @@ static const struct resolve_vertex *env_stack_peak(struct btf_verifier_env *env)
  * *type_size: (x * y * sizeof(u32)).  Hence, *type_size always
  *             corresponds to the return type.
  * *elem_type: u32
+ * *elem_id: id of u32
  * *total_nelems: (x * y).  Hence, individual elem size is
  *                (*type_size / *total_nelems)
  *
@@ -1086,15 +1087,16 @@ static const struct resolve_vertex *env_stack_peak(struct btf_verifier_env *env)
  * return type: type "struct X"
  * *type_size: sizeof(struct X)
  * *elem_type: same as return type ("struct X")
+ * *elem_id: 0
  * *total_nelems: 1
  */
 static const struct btf_type *
 __btf_resolve_size(const struct btf *btf, const struct btf_type *type,
 		   u32 *type_size, const struct btf_type **elem_type,
-		   u32 *total_nelems)
+		   u32 *elem_id, u32 *total_nelems)
 {
 	const struct btf_type *array_type = NULL;
-	const struct btf_array *array;
+	const struct btf_array *array = NULL;
 	u32 i, size, nelems = 1;
 
 	for (i = 0; i < MAX_RESOLVE_DEPTH; i++) {
@@ -1146,6 +1148,8 @@ __btf_resolve_size(const struct btf *btf, const struct btf_type *type,
 		*total_nelems = nelems;
 	if (elem_type)
 		*elem_type = type;
+	if (elem_id)
+		*elem_id = array ? array->type : 0;
 
 	return array_type ? : type;
 }
@@ -3984,7 +3988,7 @@ int btf_struct_access(struct bpf_verifier_log *log,
 		mname = __btf_name_by_offset(btf_vmlinux, member->name_off);
 
 		mtype = __btf_resolve_size(btf_vmlinux, mtype, &msize,
-					   &elem_type, &total_nelems);
+					   &elem_type, NULL, &total_nelems);
 		if (IS_ERR(mtype)) {
 			bpf_log(log, "field %s doesn't have size\n", mname);
 			return -EFAULT;
-- 
2.25.4


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

* [PATCH v9 bpf-next 05/14] bpf: Add type_id pointer as argument to __btf_resolve_size
  2020-08-01 17:03 [PATCH v9 bpf-next 00/14] bpf: Add d_path helper Jiri Olsa
                   ` (3 preceding siblings ...)
  2020-08-01 17:03 ` [PATCH v9 bpf-next 04/14] bpf: Add elem_id pointer as argument to __btf_resolve_size Jiri Olsa
@ 2020-08-01 17:03 ` Jiri Olsa
  2020-08-05  6:05   ` Andrii Nakryiko
  2020-08-01 17:03 ` [PATCH v9 bpf-next 06/14] bpf: Remove recursion call in btf_struct_access Jiri Olsa
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 38+ messages in thread
From: Jiri Olsa @ 2020-08-01 17:03 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: netdev, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

Adding type_id pointer as argument to __btf_resolve_size
to return also BTF ID of the resolved type. It will be
used in following changes.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 kernel/bpf/btf.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index e43aeb80fd91..bc05a24f7361 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -1082,6 +1082,7 @@ static const struct resolve_vertex *env_stack_peak(struct btf_verifier_env *env)
  * *elem_id: id of u32
  * *total_nelems: (x * y).  Hence, individual elem size is
  *                (*type_size / *total_nelems)
+ * *type_id: id of type if it's changed within the function, 0 if not
  *
  * type: is not an array (e.g. const struct X)
  * return type: type "struct X"
@@ -1089,15 +1090,16 @@ static const struct resolve_vertex *env_stack_peak(struct btf_verifier_env *env)
  * *elem_type: same as return type ("struct X")
  * *elem_id: 0
  * *total_nelems: 1
+ * *type_id: id of type if it's changed within the function, 0 if not
  */
 static const struct btf_type *
 __btf_resolve_size(const struct btf *btf, const struct btf_type *type,
 		   u32 *type_size, const struct btf_type **elem_type,
-		   u32 *elem_id, u32 *total_nelems)
+		   u32 *elem_id, u32 *total_nelems, u32 *type_id)
 {
 	const struct btf_type *array_type = NULL;
 	const struct btf_array *array = NULL;
-	u32 i, size, nelems = 1;
+	u32 i, size, nelems = 1, id = 0;
 
 	for (i = 0; i < MAX_RESOLVE_DEPTH; i++) {
 		switch (BTF_INFO_KIND(type->info)) {
@@ -1118,6 +1120,7 @@ __btf_resolve_size(const struct btf *btf, const struct btf_type *type,
 		case BTF_KIND_VOLATILE:
 		case BTF_KIND_CONST:
 		case BTF_KIND_RESTRICT:
+			id = type->type;
 			type = btf_type_by_id(btf, type->type);
 			break;
 
@@ -1150,6 +1153,8 @@ __btf_resolve_size(const struct btf *btf, const struct btf_type *type,
 		*elem_type = type;
 	if (elem_id)
 		*elem_id = array ? array->type : 0;
+	if (type_id && id)
+		*type_id = id;
 
 	return array_type ? : type;
 }
@@ -1158,7 +1163,7 @@ const struct btf_type *
 btf_resolve_size(const struct btf *btf, const struct btf_type *type,
 		 u32 *type_size)
 {
-	return __btf_resolve_size(btf, type, type_size, NULL, NULL);
+	return __btf_resolve_size(btf, type, type_size, NULL, NULL, NULL, NULL);
 }
 
 /* The input param "type_id" must point to a needs_resolve type */
@@ -3988,7 +3993,7 @@ int btf_struct_access(struct bpf_verifier_log *log,
 		mname = __btf_name_by_offset(btf_vmlinux, member->name_off);
 
 		mtype = __btf_resolve_size(btf_vmlinux, mtype, &msize,
-					   &elem_type, NULL, &total_nelems);
+					   &elem_type, NULL, &total_nelems, NULL);
 		if (IS_ERR(mtype)) {
 			bpf_log(log, "field %s doesn't have size\n", mname);
 			return -EFAULT;
-- 
2.25.4


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

* [PATCH v9 bpf-next 06/14] bpf: Remove recursion call in btf_struct_access
  2020-08-01 17:03 [PATCH v9 bpf-next 00/14] bpf: Add d_path helper Jiri Olsa
                   ` (4 preceding siblings ...)
  2020-08-01 17:03 ` [PATCH v9 bpf-next 05/14] bpf: Add type_id " Jiri Olsa
@ 2020-08-01 17:03 ` Jiri Olsa
  2020-08-05  6:12   ` Andrii Nakryiko
  2020-08-01 17:03 ` [PATCH v9 bpf-next 07/14] bpf: Factor btf_struct_access function Jiri Olsa
                   ` (7 subsequent siblings)
  13 siblings, 1 reply; 38+ messages in thread
From: Jiri Olsa @ 2020-08-01 17:03 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: netdev, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

Andrii suggested we can simply jump to again label
instead of making recursion call.

Suggested-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 kernel/bpf/btf.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index bc05a24f7361..0f995038b589 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -3931,14 +3931,13 @@ int btf_struct_access(struct bpf_verifier_log *log,
 		/* Only allow structure for now, can be relaxed for
 		 * other types later.
 		 */
-		elem_type = btf_type_skip_modifiers(btf_vmlinux,
-						    array_elem->type, NULL);
-		if (!btf_type_is_struct(elem_type))
+		t = btf_type_skip_modifiers(btf_vmlinux, array_elem->type,
+					    NULL);
+		if (!btf_type_is_struct(t))
 			goto error;
 
-		off = (off - moff) % elem_type->size;
-		return btf_struct_access(log, elem_type, off, size, atype,
-					 next_btf_id);
+		off = (off - moff) % t->size;
+		goto again;
 
 error:
 		bpf_log(log, "access beyond struct %s at off %u size %u\n",
-- 
2.25.4


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

* [PATCH v9 bpf-next 07/14] bpf: Factor btf_struct_access function
  2020-08-01 17:03 [PATCH v9 bpf-next 00/14] bpf: Add d_path helper Jiri Olsa
                   ` (5 preceding siblings ...)
  2020-08-01 17:03 ` [PATCH v9 bpf-next 06/14] bpf: Remove recursion call in btf_struct_access Jiri Olsa
@ 2020-08-01 17:03 ` Jiri Olsa
  2020-08-05  6:18   ` Andrii Nakryiko
  2020-08-01 17:03 ` [PATCH v9 bpf-next 08/14] bpf: Add btf_struct_ids_match function Jiri Olsa
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 38+ messages in thread
From: Jiri Olsa @ 2020-08-01 17:03 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: netdev, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

Adding btf_struct_walk function that walks through the
struct type + given offset and returns following values:

  enum bpf_struct_walk_result {
       /* < 0 error */
       WALK_SCALAR = 0,
       WALK_PTR,
       WALK_STRUCT,
  };

WALK_SCALAR - when SCALAR_VALUE is found
WALK_PTR    - when pointer value is found, its ID is stored
              in 'next_btf_id' output param
WALK_STRUCT - when nested struct object is found, its ID is stored
              in 'next_btf_id' output param

It will be used in following patches to get all nested
struct objects for given type and offset.

The btf_struct_access now calls btf_struct_walk function,
as long as it gets nested structs as return value.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 kernel/bpf/btf.c | 75 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 65 insertions(+), 10 deletions(-)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 0f995038b589..7bacc2f56061 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -3886,16 +3886,22 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
 	return true;
 }
 
-int btf_struct_access(struct bpf_verifier_log *log,
-		      const struct btf_type *t, int off, int size,
-		      enum bpf_access_type atype,
-		      u32 *next_btf_id)
+enum bpf_struct_walk_result {
+	/* < 0 error */
+	WALK_SCALAR = 0,
+	WALK_PTR,
+	WALK_STRUCT,
+};
+
+static int btf_struct_walk(struct bpf_verifier_log *log,
+			   const struct btf_type *t, int off, int size,
+			   u32 *next_btf_id)
 {
 	u32 i, moff, mtrue_end, msize = 0, total_nelems = 0;
 	const struct btf_type *mtype, *elem_type = NULL;
 	const struct btf_member *member;
 	const char *tname, *mname;
-	u32 vlen;
+	u32 vlen, elem_id, mid;
 
 again:
 	tname = __btf_name_by_offset(btf_vmlinux, t->name_off);
@@ -3966,7 +3972,7 @@ int btf_struct_access(struct bpf_verifier_log *log,
 			 */
 			if (off <= moff &&
 			    BITS_ROUNDUP_BYTES(end_bit) <= off + size)
-				return SCALAR_VALUE;
+				return WALK_SCALAR;
 
 			/* off may be accessing a following member
 			 *
@@ -3988,11 +3994,13 @@ int btf_struct_access(struct bpf_verifier_log *log,
 			break;
 
 		/* type of the field */
+		mid = member->type;
 		mtype = btf_type_by_id(btf_vmlinux, member->type);
 		mname = __btf_name_by_offset(btf_vmlinux, member->name_off);
 
 		mtype = __btf_resolve_size(btf_vmlinux, mtype, &msize,
-					   &elem_type, NULL, &total_nelems, NULL);
+					   &elem_type, &elem_id, &total_nelems,
+					   &mid);
 		if (IS_ERR(mtype)) {
 			bpf_log(log, "field %s doesn't have size\n", mname);
 			return -EFAULT;
@@ -4054,6 +4062,7 @@ int btf_struct_access(struct bpf_verifier_log *log,
 			elem_idx = (off - moff) / msize;
 			moff += elem_idx * msize;
 			mtype = elem_type;
+			mid = elem_id;
 		}
 
 		/* the 'off' we're looking for is either equal to start
@@ -4063,6 +4072,12 @@ int btf_struct_access(struct bpf_verifier_log *log,
 			/* our field must be inside that union or struct */
 			t = mtype;
 
+			/* return if the offset matches the member offset */
+			if (off == moff) {
+				*next_btf_id = mid;
+				return WALK_STRUCT;
+			}
+
 			/* adjust offset we're looking for */
 			off -= moff;
 			goto again;
@@ -4078,11 +4093,10 @@ int btf_struct_access(struct bpf_verifier_log *log,
 					mname, moff, tname, off, size);
 				return -EACCES;
 			}
-
 			stype = btf_type_skip_modifiers(btf_vmlinux, mtype->type, &id);
 			if (btf_type_is_struct(stype)) {
 				*next_btf_id = id;
-				return PTR_TO_BTF_ID;
+				return WALK_PTR;
 			}
 		}
 
@@ -4099,12 +4113,53 @@ int btf_struct_access(struct bpf_verifier_log *log,
 			return -EACCES;
 		}
 
-		return SCALAR_VALUE;
+		return WALK_SCALAR;
 	}
 	bpf_log(log, "struct %s doesn't have field at offset %d\n", tname, off);
 	return -EINVAL;
 }
 
+int btf_struct_access(struct bpf_verifier_log *log,
+		      const struct btf_type *t, int off, int size,
+		      enum bpf_access_type atype __maybe_unused,
+		      u32 *next_btf_id)
+{
+	int err;
+	u32 id;
+
+	do {
+		err = btf_struct_walk(log, t, off, size, &id);
+
+		switch (err) {
+		case WALK_PTR:
+			/* If we found the pointer or scalar on t+off,
+			 * we're done.
+			 */
+			*next_btf_id = id;
+			return PTR_TO_BTF_ID;
+		case WALK_SCALAR:
+			return SCALAR_VALUE;
+		case WALK_STRUCT:
+			/* We found nested struct, so continue the search
+			 * by diving in it. At this point the offset is
+			 * aligned with the new type, so set it to 0.
+			 */
+			t = btf_type_by_id(btf_vmlinux, id);
+			off = 0;
+			break;
+		default:
+			/* It's either error or unknown return value..
+			 * scream and leave.
+			 */
+			if (WARN_ONCE(err > 0, "unknown btf_struct_walk return value"))
+				return -EINVAL;
+			return err;
+		}
+	} while (t);
+
+	return -EINVAL;
+}
+
 int btf_resolve_helper_id(struct bpf_verifier_log *log,
 			  const struct bpf_func_proto *fn, int arg)
 {
-- 
2.25.4


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

* [PATCH v9 bpf-next 08/14] bpf: Add btf_struct_ids_match function
  2020-08-01 17:03 [PATCH v9 bpf-next 00/14] bpf: Add d_path helper Jiri Olsa
                   ` (6 preceding siblings ...)
  2020-08-01 17:03 ` [PATCH v9 bpf-next 07/14] bpf: Factor btf_struct_access function Jiri Olsa
@ 2020-08-01 17:03 ` Jiri Olsa
  2020-08-05  6:27   ` Andrii Nakryiko
  2020-08-01 17:03 ` [PATCH v9 bpf-next 09/14] bpf: Add BTF_SET_START/END macros Jiri Olsa
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 38+ messages in thread
From: Jiri Olsa @ 2020-08-01 17:03 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: netdev, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

Adding btf_struct_ids_match function to check if given address provided
by BTF object + offset is also address of another nested BTF object.

This allows to pass an argument to helper, which is defined via parent
BTF object + offset, like for bpf_d_path (added in following changes):

  SEC("fentry/filp_close")
  int BPF_PROG(prog_close, struct file *file, void *id)
  {
    ...
    ret = bpf_d_path(&file->f_path, ...

The first bpf_d_path argument is hold by verifier as BTF file object
plus offset of f_path member.

The btf_struct_ids_match function will walk the struct file object and
check if there's nested struct path object on the given offset.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 include/linux/bpf.h   |  2 ++
 kernel/bpf/btf.c      | 31 +++++++++++++++++++++++++++++++
 kernel/bpf/verifier.c | 20 +++++++++++++-------
 3 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 40c5e206ecf2..8206d5e324be 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1337,6 +1337,8 @@ int btf_struct_access(struct bpf_verifier_log *log,
 		      const struct btf_type *t, int off, int size,
 		      enum bpf_access_type atype,
 		      u32 *next_btf_id);
+bool btf_struct_ids_match(struct bpf_verifier_log *log,
+			  int off, u32 id, u32 need_type_id);
 int btf_resolve_helper_id(struct bpf_verifier_log *log,
 			  const struct bpf_func_proto *fn, int);
 
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 7bacc2f56061..ba05b15ad599 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -4160,6 +4160,37 @@ int btf_struct_access(struct bpf_verifier_log *log,
 	return -EINVAL;
 }
 
+bool btf_struct_ids_match(struct bpf_verifier_log *log,
+			  int off, u32 id, u32 need_type_id)
+{
+	const struct btf_type *type;
+	int err;
+
+	/* Are we already done? */
+	if (need_type_id == id && off == 0)
+		return true;
+
+again:
+	type = btf_type_by_id(btf_vmlinux, id);
+	if (!type)
+		return false;
+	err = btf_struct_walk(log, type, off, 1, &id);
+	if (err != WALK_STRUCT)
+		return false;
+
+	/* We found nested struct object. If it matches
+	 * the requested ID, we're done. Otherwise let's
+	 * continue the search with offset 0 in the new
+	 * type.
+	 */
+	if (need_type_id != id) {
+		off = 0;
+		goto again;
+	}
+
+	return true;
+}
+
 int btf_resolve_helper_id(struct bpf_verifier_log *log,
 			  const struct bpf_func_proto *fn, int arg)
 {
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index b6ccfce3bf4c..bb6ca19f282d 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -3960,16 +3960,21 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
 				goto err_type;
 		}
 	} else if (arg_type == ARG_PTR_TO_BTF_ID) {
+		bool ids_match = false;
+
 		expected_type = PTR_TO_BTF_ID;
 		if (type != expected_type)
 			goto err_type;
 		if (!fn->check_btf_id) {
-			if (reg->btf_id != meta->btf_id) {
-				verbose(env, "Helper has type %s got %s in R%d\n",
-					kernel_type_name(meta->btf_id),
-					kernel_type_name(reg->btf_id), regno);
-
-				return -EACCES;
+			if (reg->btf_id != meta->btf_id || reg->off) {
+				ids_match = btf_struct_ids_match(&env->log, reg->off, reg->btf_id,
+								 meta->btf_id);
+				if (!ids_match) {
+					verbose(env, "Helper has type %s got %s in R%d\n",
+						kernel_type_name(meta->btf_id),
+						kernel_type_name(reg->btf_id), regno);
+					return -EACCES;
+				}
 			}
 		} else if (!fn->check_btf_id(reg->btf_id, arg)) {
 			verbose(env, "Helper does not support %s in R%d\n",
@@ -3977,7 +3982,8 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
 
 			return -EACCES;
 		}
-		if (!tnum_is_const(reg->var_off) || reg->var_off.value || reg->off) {
+		if (!ids_match &&
+		    (!tnum_is_const(reg->var_off) || reg->var_off.value || reg->off)) {
 			verbose(env, "R%d is a pointer to in-kernel struct with non-zero offset\n",
 				regno);
 			return -EACCES;
-- 
2.25.4


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

* [PATCH v9 bpf-next 09/14] bpf: Add BTF_SET_START/END macros
  2020-08-01 17:03 [PATCH v9 bpf-next 00/14] bpf: Add d_path helper Jiri Olsa
                   ` (7 preceding siblings ...)
  2020-08-01 17:03 ` [PATCH v9 bpf-next 08/14] bpf: Add btf_struct_ids_match function Jiri Olsa
@ 2020-08-01 17:03 ` Jiri Olsa
  2020-08-05  6:29   ` Andrii Nakryiko
  2020-08-01 17:03 ` [PATCH v9 bpf-next 10/14] bpf: Add d_path helper Jiri Olsa
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 38+ messages in thread
From: Jiri Olsa @ 2020-08-01 17:03 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: netdev, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

Adding support to define sorted set of BTF ID values.

Following defines sorted set of BTF ID values:

  BTF_SET_START(btf_allowlist_d_path)
  BTF_ID(func, vfs_truncate)
  BTF_ID(func, vfs_fallocate)
  BTF_ID(func, dentry_open)
  BTF_ID(func, vfs_getattr)
  BTF_ID(func, filp_close)
  BTF_SET_END(btf_allowlist_d_path)

It defines following 'struct btf_id_set' variable to access
values and count:

  struct btf_id_set btf_allowlist_d_path;

Adding 'allowed' callback to struct bpf_func_proto, to allow
verifier the check on allowed callers.

Adding btf_id_set_contains function, which will be used by
allowed callbacks to verify the caller's BTF ID value is
within allowed set.

Also removing extra '\' in __BTF_ID_LIST macro.

Added BTF_SET_START_GLOBAL macro for global sets.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 include/linux/bpf.h           |  4 +++
 include/linux/btf_ids.h       | 51 ++++++++++++++++++++++++++++++++++-
 kernel/bpf/btf.c              | 14 ++++++++++
 kernel/bpf/verifier.c         |  5 ++++
 tools/include/linux/btf_ids.h | 51 ++++++++++++++++++++++++++++++++++-
 5 files changed, 123 insertions(+), 2 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 8206d5e324be..865860d80d39 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -309,6 +309,7 @@ struct bpf_func_proto {
 						    * for this argument.
 						    */
 	int *ret_btf_id; /* return value btf_id */
+	bool (*allowed)(const struct bpf_prog *prog);
 };
 
 /* bpf_context is intentionally undefined structure. Pointer to bpf_context is
@@ -1849,4 +1850,7 @@ enum bpf_text_poke_type {
 int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
 		       void *addr1, void *addr2);
 
+struct btf_id_set;
+bool btf_id_set_contains(struct btf_id_set *set, u32 id);
+
 #endif /* _LINUX_BPF_H */
diff --git a/include/linux/btf_ids.h b/include/linux/btf_ids.h
index 4867d549e3c1..210b086188a3 100644
--- a/include/linux/btf_ids.h
+++ b/include/linux/btf_ids.h
@@ -3,6 +3,11 @@
 #ifndef _LINUX_BTF_IDS_H
 #define _LINUX_BTF_IDS_H
 
+struct btf_id_set {
+	u32 cnt;
+	u32 ids[];
+};
+
 #ifdef CONFIG_DEBUG_INFO_BTF
 
 #include <linux/compiler.h> /* for __PASTE */
@@ -62,7 +67,7 @@ asm(							\
 ".pushsection " BTF_IDS_SECTION ",\"a\";       \n"	\
 "." #scope " " #name ";                        \n"	\
 #name ":;                                      \n"	\
-".popsection;                                  \n");	\
+".popsection;                                  \n");
 
 #define BTF_ID_LIST(name)				\
 __BTF_ID_LIST(name, local)				\
@@ -88,12 +93,56 @@ asm(							\
 ".zero 4                                       \n"	\
 ".popsection;                                  \n");
 
+/*
+ * The BTF_SET_START/END macros pair defines sorted list of
+ * BTF IDs plus its members count, with following layout:
+ *
+ * BTF_SET_START(list)
+ * BTF_ID(type1, name1)
+ * BTF_ID(type2, name2)
+ * BTF_SET_END(list)
+ *
+ * __BTF_ID__set__list:
+ * .zero 4
+ * list:
+ * __BTF_ID__type1__name1__3:
+ * .zero 4
+ * __BTF_ID__type2__name2__4:
+ * .zero 4
+ *
+ */
+#define __BTF_SET_START(name, scope)			\
+asm(							\
+".pushsection " BTF_IDS_SECTION ",\"a\";       \n"	\
+"." #scope " __BTF_ID__set__" #name ";         \n"	\
+"__BTF_ID__set__" #name ":;                    \n"	\
+".zero 4                                       \n"	\
+".popsection;                                  \n");
+
+#define BTF_SET_START(name)				\
+__BTF_ID_LIST(name, local)				\
+__BTF_SET_START(name, local)
+
+#define BTF_SET_START_GLOBAL(name)			\
+__BTF_ID_LIST(name, globl)				\
+__BTF_SET_START(name, globl)
+
+#define BTF_SET_END(name)				\
+asm(							\
+".pushsection " BTF_IDS_SECTION ",\"a\";      \n"	\
+".size __BTF_ID__set__" #name ", .-" #name "  \n"	\
+".popsection;                                 \n");	\
+extern struct btf_id_set name;
+
 #else
 
 #define BTF_ID_LIST(name) static u32 name[5];
 #define BTF_ID(prefix, name)
 #define BTF_ID_UNUSED
 #define BTF_ID_LIST_GLOBAL(name) u32 name[1];
+#define BTF_SET_START(name) static struct btf_id_set name = { 0 };
+#define BTF_SET_START_GLOBAL(name) static struct btf_id_set name = { 0 };
+#define BTF_SET_END(name)
 
 #endif /* CONFIG_DEBUG_INFO_BTF */
 
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index ba05b15ad599..c51caf508d3d 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -21,6 +21,8 @@
 #include <linux/btf_ids.h>
 #include <linux/skmsg.h>
 #include <linux/perf_event.h>
+#include <linux/bsearch.h>
+#include <linux/btf_ids.h>
 #include <net/sock.h>
 
 /* BTF (BPF Type Format) is the meta data format which describes
@@ -4762,3 +4764,15 @@ u32 btf_id(const struct btf *btf)
 {
 	return btf->id;
 }
+
+static int btf_id_cmp_func(const void *a, const void *b)
+{
+	const int *pa = a, *pb = b;
+
+	return *pa - *pb;
+}
+
+bool btf_id_set_contains(struct btf_id_set *set, u32 id)
+{
+	return bsearch(&id, set->ids, set->cnt, sizeof(u32), btf_id_cmp_func) != NULL;
+}
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index bb6ca19f282d..523c5ecc79dd 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -4781,6 +4781,11 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn
 		return -EINVAL;
 	}
 
+	if (fn->allowed && !fn->allowed(env->prog)) {
+		verbose(env, "helper call is not allowed in probe\n");
+		return -EINVAL;
+	}
+
 	/* With LD_ABS/IND some JITs save/restore skb from r1. */
 	changes_data = bpf_helper_changes_pkt_data(fn->func);
 	if (changes_data && fn->arg1_type != ARG_PTR_TO_CTX) {
diff --git a/tools/include/linux/btf_ids.h b/tools/include/linux/btf_ids.h
index 4867d549e3c1..210b086188a3 100644
--- a/tools/include/linux/btf_ids.h
+++ b/tools/include/linux/btf_ids.h
@@ -3,6 +3,11 @@
 #ifndef _LINUX_BTF_IDS_H
 #define _LINUX_BTF_IDS_H
 
+struct btf_id_set {
+	u32 cnt;
+	u32 ids[];
+};
+
 #ifdef CONFIG_DEBUG_INFO_BTF
 
 #include <linux/compiler.h> /* for __PASTE */
@@ -62,7 +67,7 @@ asm(							\
 ".pushsection " BTF_IDS_SECTION ",\"a\";       \n"	\
 "." #scope " " #name ";                        \n"	\
 #name ":;                                      \n"	\
-".popsection;                                  \n");	\
+".popsection;                                  \n");
 
 #define BTF_ID_LIST(name)				\
 __BTF_ID_LIST(name, local)				\
@@ -88,12 +93,56 @@ asm(							\
 ".zero 4                                       \n"	\
 ".popsection;                                  \n");
 
+/*
+ * The BTF_SET_START/END macros pair defines sorted list of
+ * BTF IDs plus its members count, with following layout:
+ *
+ * BTF_SET_START(list)
+ * BTF_ID(type1, name1)
+ * BTF_ID(type2, name2)
+ * BTF_SET_END(list)
+ *
+ * __BTF_ID__set__list:
+ * .zero 4
+ * list:
+ * __BTF_ID__type1__name1__3:
+ * .zero 4
+ * __BTF_ID__type2__name2__4:
+ * .zero 4
+ *
+ */
+#define __BTF_SET_START(name, scope)			\
+asm(							\
+".pushsection " BTF_IDS_SECTION ",\"a\";       \n"	\
+"." #scope " __BTF_ID__set__" #name ";         \n"	\
+"__BTF_ID__set__" #name ":;                    \n"	\
+".zero 4                                       \n"	\
+".popsection;                                  \n");
+
+#define BTF_SET_START(name)				\
+__BTF_ID_LIST(name, local)				\
+__BTF_SET_START(name, local)
+
+#define BTF_SET_START_GLOBAL(name)			\
+__BTF_ID_LIST(name, globl)				\
+__BTF_SET_START(name, globl)
+
+#define BTF_SET_END(name)				\
+asm(							\
+".pushsection " BTF_IDS_SECTION ",\"a\";      \n"	\
+".size __BTF_ID__set__" #name ", .-" #name "  \n"	\
+".popsection;                                 \n");	\
+extern struct btf_id_set name;
+
 #else
 
 #define BTF_ID_LIST(name) static u32 name[5];
 #define BTF_ID(prefix, name)
 #define BTF_ID_UNUSED
 #define BTF_ID_LIST_GLOBAL(name) u32 name[1];
+#define BTF_SET_START(name) static struct btf_id_set name = { 0 };
+#define BTF_SET_START_GLOBAL(name) static struct btf_id_set name = { 0 };
+#define BTF_SET_END(name)
 
 #endif /* CONFIG_DEBUG_INFO_BTF */
 
-- 
2.25.4


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

* [PATCH v9 bpf-next 10/14] bpf: Add d_path helper
  2020-08-01 17:03 [PATCH v9 bpf-next 00/14] bpf: Add d_path helper Jiri Olsa
                   ` (8 preceding siblings ...)
  2020-08-01 17:03 ` [PATCH v9 bpf-next 09/14] bpf: Add BTF_SET_START/END macros Jiri Olsa
@ 2020-08-01 17:03 ` Jiri Olsa
  2020-08-02  3:13   ` Alexei Starovoitov
                     ` (2 more replies)
  2020-08-01 17:03 ` [PATCH v9 bpf-next 11/14] bpf: Update .BTF_ids section in btf.rst with sets info Jiri Olsa
                   ` (3 subsequent siblings)
  13 siblings, 3 replies; 38+ messages in thread
From: Jiri Olsa @ 2020-08-01 17:03 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: netdev, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

Adding d_path helper function that returns full path for
given 'struct path' object, which needs to be the kernel
BTF 'path' object. The path is returned in buffer provided
'buf' of size 'sz' and is zero terminated.

  bpf_d_path(&file->f_path, buf, size);

The helper calls directly d_path function, so there's only
limited set of function it can be called from. Adding just
very modest set for the start.

Updating also bpf.h tools uapi header and adding 'path' to
bpf_helpers_doc.py script.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 include/uapi/linux/bpf.h       | 13 +++++++++
 kernel/trace/bpf_trace.c       | 48 ++++++++++++++++++++++++++++++++++
 scripts/bpf_helpers_doc.py     |  2 ++
 tools/include/uapi/linux/bpf.h | 13 +++++++++
 4 files changed, 76 insertions(+)

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index eb5e0c38eb2c..a356ea1357bf 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -3389,6 +3389,18 @@ union bpf_attr {
  *		A non-negative value equal to or less than *size* on success,
  *		or a negative error in case of failure.
  *
+ * int bpf_d_path(struct path *path, char *buf, u32 sz)
+ *	Description
+ *		Return full path for given 'struct path' object, which
+ *		needs to be the kernel BTF 'path' object. The path is
+ *		returned in buffer provided 'buf' of size 'sz' and
+ *		is zero terminated.
+ *
+ *	Return
+ *		On success, the strictly positive length of the string,
+ *		including the trailing NUL character. On error, a negative
+ *		value.
+ *
  */
 #define __BPF_FUNC_MAPPER(FN)		\
 	FN(unspec),			\
@@ -3533,6 +3545,7 @@ union bpf_attr {
 	FN(skc_to_tcp_request_sock),	\
 	FN(skc_to_udp6_sock),		\
 	FN(get_task_stack),		\
+	FN(d_path),			\
 	/* */
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index cb91ef902cc4..02a76e246545 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -1098,6 +1098,52 @@ static const struct bpf_func_proto bpf_send_signal_thread_proto = {
 	.arg1_type	= ARG_ANYTHING,
 };
 
+BPF_CALL_3(bpf_d_path, struct path *, path, char *, buf, u32, sz)
+{
+	int len;
+	char *p;
+
+	if (!sz)
+		return -ENAMETOOLONG;
+
+	p = d_path(path, buf, sz);
+	if (IS_ERR(p)) {
+		len = PTR_ERR(p);
+	} else {
+		len = buf + sz - p;
+		memmove(buf, p, len);
+	}
+
+	return len;
+}
+
+BTF_SET_START(btf_allowlist_d_path)
+BTF_ID(func, vfs_truncate)
+BTF_ID(func, vfs_fallocate)
+BTF_ID(func, dentry_open)
+BTF_ID(func, vfs_getattr)
+BTF_ID(func, filp_close)
+BTF_SET_END(btf_allowlist_d_path)
+
+static bool bpf_d_path_allowed(const struct bpf_prog *prog)
+{
+	return btf_id_set_contains(&btf_allowlist_d_path, prog->aux->attach_btf_id);
+}
+
+BTF_ID_LIST(bpf_d_path_btf_ids)
+BTF_ID(struct, path)
+
+static const struct bpf_func_proto bpf_d_path_proto = {
+	.func		= bpf_d_path,
+	.gpl_only	= false,
+	.ret_type	= RET_INTEGER,
+	.arg1_type	= ARG_PTR_TO_BTF_ID,
+	.arg2_type	= ARG_PTR_TO_MEM,
+	.arg3_type	= ARG_CONST_SIZE_OR_ZERO,
+	.btf_id		= bpf_d_path_btf_ids,
+	.allowed	= bpf_d_path_allowed,
+};
+
 const struct bpf_func_proto *
 bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 {
@@ -1579,6 +1625,8 @@ tracing_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 		return prog->expected_attach_type == BPF_TRACE_ITER ?
 		       &bpf_seq_write_proto :
 		       NULL;
+	case BPF_FUNC_d_path:
+		return &bpf_d_path_proto;
 	default:
 		return raw_tp_prog_func_proto(func_id, prog);
 	}
diff --git a/scripts/bpf_helpers_doc.py b/scripts/bpf_helpers_doc.py
index 5bfa448b4704..08388173973f 100755
--- a/scripts/bpf_helpers_doc.py
+++ b/scripts/bpf_helpers_doc.py
@@ -432,6 +432,7 @@ class PrinterHelpers(Printer):
             'struct __sk_buff',
             'struct sk_msg_md',
             'struct xdp_md',
+            'struct path',
     ]
     known_types = {
             '...',
@@ -472,6 +473,7 @@ class PrinterHelpers(Printer):
             'struct tcp_request_sock',
             'struct udp6_sock',
             'struct task_struct',
+            'struct path',
     }
     mapped_types = {
             'u8': '__u8',
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index eb5e0c38eb2c..a356ea1357bf 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -3389,6 +3389,18 @@ union bpf_attr {
  *		A non-negative value equal to or less than *size* on success,
  *		or a negative error in case of failure.
  *
+ * int bpf_d_path(struct path *path, char *buf, u32 sz)
+ *	Description
+ *		Return full path for given 'struct path' object, which
+ *		needs to be the kernel BTF 'path' object. The path is
+ *		returned in buffer provided 'buf' of size 'sz' and
+ *		is zero terminated.
+ *
+ *	Return
+ *		On success, the strictly positive length of the string,
+ *		including the trailing NUL character. On error, a negative
+ *		value.
+ *
  */
 #define __BPF_FUNC_MAPPER(FN)		\
 	FN(unspec),			\
@@ -3533,6 +3545,7 @@ union bpf_attr {
 	FN(skc_to_tcp_request_sock),	\
 	FN(skc_to_udp6_sock),		\
 	FN(get_task_stack),		\
+	FN(d_path),			\
 	/* */
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
-- 
2.25.4


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

* [PATCH v9 bpf-next 11/14] bpf: Update .BTF_ids section in btf.rst with sets info
  2020-08-01 17:03 [PATCH v9 bpf-next 00/14] bpf: Add d_path helper Jiri Olsa
                   ` (9 preceding siblings ...)
  2020-08-01 17:03 ` [PATCH v9 bpf-next 10/14] bpf: Add d_path helper Jiri Olsa
@ 2020-08-01 17:03 ` Jiri Olsa
  2020-08-01 17:03 ` [PATCH v9 bpf-next 12/14] selftests/bpf: Add verifier test for d_path helper Jiri Olsa
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 38+ messages in thread
From: Jiri Olsa @ 2020-08-01 17:03 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: netdev, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

Updating btf.rst doc with info about BTF_SET_START/END macros.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 Documentation/bpf/btf.rst | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/Documentation/bpf/btf.rst b/Documentation/bpf/btf.rst
index b5361b8621c9..44dc789de2b4 100644
--- a/Documentation/bpf/btf.rst
+++ b/Documentation/bpf/btf.rst
@@ -724,6 +724,31 @@ want to define unused entry in BTF_ID_LIST, like::
       BTF_ID_UNUSED
       BTF_ID(struct, task_struct)
 
+The ``BTF_SET_START/END`` macros pair defines sorted list of BTF ID values
+and their count, with following syntax::
+
+  BTF_SET_START(set)
+  BTF_ID(type1, name1)
+  BTF_ID(type2, name2)
+  BTF_SET_END(set)
+
+resulting in following layout in .BTF_ids section::
+
+  __BTF_ID__set__set:
+  .zero 4
+  __BTF_ID__type1__name1__3:
+  .zero 4
+  __BTF_ID__type2__name2__4:
+  .zero 4
+
+The ``struct btf_id_set set;`` variable is defined to access the list.
+
+The ``typeX`` name can be one of following::
+
+   struct, union, typedef, func
+
+and is used as a filter when resolving the BTF ID value.
+
 All the BTF ID lists and sets are compiled in the .BTF_ids section and
 resolved during the linking phase of kernel build by ``resolve_btfids`` tool.
 
-- 
2.25.4


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

* [PATCH v9 bpf-next 12/14] selftests/bpf: Add verifier test for d_path helper
  2020-08-01 17:03 [PATCH v9 bpf-next 00/14] bpf: Add d_path helper Jiri Olsa
                   ` (10 preceding siblings ...)
  2020-08-01 17:03 ` [PATCH v9 bpf-next 11/14] bpf: Update .BTF_ids section in btf.rst with sets info Jiri Olsa
@ 2020-08-01 17:03 ` Jiri Olsa
  2020-08-01 17:03 ` [PATCH v9 bpf-next 13/14] selftests/bpf: Add " Jiri Olsa
  2020-08-01 17:03 ` [PATCH v9 bpf-next 14/14] selftests/bpf: Add set test to resolve_btfids Jiri Olsa
  13 siblings, 0 replies; 38+ messages in thread
From: Jiri Olsa @ 2020-08-01 17:03 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: netdev, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

Adding verifier test for attaching tracing program and
calling d_path helper from within and testing that it's
allowed for dentry_open function and denied for 'd_path'
function with appropriate error.

Acked-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/testing/selftests/bpf/test_verifier.c   | 19 +++++++++-
 tools/testing/selftests/bpf/verifier/d_path.c | 37 +++++++++++++++++++
 2 files changed, 55 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/bpf/verifier/d_path.c

diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 78a6bae56ea6..9be395d9dc64 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -114,6 +114,7 @@ struct bpf_test {
 		bpf_testdata_struct_t retvals[MAX_TEST_RUNS];
 	};
 	enum bpf_attach_type expected_attach_type;
+	const char *kfunc;
 };
 
 /* Note we want this to be 64 bit aligned so that the end of our array is
@@ -984,8 +985,24 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
 		attr.log_level = 4;
 	attr.prog_flags = pflags;
 
+	if (prog_type == BPF_PROG_TYPE_TRACING && test->kfunc) {
+		attr.attach_btf_id = libbpf_find_vmlinux_btf_id(test->kfunc,
+						attr.expected_attach_type);
+		if (attr.attach_btf_id < 0) {
+			printf("FAIL\nFailed to find BTF ID for '%s'!\n",
+				test->kfunc);
+			(*errors)++;
+			return;
+		}
+	}
+
 	fd_prog = bpf_load_program_xattr(&attr, bpf_vlog, sizeof(bpf_vlog));
-	if (fd_prog < 0 && !bpf_probe_prog_type(prog_type, 0)) {
+
+	/* BPF_PROG_TYPE_TRACING requires more setup and
+	 * bpf_probe_prog_type won't give correct answer
+	 */
+	if (fd_prog < 0 && prog_type != BPF_PROG_TYPE_TRACING &&
+	    !bpf_probe_prog_type(prog_type, 0)) {
 		printf("SKIP (unsupported program type %d)\n", prog_type);
 		skips++;
 		goto close_fds;
diff --git a/tools/testing/selftests/bpf/verifier/d_path.c b/tools/testing/selftests/bpf/verifier/d_path.c
new file mode 100644
index 000000000000..b988396379a7
--- /dev/null
+++ b/tools/testing/selftests/bpf/verifier/d_path.c
@@ -0,0 +1,37 @@
+{
+	"d_path accept",
+	.insns = {
+	BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_1, 0),
+	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+	BPF_MOV64_IMM(BPF_REG_6, 0),
+	BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 0),
+	BPF_LD_IMM64(BPF_REG_3, 8),
+	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_d_path),
+	BPF_MOV64_IMM(BPF_REG_0, 0),
+	BPF_EXIT_INSN(),
+	},
+	.result = ACCEPT,
+	.prog_type = BPF_PROG_TYPE_TRACING,
+	.expected_attach_type = BPF_TRACE_FENTRY,
+	.kfunc = "dentry_open",
+},
+{
+	"d_path reject",
+	.insns = {
+	BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_1, 0),
+	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+	BPF_MOV64_IMM(BPF_REG_6, 0),
+	BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 0),
+	BPF_LD_IMM64(BPF_REG_3, 8),
+	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_d_path),
+	BPF_MOV64_IMM(BPF_REG_0, 0),
+	BPF_EXIT_INSN(),
+	},
+	.errstr = "helper call is not allowed in probe",
+	.result = REJECT,
+	.prog_type = BPF_PROG_TYPE_TRACING,
+	.expected_attach_type = BPF_TRACE_FENTRY,
+	.kfunc = "d_path",
+},
-- 
2.25.4


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

* [PATCH v9 bpf-next 13/14] selftests/bpf: Add test for d_path helper
  2020-08-01 17:03 [PATCH v9 bpf-next 00/14] bpf: Add d_path helper Jiri Olsa
                   ` (11 preceding siblings ...)
  2020-08-01 17:03 ` [PATCH v9 bpf-next 12/14] selftests/bpf: Add verifier test for d_path helper Jiri Olsa
@ 2020-08-01 17:03 ` Jiri Olsa
  2020-08-05  6:40   ` Andrii Nakryiko
  2020-08-01 17:03 ` [PATCH v9 bpf-next 14/14] selftests/bpf: Add set test to resolve_btfids Jiri Olsa
  13 siblings, 1 reply; 38+ messages in thread
From: Jiri Olsa @ 2020-08-01 17:03 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: Wenbo Zhang, netdev, bpf, Song Liu, Yonghong Song,
	Martin KaFai Lau, David Miller, John Fastabend, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

Adding test for d_path helper which is pretty much
copied from Wenbo Zhang's test for bpf_get_fd_path,
which never made it in.

The test is doing fstat/close on several fd types,
and verifies we got the d_path helper working on
kernel probes for vfs_getattr/filp_close functions.

Original-patch-by: Wenbo Zhang <ethercflow@gmail.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 .../testing/selftests/bpf/prog_tests/d_path.c | 147 ++++++++++++++++++
 .../testing/selftests/bpf/progs/test_d_path.c |  64 ++++++++
 2 files changed, 211 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/d_path.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_d_path.c

diff --git a/tools/testing/selftests/bpf/prog_tests/d_path.c b/tools/testing/selftests/bpf/prog_tests/d_path.c
new file mode 100644
index 000000000000..058765da17e6
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/d_path.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+#include <test_progs.h>
+#include <sys/stat.h>
+#include <linux/sched.h>
+#include <sys/syscall.h>
+
+#define MAX_PATH_LEN		128
+#define MAX_FILES		7
+
+#include "test_d_path.skel.h"
+
+static int duration;
+
+static struct {
+	__u32 cnt;
+	char paths[MAX_FILES][MAX_PATH_LEN];
+} src;
+
+static int set_pathname(int fd, pid_t pid)
+{
+	char buf[MAX_PATH_LEN];
+
+	snprintf(buf, MAX_PATH_LEN, "/proc/%d/fd/%d", pid, fd);
+	return readlink(buf, src.paths[src.cnt++], MAX_PATH_LEN);
+}
+
+static int trigger_fstat_events(pid_t pid)
+{
+	int sockfd = -1, procfd = -1, devfd = -1;
+	int localfd = -1, indicatorfd = -1;
+	int pipefd[2] = { -1, -1 };
+	struct stat fileStat;
+	int ret = -1;
+
+	/* unmountable pseudo-filesystems */
+	if (CHECK(pipe(pipefd) < 0, "trigger", "pipe failed\n"))
+		return ret;
+	/* unmountable pseudo-filesystems */
+	sockfd = socket(AF_INET, SOCK_STREAM, 0);
+	if (CHECK(sockfd < 0, "trigger", "scoket failed\n"))
+		goto out_close;
+	/* mountable pseudo-filesystems */
+	procfd = open("/proc/self/comm", O_RDONLY);
+	if (CHECK(procfd < 0, "trigger", "open /proc/self/comm failed\n"))
+		goto out_close;
+	devfd = open("/dev/urandom", O_RDONLY);
+	if (CHECK(devfd < 0, "trigger", "open /dev/urandom failed\n"))
+		goto out_close;
+	localfd = open("/tmp/d_path_loadgen.txt", O_CREAT | O_RDONLY);
+	if (CHECK(localfd < 0, "trigger", "open /tmp/d_path_loadgen.txt failed\n"))
+		goto out_close;
+	/* bpf_d_path will return path with (deleted) */
+	remove("/tmp/d_path_loadgen.txt");
+	indicatorfd = open("/tmp/", O_PATH);
+	if (CHECK(indicatorfd < 0, "trigger", "open /tmp/ failed\n"))
+		goto out_close;
+
+	ret = set_pathname(pipefd[0], pid);
+	if (CHECK(ret < 0, "trigger", "set_pathname failed for pipe[0]\n"))
+		goto out_close;
+	ret = set_pathname(pipefd[1], pid);
+	if (CHECK(ret < 0, "trigger", "set_pathname failed for pipe[1]\n"))
+		goto out_close;
+	ret = set_pathname(sockfd, pid);
+	if (CHECK(ret < 0, "trigger", "set_pathname failed for socket\n"))
+		goto out_close;
+	ret = set_pathname(procfd, pid);
+	if (CHECK(ret < 0, "trigger", "set_pathname failed for proc\n"))
+		goto out_close;
+	ret = set_pathname(devfd, pid);
+	if (CHECK(ret < 0, "trigger", "set_pathname failed for dev\n"))
+		goto out_close;
+	ret = set_pathname(localfd, pid);
+	if (CHECK(ret < 0, "trigger", "set_pathname failed for file\n"))
+		goto out_close;
+	ret = set_pathname(indicatorfd, pid);
+	if (CHECK(ret < 0, "trigger", "set_pathname failed for dir\n"))
+		goto out_close;
+
+	/* triggers vfs_getattr */
+	fstat(pipefd[0], &fileStat);
+	fstat(pipefd[1], &fileStat);
+	fstat(sockfd, &fileStat);
+	fstat(procfd, &fileStat);
+	fstat(devfd, &fileStat);
+	fstat(localfd, &fileStat);
+	fstat(indicatorfd, &fileStat);
+
+out_close:
+	/* triggers filp_close */
+	close(pipefd[0]);
+	close(pipefd[1]);
+	close(sockfd);
+	close(procfd);
+	close(devfd);
+	close(localfd);
+	close(indicatorfd);
+	return ret;
+}
+
+void test_d_path(void)
+{
+	struct test_d_path__bss *bss;
+	struct test_d_path *skel;
+	int err;
+
+	skel = test_d_path__open_and_load();
+	if (CHECK(!skel, "setup", "d_path skeleton failed\n"))
+		goto cleanup;
+
+	err = test_d_path__attach(skel);
+	if (CHECK(err, "setup", "attach failed: %d\n", err))
+		goto cleanup;
+
+	bss = skel->bss;
+	bss->my_pid = getpid();
+
+	err = trigger_fstat_events(bss->my_pid);
+	if (err < 0)
+		goto cleanup;
+
+	for (int i = 0; i < MAX_FILES; i++) {
+		CHECK(strncmp(src.paths[i], bss->paths_stat[i], MAX_PATH_LEN),
+		      "check",
+		      "failed to get stat path[%d]: %s vs %s\n",
+		      i, src.paths[i], bss->paths_stat[i]);
+		CHECK(strncmp(src.paths[i], bss->paths_close[i], MAX_PATH_LEN),
+		      "check",
+		      "failed to get close path[%d]: %s vs %s\n",
+		      i, src.paths[i], bss->paths_close[i]);
+		/* The d_path helper returns size plus NUL char, hence + 1 */
+		CHECK(bss->rets_stat[i] != strlen(bss->paths_stat[i]) + 1,
+		      "check",
+		      "failed to match stat return [%d]: %d vs %zd [%s]\n",
+		      i, bss->rets_stat[i], strlen(bss->paths_stat[i]) + 1,
+		      bss->paths_stat[i]);
+		CHECK(bss->rets_close[i] != strlen(bss->paths_stat[i]) + 1,
+		      "check",
+		      "failed to match stat return [%d]: %d vs %zd [%s]\n",
+		      i, bss->rets_close[i], strlen(bss->paths_close[i]) + 1,
+		      bss->paths_stat[i]);
+	}
+
+cleanup:
+	test_d_path__destroy(skel);
+}
diff --git a/tools/testing/selftests/bpf/progs/test_d_path.c b/tools/testing/selftests/bpf/progs/test_d_path.c
new file mode 100644
index 000000000000..9d342d7a1de6
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_d_path.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+#define MAX_PATH_LEN		128
+#define MAX_FILES		7
+
+pid_t my_pid = 0;
+__u32 cnt_stat = 0;
+__u32 cnt_close = 0;
+char paths_stat[MAX_FILES][MAX_PATH_LEN] = {};
+char paths_close[MAX_FILES][MAX_PATH_LEN] = {};
+int rets_stat[MAX_FILES] = {};
+int rets_close[MAX_FILES] = {};
+
+SEC("fentry/vfs_getattr")
+int BPF_PROG(prog_stat, struct path *path, struct kstat *stat,
+	     __u32 request_mask, unsigned int query_flags)
+{
+	pid_t pid = bpf_get_current_pid_tgid() >> 32;
+	int ret;
+
+	if (pid != my_pid)
+		return 0;
+
+	if (cnt_stat >= MAX_FILES)
+		return 0;
+	ret = bpf_d_path(path, paths_stat[cnt_stat], MAX_PATH_LEN);
+
+	/* We need to recheck cnt_stat for verifier. */
+	if (cnt_stat >= MAX_FILES)
+		return 0;
+	rets_stat[cnt_stat] = ret;
+
+	cnt_stat++;
+	return 0;
+}
+
+SEC("fentry/filp_close")
+int BPF_PROG(prog_close, struct file *file, void *id)
+{
+	pid_t pid = bpf_get_current_pid_tgid() >> 32;
+	int ret;
+
+	if (pid != my_pid)
+		return 0;
+
+	if (cnt_close >= MAX_FILES)
+		return 0;
+	ret = bpf_d_path(&file->f_path,
+			 paths_close[cnt_close], MAX_PATH_LEN);
+
+	/* We need to recheck cnt_stat for verifier. */
+	if (cnt_close >= MAX_FILES)
+		return 0;
+	rets_close[cnt_close] = ret;
+
+	cnt_close++;
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";
-- 
2.25.4


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

* [PATCH v9 bpf-next 14/14] selftests/bpf: Add set test to resolve_btfids
  2020-08-01 17:03 [PATCH v9 bpf-next 00/14] bpf: Add d_path helper Jiri Olsa
                   ` (12 preceding siblings ...)
  2020-08-01 17:03 ` [PATCH v9 bpf-next 13/14] selftests/bpf: Add " Jiri Olsa
@ 2020-08-01 17:03 ` Jiri Olsa
  2020-08-05  6:41   ` Andrii Nakryiko
  13 siblings, 1 reply; 38+ messages in thread
From: Jiri Olsa @ 2020-08-01 17:03 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: netdev, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

Adding test to for sets resolve_btfids. We're checking that
testing set gets properly resolved and sorted.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 .../selftests/bpf/prog_tests/resolve_btfids.c | 39 ++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/bpf/prog_tests/resolve_btfids.c b/tools/testing/selftests/bpf/prog_tests/resolve_btfids.c
index 3b127cab4864..8826c652adad 100644
--- a/tools/testing/selftests/bpf/prog_tests/resolve_btfids.c
+++ b/tools/testing/selftests/bpf/prog_tests/resolve_btfids.c
@@ -47,6 +47,15 @@ BTF_ID(struct,  S)
 BTF_ID(union,   U)
 BTF_ID(func,    func)
 
+BTF_SET_START(test_set)
+BTF_ID(typedef, S)
+BTF_ID(typedef, T)
+BTF_ID(typedef, U)
+BTF_ID(struct,  S)
+BTF_ID(union,   U)
+BTF_ID(func,    func)
+BTF_SET_END(test_set)
+
 static int
 __resolve_symbol(struct btf *btf, int type_id)
 {
@@ -116,12 +125,40 @@ int test_resolve_btfids(void)
 	 */
 	for (j = 0; j < ARRAY_SIZE(test_lists); j++) {
 		test_list = test_lists[j];
-		for (i = 0; i < ARRAY_SIZE(test_symbols) && !ret; i++) {
+		for (i = 0; i < ARRAY_SIZE(test_symbols); i++) {
 			ret = CHECK(test_list[i] != test_symbols[i].id,
 				    "id_check",
 				    "wrong ID for %s (%d != %d)\n",
 				    test_symbols[i].name,
 				    test_list[i], test_symbols[i].id);
+			if (ret)
+				return ret;
+		}
+	}
+
+	/* Check BTF_SET_START(test_set) IDs */
+	for (i = 0; i < test_set.cnt; i++) {
+		bool found = false;
+
+		for (j = 0; j < ARRAY_SIZE(test_symbols); j++) {
+			if (test_symbols[j].id != test_set.ids[i])
+				continue;
+			found = true;
+			break;
+		}
+
+		ret = CHECK(!found, "id_check",
+			    "ID %d not found in test_symbols\n",
+			    test_set.ids[i]);
+		if (ret)
+			break;
+
+		if (i > 0) {
+			ret = CHECK(test_set.ids[i - 1] > test_set.ids[i],
+				    "sort_check",
+				    "test_set is not sorted\n");
+			if (ret)
+				break;
 		}
 	}
 
-- 
2.25.4


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

* Re: [PATCH v9 bpf-next 10/14] bpf: Add d_path helper
  2020-08-01 17:03 ` [PATCH v9 bpf-next 10/14] bpf: Add d_path helper Jiri Olsa
@ 2020-08-02  3:13   ` Alexei Starovoitov
  2020-08-02 18:26     ` Jiri Olsa
  2020-08-05  6:35   ` Andrii Nakryiko
  2020-08-07  0:31   ` KP Singh
  2 siblings, 1 reply; 38+ messages in thread
From: Alexei Starovoitov @ 2020-08-02  3:13 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, netdev,
	bpf, Song Liu, Yonghong Song, Martin KaFai Lau, David Miller,
	John Fastabend, Wenbo Zhang, KP Singh, Brendan Gregg,
	Florent Revest, Al Viro

On Sat, Aug 01, 2020 at 07:03:18PM +0200, Jiri Olsa wrote:
> Adding d_path helper function that returns full path for
> given 'struct path' object, which needs to be the kernel
> BTF 'path' object. The path is returned in buffer provided
> 'buf' of size 'sz' and is zero terminated.
> 
>   bpf_d_path(&file->f_path, buf, size);
> 
> The helper calls directly d_path function, so there's only
> limited set of function it can be called from. Adding just
> very modest set for the start.
> 
> Updating also bpf.h tools uapi header and adding 'path' to
> bpf_helpers_doc.py script.
> 
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  include/uapi/linux/bpf.h       | 13 +++++++++
>  kernel/trace/bpf_trace.c       | 48 ++++++++++++++++++++++++++++++++++
>  scripts/bpf_helpers_doc.py     |  2 ++
>  tools/include/uapi/linux/bpf.h | 13 +++++++++
>  4 files changed, 76 insertions(+)
> 
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index eb5e0c38eb2c..a356ea1357bf 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -3389,6 +3389,18 @@ union bpf_attr {
>   *		A non-negative value equal to or less than *size* on success,
>   *		or a negative error in case of failure.
>   *
> + * int bpf_d_path(struct path *path, char *buf, u32 sz)

Please make it return 'long'. As you well ware the generated code will be better.

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

* Re: [PATCH v9 bpf-next 10/14] bpf: Add d_path helper
  2020-08-02  3:13   ` Alexei Starovoitov
@ 2020-08-02 18:26     ` Jiri Olsa
  0 siblings, 0 replies; 38+ messages in thread
From: Jiri Olsa @ 2020-08-02 18:26 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Jiri Olsa, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	netdev, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

On Sat, Aug 01, 2020 at 08:13:42PM -0700, Alexei Starovoitov wrote:
> On Sat, Aug 01, 2020 at 07:03:18PM +0200, Jiri Olsa wrote:
> > Adding d_path helper function that returns full path for
> > given 'struct path' object, which needs to be the kernel
> > BTF 'path' object. The path is returned in buffer provided
> > 'buf' of size 'sz' and is zero terminated.
> > 
> >   bpf_d_path(&file->f_path, buf, size);
> > 
> > The helper calls directly d_path function, so there's only
> > limited set of function it can be called from. Adding just
> > very modest set for the start.
> > 
> > Updating also bpf.h tools uapi header and adding 'path' to
> > bpf_helpers_doc.py script.
> > 
> > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > ---
> >  include/uapi/linux/bpf.h       | 13 +++++++++
> >  kernel/trace/bpf_trace.c       | 48 ++++++++++++++++++++++++++++++++++
> >  scripts/bpf_helpers_doc.py     |  2 ++
> >  tools/include/uapi/linux/bpf.h | 13 +++++++++
> >  4 files changed, 76 insertions(+)
> > 
> > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > index eb5e0c38eb2c..a356ea1357bf 100644
> > --- a/include/uapi/linux/bpf.h
> > +++ b/include/uapi/linux/bpf.h
> > @@ -3389,6 +3389,18 @@ union bpf_attr {
> >   *		A non-negative value equal to or less than *size* on success,
> >   *		or a negative error in case of failure.
> >   *
> > + * int bpf_d_path(struct path *path, char *buf, u32 sz)
> 
> Please make it return 'long'. As you well ware the generated code will be better.
> 

will do, thanks

jirka


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

* Re: [PATCH v9 bpf-next 01/14] tools resolve_btfids: Add size check to get_id function
  2020-08-01 17:03 ` [PATCH v9 bpf-next 01/14] tools resolve_btfids: Add size check to get_id function Jiri Olsa
@ 2020-08-05  6:00   ` Andrii Nakryiko
  0 siblings, 0 replies; 38+ messages in thread
From: Andrii Nakryiko @ 2020-08-05  6:00 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Networking,
	bpf, Song Liu, Yonghong Song, Martin KaFai Lau, David Miller,
	John Fastabend, Wenbo Zhang, KP Singh, Brendan Gregg,
	Florent Revest, Al Viro

On Sat, Aug 1, 2020 at 10:04 AM Jiri Olsa <jolsa@kernel.org> wrote:
>
> To make sure we don't crash on malformed symbols.
>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---

Acked-by: Andrii Nakryiko <andriin@fb.com>

>  tools/bpf/resolve_btfids/main.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
>

[...]

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

* Re: [PATCH v9 bpf-next 02/14] tools resolve_btfids: Add support for set symbols
  2020-08-01 17:03 ` [PATCH v9 bpf-next 02/14] tools resolve_btfids: Add support for set symbols Jiri Olsa
@ 2020-08-05  6:04   ` Andrii Nakryiko
  0 siblings, 0 replies; 38+ messages in thread
From: Andrii Nakryiko @ 2020-08-05  6:04 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Networking,
	bpf, Song Liu, Yonghong Song, Martin KaFai Lau, David Miller,
	John Fastabend, Wenbo Zhang, KP Singh, Brendan Gregg,
	Florent Revest, Al Viro

On Sat, Aug 1, 2020 at 10:04 AM Jiri Olsa <jolsa@kernel.org> wrote:
>
> The set symbol does not have the unique number suffix,
> so we need to give it a special parsing function.
>
> This was omitted in the first batch, because there was
> no set support yet, so it slipped in the testing.
>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---

Acked-by: Andrii Nakryiko <andriin@fb.com>

>  tools/bpf/resolve_btfids/main.c | 20 +++++++++++++++++++-
>  1 file changed, 19 insertions(+), 1 deletion(-)
>

[...]

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

* Re: [PATCH v9 bpf-next 05/14] bpf: Add type_id pointer as argument to __btf_resolve_size
  2020-08-01 17:03 ` [PATCH v9 bpf-next 05/14] bpf: Add type_id " Jiri Olsa
@ 2020-08-05  6:05   ` Andrii Nakryiko
  0 siblings, 0 replies; 38+ messages in thread
From: Andrii Nakryiko @ 2020-08-05  6:05 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Networking,
	bpf, Song Liu, Yonghong Song, Martin KaFai Lau, David Miller,
	John Fastabend, Wenbo Zhang, KP Singh, Brendan Gregg,
	Florent Revest, Al Viro

On Sat, Aug 1, 2020 at 10:04 AM Jiri Olsa <jolsa@kernel.org> wrote:
>
> Adding type_id pointer as argument to __btf_resolve_size
> to return also BTF ID of the resolved type. It will be
> used in following changes.
>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---

Acked-by: Andrii Nakryiko <andriin@fb.com>

>  kernel/bpf/btf.c | 13 +++++++++----
>  1 file changed, 9 insertions(+), 4 deletions(-)
>

[...]

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

* Re: [PATCH v9 bpf-next 06/14] bpf: Remove recursion call in btf_struct_access
  2020-08-01 17:03 ` [PATCH v9 bpf-next 06/14] bpf: Remove recursion call in btf_struct_access Jiri Olsa
@ 2020-08-05  6:12   ` Andrii Nakryiko
  2020-08-05 17:36     ` Jiri Olsa
  0 siblings, 1 reply; 38+ messages in thread
From: Andrii Nakryiko @ 2020-08-05  6:12 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Networking,
	bpf, Song Liu, Yonghong Song, Martin KaFai Lau, David Miller,
	John Fastabend, Wenbo Zhang, KP Singh, Brendan Gregg,
	Florent Revest, Al Viro

On Sat, Aug 1, 2020 at 10:04 AM Jiri Olsa <jolsa@kernel.org> wrote:
>
> Andrii suggested we can simply jump to again label
> instead of making recursion call.
>
> Suggested-by: Andrii Nakryiko <andriin@fb.com>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  kernel/bpf/btf.c | 11 +++++------
>  1 file changed, 5 insertions(+), 6 deletions(-)
>
> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> index bc05a24f7361..0f995038b589 100644
> --- a/kernel/bpf/btf.c
> +++ b/kernel/bpf/btf.c
> @@ -3931,14 +3931,13 @@ int btf_struct_access(struct bpf_verifier_log *log,
>                 /* Only allow structure for now, can be relaxed for
>                  * other types later.
>                  */
> -               elem_type = btf_type_skip_modifiers(btf_vmlinux,
> -                                                   array_elem->type, NULL);
> -               if (!btf_type_is_struct(elem_type))
> +               t = btf_type_skip_modifiers(btf_vmlinux, array_elem->type,
> +                                           NULL);
> +               if (!btf_type_is_struct(t))
>                         goto error;
>
> -               off = (off - moff) % elem_type->size;
> -               return btf_struct_access(log, elem_type, off, size, atype,
> -                                        next_btf_id);
> +               off = (off - moff) % t->size;
> +               goto again;

Transformation looks good, thanks. So:

Acked-by: Andrii Nakryiko <andriin@fb.com>

But this '% t->size' makes me wonder what will happen when we have an
array of zero-sized structs or multi-dimensional arrays with
dimensions of size 0... I.e.:

struct {} arr[123];

or

int arr[0][0]0];

We should probably be more careful with division here.

>
>  error:
>                 bpf_log(log, "access beyond struct %s at off %u size %u\n",
> --
> 2.25.4
>

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

* Re: [PATCH v9 bpf-next 07/14] bpf: Factor btf_struct_access function
  2020-08-01 17:03 ` [PATCH v9 bpf-next 07/14] bpf: Factor btf_struct_access function Jiri Olsa
@ 2020-08-05  6:18   ` Andrii Nakryiko
  0 siblings, 0 replies; 38+ messages in thread
From: Andrii Nakryiko @ 2020-08-05  6:18 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Networking,
	bpf, Song Liu, Yonghong Song, Martin KaFai Lau, David Miller,
	John Fastabend, Wenbo Zhang, KP Singh, Brendan Gregg,
	Florent Revest, Al Viro

On Sat, Aug 1, 2020 at 10:04 AM Jiri Olsa <jolsa@kernel.org> wrote:
>
> Adding btf_struct_walk function that walks through the
> struct type + given offset and returns following values:
>
>   enum bpf_struct_walk_result {
>        /* < 0 error */
>        WALK_SCALAR = 0,
>        WALK_PTR,
>        WALK_STRUCT,
>   };
>
> WALK_SCALAR - when SCALAR_VALUE is found
> WALK_PTR    - when pointer value is found, its ID is stored
>               in 'next_btf_id' output param
> WALK_STRUCT - when nested struct object is found, its ID is stored
>               in 'next_btf_id' output param
>
> It will be used in following patches to get all nested
> struct objects for given type and offset.
>
> The btf_struct_access now calls btf_struct_walk function,
> as long as it gets nested structs as return value.
>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---

This turned out to be rather much more succinct and clean than I
imagined when I was originally proposing the struct iteration idea.
Great job at abstracting this!

Acked-by: Andrii Nakryiko <andriin@fb.com>

>  kernel/bpf/btf.c | 75 +++++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 65 insertions(+), 10 deletions(-)
>

[...]

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

* Re: [PATCH v9 bpf-next 08/14] bpf: Add btf_struct_ids_match function
  2020-08-01 17:03 ` [PATCH v9 bpf-next 08/14] bpf: Add btf_struct_ids_match function Jiri Olsa
@ 2020-08-05  6:27   ` Andrii Nakryiko
  2020-08-05 17:56     ` Jiri Olsa
  0 siblings, 1 reply; 38+ messages in thread
From: Andrii Nakryiko @ 2020-08-05  6:27 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Networking,
	bpf, Song Liu, Yonghong Song, Martin KaFai Lau, David Miller,
	John Fastabend, Wenbo Zhang, KP Singh, Brendan Gregg,
	Florent Revest, Al Viro

On Sat, Aug 1, 2020 at 10:04 AM Jiri Olsa <jolsa@kernel.org> wrote:
>
> Adding btf_struct_ids_match function to check if given address provided
> by BTF object + offset is also address of another nested BTF object.
>
> This allows to pass an argument to helper, which is defined via parent
> BTF object + offset, like for bpf_d_path (added in following changes):
>
>   SEC("fentry/filp_close")
>   int BPF_PROG(prog_close, struct file *file, void *id)
>   {
>     ...
>     ret = bpf_d_path(&file->f_path, ...
>
> The first bpf_d_path argument is hold by verifier as BTF file object
> plus offset of f_path member.
>
> The btf_struct_ids_match function will walk the struct file object and
> check if there's nested struct path object on the given offset.
>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  include/linux/bpf.h   |  2 ++
>  kernel/bpf/btf.c      | 31 +++++++++++++++++++++++++++++++
>  kernel/bpf/verifier.c | 20 +++++++++++++-------
>  3 files changed, 46 insertions(+), 7 deletions(-)
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index 40c5e206ecf2..8206d5e324be 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -1337,6 +1337,8 @@ int btf_struct_access(struct bpf_verifier_log *log,
>                       const struct btf_type *t, int off, int size,
>                       enum bpf_access_type atype,
>                       u32 *next_btf_id);
> +bool btf_struct_ids_match(struct bpf_verifier_log *log,
> +                         int off, u32 id, u32 need_type_id);
>  int btf_resolve_helper_id(struct bpf_verifier_log *log,
>                           const struct bpf_func_proto *fn, int);
>
> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> index 7bacc2f56061..ba05b15ad599 100644
> --- a/kernel/bpf/btf.c
> +++ b/kernel/bpf/btf.c
> @@ -4160,6 +4160,37 @@ int btf_struct_access(struct bpf_verifier_log *log,
>         return -EINVAL;
>  }
>
> +bool btf_struct_ids_match(struct bpf_verifier_log *log,
> +                         int off, u32 id, u32 need_type_id)
> +{
> +       const struct btf_type *type;
> +       int err;
> +
> +       /* Are we already done? */
> +       if (need_type_id == id && off == 0)
> +               return true;
> +
> +again:
> +       type = btf_type_by_id(btf_vmlinux, id);
> +       if (!type)
> +               return false;
> +       err = btf_struct_walk(log, type, off, 1, &id);

nit: this size=1 looks a bit artificial, seems like btf_struct_walk()
will work with size==0 just as well, no?

> +       if (err != WALK_STRUCT)
> +               return false;
> +
> +       /* We found nested struct object. If it matches
> +        * the requested ID, we're done. Otherwise let's
> +        * continue the search with offset 0 in the new
> +        * type.
> +        */
> +       if (need_type_id != id) {
> +               off = 0;
> +               goto again;
> +       }
> +
> +       return true;
> +}
> +
>  int btf_resolve_helper_id(struct bpf_verifier_log *log,
>                           const struct bpf_func_proto *fn, int arg)
>  {
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index b6ccfce3bf4c..bb6ca19f282d 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -3960,16 +3960,21 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
>                                 goto err_type;
>                 }
>         } else if (arg_type == ARG_PTR_TO_BTF_ID) {
> +               bool ids_match = false;
> +
>                 expected_type = PTR_TO_BTF_ID;
>                 if (type != expected_type)
>                         goto err_type;
>                 if (!fn->check_btf_id) {
> -                       if (reg->btf_id != meta->btf_id) {
> -                               verbose(env, "Helper has type %s got %s in R%d\n",
> -                                       kernel_type_name(meta->btf_id),
> -                                       kernel_type_name(reg->btf_id), regno);
> -
> -                               return -EACCES;
> +                       if (reg->btf_id != meta->btf_id || reg->off) {

Will it ever succeed if reg->btf_id == meta->btf_id, but reg->off > 0?
That would require recursively nested type, which is not possible,
right? Or what am I missing? Is it just a simplification of the error
handling path?

> +                               ids_match = btf_struct_ids_match(&env->log, reg->off, reg->btf_id,
> +                                                                meta->btf_id);
> +                               if (!ids_match) {
> +                                       verbose(env, "Helper has type %s got %s in R%d\n",
> +                                               kernel_type_name(meta->btf_id),
> +                                               kernel_type_name(reg->btf_id), regno);
> +                                       return -EACCES;
> +                               }
>                         }
>                 } else if (!fn->check_btf_id(reg->btf_id, arg)) {
>                         verbose(env, "Helper does not support %s in R%d\n",
> @@ -3977,7 +3982,8 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
>
>                         return -EACCES;
>                 }
> -               if (!tnum_is_const(reg->var_off) || reg->var_off.value || reg->off) {
> +               if (!ids_match &&
> +                   (!tnum_is_const(reg->var_off) || reg->var_off.value || reg->off)) {
>                         verbose(env, "R%d is a pointer to in-kernel struct with non-zero offset\n",
>                                 regno);
>                         return -EACCES;
> --
> 2.25.4
>

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

* Re: [PATCH v9 bpf-next 09/14] bpf: Add BTF_SET_START/END macros
  2020-08-01 17:03 ` [PATCH v9 bpf-next 09/14] bpf: Add BTF_SET_START/END macros Jiri Olsa
@ 2020-08-05  6:29   ` Andrii Nakryiko
  0 siblings, 0 replies; 38+ messages in thread
From: Andrii Nakryiko @ 2020-08-05  6:29 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Networking,
	bpf, Song Liu, Yonghong Song, Martin KaFai Lau, David Miller,
	John Fastabend, Wenbo Zhang, KP Singh, Brendan Gregg,
	Florent Revest, Al Viro

On Sat, Aug 1, 2020 at 10:04 AM Jiri Olsa <jolsa@kernel.org> wrote:
>
> Adding support to define sorted set of BTF ID values.
>
> Following defines sorted set of BTF ID values:
>
>   BTF_SET_START(btf_allowlist_d_path)
>   BTF_ID(func, vfs_truncate)
>   BTF_ID(func, vfs_fallocate)
>   BTF_ID(func, dentry_open)
>   BTF_ID(func, vfs_getattr)
>   BTF_ID(func, filp_close)
>   BTF_SET_END(btf_allowlist_d_path)
>
> It defines following 'struct btf_id_set' variable to access
> values and count:
>
>   struct btf_id_set btf_allowlist_d_path;
>
> Adding 'allowed' callback to struct bpf_func_proto, to allow
> verifier the check on allowed callers.
>
> Adding btf_id_set_contains function, which will be used by
> allowed callbacks to verify the caller's BTF ID value is
> within allowed set.
>
> Also removing extra '\' in __BTF_ID_LIST macro.
>
> Added BTF_SET_START_GLOBAL macro for global sets.
>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---

LGTM.

Acked-by: Andrii Nakryiko <andriin@fb.com>

>  include/linux/bpf.h           |  4 +++
>  include/linux/btf_ids.h       | 51 ++++++++++++++++++++++++++++++++++-
>  kernel/bpf/btf.c              | 14 ++++++++++
>  kernel/bpf/verifier.c         |  5 ++++
>  tools/include/linux/btf_ids.h | 51 ++++++++++++++++++++++++++++++++++-
>  5 files changed, 123 insertions(+), 2 deletions(-)
>

[...]

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

* Re: [PATCH v9 bpf-next 10/14] bpf: Add d_path helper
  2020-08-01 17:03 ` [PATCH v9 bpf-next 10/14] bpf: Add d_path helper Jiri Olsa
  2020-08-02  3:13   ` Alexei Starovoitov
@ 2020-08-05  6:35   ` Andrii Nakryiko
  2020-08-05 17:58     ` Jiri Olsa
  2020-08-07  0:31   ` KP Singh
  2 siblings, 1 reply; 38+ messages in thread
From: Andrii Nakryiko @ 2020-08-05  6:35 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Networking,
	bpf, Song Liu, Yonghong Song, Martin KaFai Lau, David Miller,
	John Fastabend, Wenbo Zhang, KP Singh, Brendan Gregg,
	Florent Revest, Al Viro

On Sat, Aug 1, 2020 at 10:04 AM Jiri Olsa <jolsa@kernel.org> wrote:
>
> Adding d_path helper function that returns full path for
> given 'struct path' object, which needs to be the kernel
> BTF 'path' object. The path is returned in buffer provided
> 'buf' of size 'sz' and is zero terminated.
>
>   bpf_d_path(&file->f_path, buf, size);
>
> The helper calls directly d_path function, so there's only
> limited set of function it can be called from. Adding just
> very modest set for the start.
>
> Updating also bpf.h tools uapi header and adding 'path' to
> bpf_helpers_doc.py script.
>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  include/uapi/linux/bpf.h       | 13 +++++++++
>  kernel/trace/bpf_trace.c       | 48 ++++++++++++++++++++++++++++++++++
>  scripts/bpf_helpers_doc.py     |  2 ++
>  tools/include/uapi/linux/bpf.h | 13 +++++++++
>  4 files changed, 76 insertions(+)
>
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index eb5e0c38eb2c..a356ea1357bf 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -3389,6 +3389,18 @@ union bpf_attr {
>   *             A non-negative value equal to or less than *size* on success,
>   *             or a negative error in case of failure.
>   *
> + * int bpf_d_path(struct path *path, char *buf, u32 sz)

nit: probably would be good to do `const struct path *` here, even if
we don't do const-ification properly in all helpers.

> + *     Description
> + *             Return full path for given 'struct path' object, which
> + *             needs to be the kernel BTF 'path' object. The path is
> + *             returned in buffer provided 'buf' of size 'sz' and

typo: in the provided buffer 'buf' of size ... ?

> + *             is zero terminated.
> + *
> + *     Return
> + *             On success, the strictly positive length of the string,
> + *             including the trailing NUL character. On error, a negative
> + *             value.
> + *
>   */
>  #define __BPF_FUNC_MAPPER(FN)          \
>         FN(unspec),                     \
> @@ -3533,6 +3545,7 @@ union bpf_attr {
>         FN(skc_to_tcp_request_sock),    \
>         FN(skc_to_udp6_sock),           \
>         FN(get_task_stack),             \
> +       FN(d_path),                     \
>         /* */
>
>  /* integer value in 'imm' field of BPF_CALL instruction selects which helper
> diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> index cb91ef902cc4..02a76e246545 100644
> --- a/kernel/trace/bpf_trace.c
> +++ b/kernel/trace/bpf_trace.c
> @@ -1098,6 +1098,52 @@ static const struct bpf_func_proto bpf_send_signal_thread_proto = {
>         .arg1_type      = ARG_ANYTHING,
>  };
>
> +BPF_CALL_3(bpf_d_path, struct path *, path, char *, buf, u32, sz)
> +{
> +       int len;
> +       char *p;
> +
> +       if (!sz)
> +               return -ENAMETOOLONG;

if we are modeling this after bpf_probe_read_str(), sz == 0 returns
success and just does nothing. I don't think anyone will ever handle
or expect this error. I'd just return 0.


> +
> +       p = d_path(path, buf, sz);
> +       if (IS_ERR(p)) {
> +               len = PTR_ERR(p);
> +       } else {
> +               len = buf + sz - p;
> +               memmove(buf, p, len);
> +       }
> +
> +       return len;
> +}
> +

[...]

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

* Re: [PATCH v9 bpf-next 13/14] selftests/bpf: Add test for d_path helper
  2020-08-01 17:03 ` [PATCH v9 bpf-next 13/14] selftests/bpf: Add " Jiri Olsa
@ 2020-08-05  6:40   ` Andrii Nakryiko
  2020-08-05 18:00     ` Jiri Olsa
  0 siblings, 1 reply; 38+ messages in thread
From: Andrii Nakryiko @ 2020-08-05  6:40 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Wenbo Zhang, Networking, bpf, Song Liu, Yonghong Song,
	Martin KaFai Lau, David Miller, John Fastabend, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

On Sat, Aug 1, 2020 at 10:05 AM Jiri Olsa <jolsa@kernel.org> wrote:
>
> Adding test for d_path helper which is pretty much
> copied from Wenbo Zhang's test for bpf_get_fd_path,
> which never made it in.
>
> The test is doing fstat/close on several fd types,
> and verifies we got the d_path helper working on
> kernel probes for vfs_getattr/filp_close functions.
>
> Original-patch-by: Wenbo Zhang <ethercflow@gmail.com>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---

Nothing wrong with this BPF implementation, but seem one suggestion below.

Acked-by: Andrii Nakryiko <andriin@fb.com>

>  .../testing/selftests/bpf/prog_tests/d_path.c | 147 ++++++++++++++++++
>  .../testing/selftests/bpf/progs/test_d_path.c |  64 ++++++++
>  2 files changed, 211 insertions(+)
>  create mode 100644 tools/testing/selftests/bpf/prog_tests/d_path.c
>  create mode 100644 tools/testing/selftests/bpf/progs/test_d_path.c
>

[...]

> diff --git a/tools/testing/selftests/bpf/progs/test_d_path.c b/tools/testing/selftests/bpf/progs/test_d_path.c
> new file mode 100644
> index 000000000000..9d342d7a1de6
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/progs/test_d_path.c
> @@ -0,0 +1,64 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include "vmlinux.h"
> +#include <bpf/bpf_helpers.h>
> +#include <bpf/bpf_tracing.h>
> +
> +#define MAX_PATH_LEN           128
> +#define MAX_FILES              7
> +
> +pid_t my_pid = 0;
> +__u32 cnt_stat = 0;
> +__u32 cnt_close = 0;
> +char paths_stat[MAX_FILES][MAX_PATH_LEN] = {};
> +char paths_close[MAX_FILES][MAX_PATH_LEN] = {};
> +int rets_stat[MAX_FILES] = {};
> +int rets_close[MAX_FILES] = {};
> +
> +SEC("fentry/vfs_getattr")
> +int BPF_PROG(prog_stat, struct path *path, struct kstat *stat,
> +            __u32 request_mask, unsigned int query_flags)
> +{
> +       pid_t pid = bpf_get_current_pid_tgid() >> 32;
> +       int ret;
> +
> +       if (pid != my_pid)
> +               return 0;
> +
> +       if (cnt_stat >= MAX_FILES)
> +               return 0;
> +       ret = bpf_d_path(path, paths_stat[cnt_stat], MAX_PATH_LEN);
> +
> +       /* We need to recheck cnt_stat for verifier. */
> +       if (cnt_stat >= MAX_FILES)
> +               return 0;
> +       rets_stat[cnt_stat] = ret;
> +
> +       cnt_stat++;
> +       return 0;
> +}
> +
> +SEC("fentry/filp_close")
> +int BPF_PROG(prog_close, struct file *file, void *id)
> +{
> +       pid_t pid = bpf_get_current_pid_tgid() >> 32;
> +       int ret;
> +
> +       if (pid != my_pid)
> +               return 0;
> +
> +       if (cnt_close >= MAX_FILES)
> +               return 0;
> +       ret = bpf_d_path(&file->f_path,
> +                        paths_close[cnt_close], MAX_PATH_LEN);
> +
> +       /* We need to recheck cnt_stat for verifier. */

you need to do it because you are re-reading a global variable; if you
stored cnt_close in a local variable, then did >= MAX_FILES check
once, you probably could have avoided this duplication. Same for
another instance above.

> +       if (cnt_close >= MAX_FILES)
> +               return 0;
> +       rets_close[cnt_close] = ret;
> +
> +       cnt_close++;
> +       return 0;
> +}
> +
> +char _license[] SEC("license") = "GPL";
> --
> 2.25.4
>

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

* Re: [PATCH v9 bpf-next 14/14] selftests/bpf: Add set test to resolve_btfids
  2020-08-01 17:03 ` [PATCH v9 bpf-next 14/14] selftests/bpf: Add set test to resolve_btfids Jiri Olsa
@ 2020-08-05  6:41   ` Andrii Nakryiko
  0 siblings, 0 replies; 38+ messages in thread
From: Andrii Nakryiko @ 2020-08-05  6:41 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Networking,
	bpf, Song Liu, Yonghong Song, Martin KaFai Lau, David Miller,
	John Fastabend, Wenbo Zhang, KP Singh, Brendan Gregg,
	Florent Revest, Al Viro

On Sat, Aug 1, 2020 at 10:04 AM Jiri Olsa <jolsa@kernel.org> wrote:
>
> Adding test to for sets resolve_btfids. We're checking that
> testing set gets properly resolved and sorted.
>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---

Acked-by: Andrii Nakryiko <andriin@fb.com>

>  .../selftests/bpf/prog_tests/resolve_btfids.c | 39 ++++++++++++++++++-
>  1 file changed, 38 insertions(+), 1 deletion(-)
>

[...]

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

* Re: [PATCH v9 bpf-next 06/14] bpf: Remove recursion call in btf_struct_access
  2020-08-05  6:12   ` Andrii Nakryiko
@ 2020-08-05 17:36     ` Jiri Olsa
  0 siblings, 0 replies; 38+ messages in thread
From: Jiri Olsa @ 2020-08-05 17:36 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Jiri Olsa, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Networking, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

On Tue, Aug 04, 2020 at 11:12:49PM -0700, Andrii Nakryiko wrote:
> On Sat, Aug 1, 2020 at 10:04 AM Jiri Olsa <jolsa@kernel.org> wrote:
> >
> > Andrii suggested we can simply jump to again label
> > instead of making recursion call.
> >
> > Suggested-by: Andrii Nakryiko <andriin@fb.com>
> > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > ---
> >  kernel/bpf/btf.c | 11 +++++------
> >  1 file changed, 5 insertions(+), 6 deletions(-)
> >
> > diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> > index bc05a24f7361..0f995038b589 100644
> > --- a/kernel/bpf/btf.c
> > +++ b/kernel/bpf/btf.c
> > @@ -3931,14 +3931,13 @@ int btf_struct_access(struct bpf_verifier_log *log,
> >                 /* Only allow structure for now, can be relaxed for
> >                  * other types later.
> >                  */
> > -               elem_type = btf_type_skip_modifiers(btf_vmlinux,
> > -                                                   array_elem->type, NULL);
> > -               if (!btf_type_is_struct(elem_type))
> > +               t = btf_type_skip_modifiers(btf_vmlinux, array_elem->type,
> > +                                           NULL);
> > +               if (!btf_type_is_struct(t))
> >                         goto error;
> >
> > -               off = (off - moff) % elem_type->size;
> > -               return btf_struct_access(log, elem_type, off, size, atype,
> > -                                        next_btf_id);
> > +               off = (off - moff) % t->size;
> > +               goto again;
> 
> Transformation looks good, thanks. So:
> 
> Acked-by: Andrii Nakryiko <andriin@fb.com>
> 
> But this '% t->size' makes me wonder what will happen when we have an
> array of zero-sized structs or multi-dimensional arrays with
> dimensions of size 0... I.e.:
> 
> struct {} arr[123];
> 
> or
> 
> int arr[0][0]0];
> 
> We should probably be more careful with division here.

right, definitely..  I'll send follow up patch for that

thanks,
jirka


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

* Re: [PATCH v9 bpf-next 08/14] bpf: Add btf_struct_ids_match function
  2020-08-05  6:27   ` Andrii Nakryiko
@ 2020-08-05 17:56     ` Jiri Olsa
  2020-08-05 21:31       ` Jiri Olsa
  0 siblings, 1 reply; 38+ messages in thread
From: Jiri Olsa @ 2020-08-05 17:56 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Jiri Olsa, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Networking, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

On Tue, Aug 04, 2020 at 11:27:55PM -0700, Andrii Nakryiko wrote:

SNIP

> > diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> > index 7bacc2f56061..ba05b15ad599 100644
> > --- a/kernel/bpf/btf.c
> > +++ b/kernel/bpf/btf.c
> > @@ -4160,6 +4160,37 @@ int btf_struct_access(struct bpf_verifier_log *log,
> >         return -EINVAL;
> >  }
> >
> > +bool btf_struct_ids_match(struct bpf_verifier_log *log,
> > +                         int off, u32 id, u32 need_type_id)
> > +{
> > +       const struct btf_type *type;
> > +       int err;
> > +
> > +       /* Are we already done? */
> > +       if (need_type_id == id && off == 0)
> > +               return true;
> > +
> > +again:
> > +       type = btf_type_by_id(btf_vmlinux, id);
> > +       if (!type)
> > +               return false;
> > +       err = btf_struct_walk(log, type, off, 1, &id);
> 
> nit: this size=1 looks a bit artificial, seems like btf_struct_walk()
> will work with size==0 just as well, no?

right, it will work the same for 0 ... not sure why I put
originaly 1 byte for size.. probably got mixed up by some
condition in btf_struct_walk that I thought 0 wouldn't pass,
but it should work, I'll change it, it's less tricky

> 
> > +       if (err != WALK_STRUCT)
> > +               return false;
> > +
> > +       /* We found nested struct object. If it matches
> > +        * the requested ID, we're done. Otherwise let's
> > +        * continue the search with offset 0 in the new
> > +        * type.
> > +        */
> > +       if (need_type_id != id) {
> > +               off = 0;
> > +               goto again;
> > +       }
> > +
> > +       return true;
> > +}
> > +
> >  int btf_resolve_helper_id(struct bpf_verifier_log *log,
> >                           const struct bpf_func_proto *fn, int arg)
> >  {
> > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > index b6ccfce3bf4c..bb6ca19f282d 100644
> > --- a/kernel/bpf/verifier.c
> > +++ b/kernel/bpf/verifier.c
> > @@ -3960,16 +3960,21 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
> >                                 goto err_type;
> >                 }
> >         } else if (arg_type == ARG_PTR_TO_BTF_ID) {
> > +               bool ids_match = false;
> > +
> >                 expected_type = PTR_TO_BTF_ID;
> >                 if (type != expected_type)
> >                         goto err_type;
> >                 if (!fn->check_btf_id) {
> > -                       if (reg->btf_id != meta->btf_id) {
> > -                               verbose(env, "Helper has type %s got %s in R%d\n",
> > -                                       kernel_type_name(meta->btf_id),
> > -                                       kernel_type_name(reg->btf_id), regno);
> > -
> > -                               return -EACCES;
> > +                       if (reg->btf_id != meta->btf_id || reg->off) {
> 
> Will it ever succeed if reg->btf_id == meta->btf_id, but reg->off > 0?
> That would require recursively nested type, which is not possible,
> right? Or what am I missing? Is it just a simplification of the error
> handling path?

ok, I wanted to cover all possible cases, but did not realized this
one is not possible ;-) will revert it to previous version

thanks,
jirka


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

* Re: [PATCH v9 bpf-next 10/14] bpf: Add d_path helper
  2020-08-05  6:35   ` Andrii Nakryiko
@ 2020-08-05 17:58     ` Jiri Olsa
  2020-08-05 21:01       ` Jiri Olsa
  0 siblings, 1 reply; 38+ messages in thread
From: Jiri Olsa @ 2020-08-05 17:58 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Jiri Olsa, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Networking, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

On Tue, Aug 04, 2020 at 11:35:53PM -0700, Andrii Nakryiko wrote:
> On Sat, Aug 1, 2020 at 10:04 AM Jiri Olsa <jolsa@kernel.org> wrote:
> >
> > Adding d_path helper function that returns full path for
> > given 'struct path' object, which needs to be the kernel
> > BTF 'path' object. The path is returned in buffer provided
> > 'buf' of size 'sz' and is zero terminated.
> >
> >   bpf_d_path(&file->f_path, buf, size);
> >
> > The helper calls directly d_path function, so there's only
> > limited set of function it can be called from. Adding just
> > very modest set for the start.
> >
> > Updating also bpf.h tools uapi header and adding 'path' to
> > bpf_helpers_doc.py script.
> >
> > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > ---
> >  include/uapi/linux/bpf.h       | 13 +++++++++
> >  kernel/trace/bpf_trace.c       | 48 ++++++++++++++++++++++++++++++++++
> >  scripts/bpf_helpers_doc.py     |  2 ++
> >  tools/include/uapi/linux/bpf.h | 13 +++++++++
> >  4 files changed, 76 insertions(+)
> >
> > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > index eb5e0c38eb2c..a356ea1357bf 100644
> > --- a/include/uapi/linux/bpf.h
> > +++ b/include/uapi/linux/bpf.h
> > @@ -3389,6 +3389,18 @@ union bpf_attr {
> >   *             A non-negative value equal to or less than *size* on success,
> >   *             or a negative error in case of failure.
> >   *
> > + * int bpf_d_path(struct path *path, char *buf, u32 sz)
> 
> nit: probably would be good to do `const struct path *` here, even if
> we don't do const-ification properly in all helpers.

ok

> 
> > + *     Description
> > + *             Return full path for given 'struct path' object, which
> > + *             needs to be the kernel BTF 'path' object. The path is
> > + *             returned in buffer provided 'buf' of size 'sz' and
> 
> typo: in the provided buffer 'buf' of size ... ?

ugh, sure

> 
> > + *             is zero terminated.
> > + *
> > + *     Return
> > + *             On success, the strictly positive length of the string,
> > + *             including the trailing NUL character. On error, a negative
> > + *             value.
> > + *
> >   */
> >  #define __BPF_FUNC_MAPPER(FN)          \
> >         FN(unspec),                     \
> > @@ -3533,6 +3545,7 @@ union bpf_attr {
> >         FN(skc_to_tcp_request_sock),    \
> >         FN(skc_to_udp6_sock),           \
> >         FN(get_task_stack),             \
> > +       FN(d_path),                     \
> >         /* */
> >
> >  /* integer value in 'imm' field of BPF_CALL instruction selects which helper
> > diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> > index cb91ef902cc4..02a76e246545 100644
> > --- a/kernel/trace/bpf_trace.c
> > +++ b/kernel/trace/bpf_trace.c
> > @@ -1098,6 +1098,52 @@ static const struct bpf_func_proto bpf_send_signal_thread_proto = {
> >         .arg1_type      = ARG_ANYTHING,
> >  };
> >
> > +BPF_CALL_3(bpf_d_path, struct path *, path, char *, buf, u32, sz)
> > +{
> > +       int len;
> > +       char *p;
> > +
> > +       if (!sz)
> > +               return -ENAMETOOLONG;
> 
> if we are modeling this after bpf_probe_read_str(), sz == 0 returns
> success and just does nothing. I don't think anyone will ever handle
> or expect this error. I'd just return 0.

ook

thanks,
jirka


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

* Re: [PATCH v9 bpf-next 13/14] selftests/bpf: Add test for d_path helper
  2020-08-05  6:40   ` Andrii Nakryiko
@ 2020-08-05 18:00     ` Jiri Olsa
  0 siblings, 0 replies; 38+ messages in thread
From: Jiri Olsa @ 2020-08-05 18:00 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Jiri Olsa, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Wenbo Zhang, Networking, bpf, Song Liu, Yonghong Song,
	Martin KaFai Lau, David Miller, John Fastabend, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

On Tue, Aug 04, 2020 at 11:40:05PM -0700, Andrii Nakryiko wrote:

SNIP

> > +SEC("fentry/vfs_getattr")
> > +int BPF_PROG(prog_stat, struct path *path, struct kstat *stat,
> > +            __u32 request_mask, unsigned int query_flags)
> > +{
> > +       pid_t pid = bpf_get_current_pid_tgid() >> 32;
> > +       int ret;
> > +
> > +       if (pid != my_pid)
> > +               return 0;
> > +
> > +       if (cnt_stat >= MAX_FILES)
> > +               return 0;
> > +       ret = bpf_d_path(path, paths_stat[cnt_stat], MAX_PATH_LEN);
> > +
> > +       /* We need to recheck cnt_stat for verifier. */
> > +       if (cnt_stat >= MAX_FILES)
> > +               return 0;
> > +       rets_stat[cnt_stat] = ret;
> > +
> > +       cnt_stat++;
> > +       return 0;
> > +}
> > +
> > +SEC("fentry/filp_close")
> > +int BPF_PROG(prog_close, struct file *file, void *id)
> > +{
> > +       pid_t pid = bpf_get_current_pid_tgid() >> 32;
> > +       int ret;
> > +
> > +       if (pid != my_pid)
> > +               return 0;
> > +
> > +       if (cnt_close >= MAX_FILES)
> > +               return 0;
> > +       ret = bpf_d_path(&file->f_path,
> > +                        paths_close[cnt_close], MAX_PATH_LEN);
> > +
> > +       /* We need to recheck cnt_stat for verifier. */
> 
> you need to do it because you are re-reading a global variable; if you
> stored cnt_close in a local variable, then did >= MAX_FILES check
> once, you probably could have avoided this duplication. Same for
> another instance above.

I see, nice.. I'll update both comments

thanks,
jirka


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

* Re: [PATCH v9 bpf-next 10/14] bpf: Add d_path helper
  2020-08-05 17:58     ` Jiri Olsa
@ 2020-08-05 21:01       ` Jiri Olsa
  2020-08-05 21:09         ` Andrii Nakryiko
  0 siblings, 1 reply; 38+ messages in thread
From: Jiri Olsa @ 2020-08-05 21:01 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Jiri Olsa, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Networking, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

On Wed, Aug 05, 2020 at 07:58:54PM +0200, Jiri Olsa wrote:
> On Tue, Aug 04, 2020 at 11:35:53PM -0700, Andrii Nakryiko wrote:
> > On Sat, Aug 1, 2020 at 10:04 AM Jiri Olsa <jolsa@kernel.org> wrote:
> > >
> > > Adding d_path helper function that returns full path for
> > > given 'struct path' object, which needs to be the kernel
> > > BTF 'path' object. The path is returned in buffer provided
> > > 'buf' of size 'sz' and is zero terminated.
> > >
> > >   bpf_d_path(&file->f_path, buf, size);
> > >
> > > The helper calls directly d_path function, so there's only
> > > limited set of function it can be called from. Adding just
> > > very modest set for the start.
> > >
> > > Updating also bpf.h tools uapi header and adding 'path' to
> > > bpf_helpers_doc.py script.
> > >
> > > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > > ---
> > >  include/uapi/linux/bpf.h       | 13 +++++++++
> > >  kernel/trace/bpf_trace.c       | 48 ++++++++++++++++++++++++++++++++++
> > >  scripts/bpf_helpers_doc.py     |  2 ++
> > >  tools/include/uapi/linux/bpf.h | 13 +++++++++
> > >  4 files changed, 76 insertions(+)
> > >
> > > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > > index eb5e0c38eb2c..a356ea1357bf 100644
> > > --- a/include/uapi/linux/bpf.h
> > > +++ b/include/uapi/linux/bpf.h
> > > @@ -3389,6 +3389,18 @@ union bpf_attr {
> > >   *             A non-negative value equal to or less than *size* on success,
> > >   *             or a negative error in case of failure.
> > >   *
> > > + * int bpf_d_path(struct path *path, char *buf, u32 sz)
> > 
> > nit: probably would be good to do `const struct path *` here, even if
> > we don't do const-ification properly in all helpers.

hum, for this I need to update scripts/bpf_helpers_doc.py and it looks
like it's not ready for const struct yet:

  CLNG-LLC [test_maps] get_cgroup_id_kern.o
In file included from progs/test_lwt_ip_encap.c:7:
In file included from /home/jolsa/linux/tools/testing/selftests/bpf/tools/include/bpf/bpf_helpers.h:11:
/home/jolsa/linux/tools/testing/selftests/bpf/tools/include/bpf/bpf_helper_defs.h:32:1: warning: 'const' ignored on this declaration [-Wmissing-declarations]
const struct path;
^

would it be ok as a follow up change? I'll need to check
on bpf_helpers_doc.py script first

jirka


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

* Re: [PATCH v9 bpf-next 10/14] bpf: Add d_path helper
  2020-08-05 21:01       ` Jiri Olsa
@ 2020-08-05 21:09         ` Andrii Nakryiko
  0 siblings, 0 replies; 38+ messages in thread
From: Andrii Nakryiko @ 2020-08-05 21:09 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Jiri Olsa, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Networking, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

On Wed, Aug 5, 2020 at 2:01 PM Jiri Olsa <jolsa@redhat.com> wrote:
>
> On Wed, Aug 05, 2020 at 07:58:54PM +0200, Jiri Olsa wrote:
> > On Tue, Aug 04, 2020 at 11:35:53PM -0700, Andrii Nakryiko wrote:
> > > On Sat, Aug 1, 2020 at 10:04 AM Jiri Olsa <jolsa@kernel.org> wrote:
> > > >
> > > > Adding d_path helper function that returns full path for
> > > > given 'struct path' object, which needs to be the kernel
> > > > BTF 'path' object. The path is returned in buffer provided
> > > > 'buf' of size 'sz' and is zero terminated.
> > > >
> > > >   bpf_d_path(&file->f_path, buf, size);
> > > >
> > > > The helper calls directly d_path function, so there's only
> > > > limited set of function it can be called from. Adding just
> > > > very modest set for the start.
> > > >
> > > > Updating also bpf.h tools uapi header and adding 'path' to
> > > > bpf_helpers_doc.py script.
> > > >
> > > > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > > > ---
> > > >  include/uapi/linux/bpf.h       | 13 +++++++++
> > > >  kernel/trace/bpf_trace.c       | 48 ++++++++++++++++++++++++++++++++++
> > > >  scripts/bpf_helpers_doc.py     |  2 ++
> > > >  tools/include/uapi/linux/bpf.h | 13 +++++++++
> > > >  4 files changed, 76 insertions(+)
> > > >
> > > > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > > > index eb5e0c38eb2c..a356ea1357bf 100644
> > > > --- a/include/uapi/linux/bpf.h
> > > > +++ b/include/uapi/linux/bpf.h
> > > > @@ -3389,6 +3389,18 @@ union bpf_attr {
> > > >   *             A non-negative value equal to or less than *size* on success,
> > > >   *             or a negative error in case of failure.
> > > >   *
> > > > + * int bpf_d_path(struct path *path, char *buf, u32 sz)
> > >
> > > nit: probably would be good to do `const struct path *` here, even if
> > > we don't do const-ification properly in all helpers.
>
> hum, for this I need to update scripts/bpf_helpers_doc.py and it looks
> like it's not ready for const struct yet:
>
>   CLNG-LLC [test_maps] get_cgroup_id_kern.o
> In file included from progs/test_lwt_ip_encap.c:7:
> In file included from /home/jolsa/linux/tools/testing/selftests/bpf/tools/include/bpf/bpf_helpers.h:11:
> /home/jolsa/linux/tools/testing/selftests/bpf/tools/include/bpf/bpf_helper_defs.h:32:1: warning: 'const' ignored on this declaration [-Wmissing-declarations]
> const struct path;
> ^
>
> would it be ok as a follow up change? I'll need to check
> on bpf_helpers_doc.py script first

yeah, no big deal

>
> jirka
>

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

* Re: [PATCH v9 bpf-next 08/14] bpf: Add btf_struct_ids_match function
  2020-08-05 17:56     ` Jiri Olsa
@ 2020-08-05 21:31       ` Jiri Olsa
  2020-08-05 21:57         ` Andrii Nakryiko
  0 siblings, 1 reply; 38+ messages in thread
From: Jiri Olsa @ 2020-08-05 21:31 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Jiri Olsa, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Networking, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

On Wed, Aug 05, 2020 at 07:56:51PM +0200, Jiri Olsa wrote:
> On Tue, Aug 04, 2020 at 11:27:55PM -0700, Andrii Nakryiko wrote:
> 
> SNIP
> 
> > > diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> > > index 7bacc2f56061..ba05b15ad599 100644
> > > --- a/kernel/bpf/btf.c
> > > +++ b/kernel/bpf/btf.c
> > > @@ -4160,6 +4160,37 @@ int btf_struct_access(struct bpf_verifier_log *log,
> > >         return -EINVAL;
> > >  }
> > >
> > > +bool btf_struct_ids_match(struct bpf_verifier_log *log,
> > > +                         int off, u32 id, u32 need_type_id)
> > > +{
> > > +       const struct btf_type *type;
> > > +       int err;
> > > +
> > > +       /* Are we already done? */
> > > +       if (need_type_id == id && off == 0)
> > > +               return true;
> > > +
> > > +again:
> > > +       type = btf_type_by_id(btf_vmlinux, id);
> > > +       if (!type)
> > > +               return false;
> > > +       err = btf_struct_walk(log, type, off, 1, &id);
> > 
> > nit: this size=1 looks a bit artificial, seems like btf_struct_walk()
> > will work with size==0 just as well, no?
> 
> right, it will work the same for 0 ... not sure why I put
> originaly 1 byte for size.. probably got mixed up by some
> condition in btf_struct_walk that I thought 0 wouldn't pass,
> but it should work, I'll change it, it's less tricky

ok, I found why it's 1 ;-) it's this condition in btf_struct_walk:

        for_each_member(i, t, member) {
                /* offset of the field in bytes */
                moff = btf_member_bit_offset(t, member) / 8;
                if (off + size <= moff)
                        /* won't find anything, field is already too far */
                        break;

I originaly chose to use 'size = 1' not to medle with this (and probably causing
other issues) and in any case we expect that anything we find have at least byte
size, so it has some logic ;-)

we could make 0 size a special case and don't break the loop for it,
but I wonder there's already someone calling it with zero and is
expecting it to fail

jirka


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

* Re: [PATCH v9 bpf-next 08/14] bpf: Add btf_struct_ids_match function
  2020-08-05 21:31       ` Jiri Olsa
@ 2020-08-05 21:57         ` Andrii Nakryiko
  0 siblings, 0 replies; 38+ messages in thread
From: Andrii Nakryiko @ 2020-08-05 21:57 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Jiri Olsa, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Networking, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, KP Singh,
	Brendan Gregg, Florent Revest, Al Viro

On Wed, Aug 5, 2020 at 2:31 PM Jiri Olsa <jolsa@redhat.com> wrote:
>
> On Wed, Aug 05, 2020 at 07:56:51PM +0200, Jiri Olsa wrote:
> > On Tue, Aug 04, 2020 at 11:27:55PM -0700, Andrii Nakryiko wrote:
> >
> > SNIP
> >
> > > > diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> > > > index 7bacc2f56061..ba05b15ad599 100644
> > > > --- a/kernel/bpf/btf.c
> > > > +++ b/kernel/bpf/btf.c
> > > > @@ -4160,6 +4160,37 @@ int btf_struct_access(struct bpf_verifier_log *log,
> > > >         return -EINVAL;
> > > >  }
> > > >
> > > > +bool btf_struct_ids_match(struct bpf_verifier_log *log,
> > > > +                         int off, u32 id, u32 need_type_id)
> > > > +{
> > > > +       const struct btf_type *type;
> > > > +       int err;
> > > > +
> > > > +       /* Are we already done? */
> > > > +       if (need_type_id == id && off == 0)
> > > > +               return true;
> > > > +
> > > > +again:
> > > > +       type = btf_type_by_id(btf_vmlinux, id);
> > > > +       if (!type)
> > > > +               return false;
> > > > +       err = btf_struct_walk(log, type, off, 1, &id);
> > >
> > > nit: this size=1 looks a bit artificial, seems like btf_struct_walk()
> > > will work with size==0 just as well, no?
> >
> > right, it will work the same for 0 ... not sure why I put
> > originaly 1 byte for size.. probably got mixed up by some
> > condition in btf_struct_walk that I thought 0 wouldn't pass,
> > but it should work, I'll change it, it's less tricky
>
> ok, I found why it's 1 ;-) it's this condition in btf_struct_walk:
>
>         for_each_member(i, t, member) {
>                 /* offset of the field in bytes */
>                 moff = btf_member_bit_offset(t, member) / 8;
>                 if (off + size <= moff)
>                         /* won't find anything, field is already too far */
>                         break;
>
> I originaly chose to use 'size = 1' not to medle with this (and probably causing
> other issues) and in any case we expect that anything we find have at least byte
> size, so it has some logic ;-)
>
> we could make 0 size a special case and don't break the loop for it,
> but I wonder there's already someone calling it with zero and is
> expecting it to fail
>

I see, ok, probably no need. Just let it be for now, I guess.

> jirka
>

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

* Re: [PATCH v9 bpf-next 10/14] bpf: Add d_path helper
  2020-08-01 17:03 ` [PATCH v9 bpf-next 10/14] bpf: Add d_path helper Jiri Olsa
  2020-08-02  3:13   ` Alexei Starovoitov
  2020-08-05  6:35   ` Andrii Nakryiko
@ 2020-08-07  0:31   ` KP Singh
  2020-08-07  8:35     ` Jiri Olsa
  2 siblings, 1 reply; 38+ messages in thread
From: KP Singh @ 2020-08-07  0:31 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Networking,
	bpf, Song Liu, Yonghong Song, Martin KaFai Lau, David Miller,
	John Fastabend, Wenbo Zhang, Brendan Gregg, Florent Revest,
	Al Viro

On Sat, Aug 1, 2020 at 7:04 PM Jiri Olsa <jolsa@kernel.org> wrote:
>
> Adding d_path helper function that returns full path for

[...]

> +}
> +
> +BTF_SET_START(btf_allowlist_d_path)
> +BTF_ID(func, vfs_truncate)
> +BTF_ID(func, vfs_fallocate)
> +BTF_ID(func, dentry_open)
> +BTF_ID(func, vfs_getattr)
> +BTF_ID(func, filp_close)
> +BTF_SET_END(btf_allowlist_d_path)
> +

> +static bool bpf_d_path_allowed(const struct bpf_prog *prog)
> +{
> +       return btf_id_set_contains(&btf_allowlist_d_path, prog->aux->attach_btf_id);
> +}

Can we allow it for LSM programs too?

- KP

> +
> +BTF_ID_LIST(bpf_d_path_btf_ids)
> +BTF_ID(struct, path)
> +

[...]

>
>  /* integer value in 'imm' field of BPF_CALL instruction selects which helper
> --
> 2.25.4
>

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

* Re: [PATCH v9 bpf-next 10/14] bpf: Add d_path helper
  2020-08-07  0:31   ` KP Singh
@ 2020-08-07  8:35     ` Jiri Olsa
  2020-08-07  9:42       ` KP Singh
  0 siblings, 1 reply; 38+ messages in thread
From: Jiri Olsa @ 2020-08-07  8:35 UTC (permalink / raw)
  To: KP Singh
  Cc: Jiri Olsa, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Networking, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, Brendan Gregg,
	Florent Revest, Al Viro

On Fri, Aug 07, 2020 at 02:31:52AM +0200, KP Singh wrote:
> On Sat, Aug 1, 2020 at 7:04 PM Jiri Olsa <jolsa@kernel.org> wrote:
> >
> > Adding d_path helper function that returns full path for
> 
> [...]
> 
> > +}
> > +
> > +BTF_SET_START(btf_allowlist_d_path)
> > +BTF_ID(func, vfs_truncate)
> > +BTF_ID(func, vfs_fallocate)
> > +BTF_ID(func, dentry_open)
> > +BTF_ID(func, vfs_getattr)
> > +BTF_ID(func, filp_close)
> > +BTF_SET_END(btf_allowlist_d_path)
> > +
> 
> > +static bool bpf_d_path_allowed(const struct bpf_prog *prog)
> > +{
> > +       return btf_id_set_contains(&btf_allowlist_d_path, prog->aux->attach_btf_id);
> > +}
> 
> Can we allow it for LSM programs too?

yes, that's why I used struct bpf_prog as argument, so we could reach the
program type.. but I was hoping we could do that in follow up patchset,
because I assume there might be still some discussion about that?

I plan to post new version today

jirka

> 
> - KP
> 
> > +
> > +BTF_ID_LIST(bpf_d_path_btf_ids)
> > +BTF_ID(struct, path)
> > +
> 
> [...]
> 
> >
> >  /* integer value in 'imm' field of BPF_CALL instruction selects which helper
> > --
> > 2.25.4
> >
> 


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

* Re: [PATCH v9 bpf-next 10/14] bpf: Add d_path helper
  2020-08-07  8:35     ` Jiri Olsa
@ 2020-08-07  9:42       ` KP Singh
  0 siblings, 0 replies; 38+ messages in thread
From: KP Singh @ 2020-08-07  9:42 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Jiri Olsa, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Networking, bpf, Song Liu, Yonghong Song, Martin KaFai Lau,
	David Miller, John Fastabend, Wenbo Zhang, Brendan Gregg,
	Florent Revest, Al Viro

On Fri, Aug 7, 2020 at 10:35 AM Jiri Olsa <jolsa@redhat.com> wrote:
>
> On Fri, Aug 07, 2020 at 02:31:52AM +0200, KP Singh wrote:
> > On Sat, Aug 1, 2020 at 7:04 PM Jiri Olsa <jolsa@kernel.org> wrote:
> > >
> > > Adding d_path helper function that returns full path for
> >
> > [...]
> >
> > > +}
> > > +
> > > +BTF_SET_START(btf_allowlist_d_path)
> > > +BTF_ID(func, vfs_truncate)
> > > +BTF_ID(func, vfs_fallocate)
> > > +BTF_ID(func, dentry_open)
> > > +BTF_ID(func, vfs_getattr)
> > > +BTF_ID(func, filp_close)
> > > +BTF_SET_END(btf_allowlist_d_path)
> > > +
> >
> > > +static bool bpf_d_path_allowed(const struct bpf_prog *prog)
> > > +{
> > > +       return btf_id_set_contains(&btf_allowlist_d_path, prog->aux->attach_btf_id);
> > > +}
> >
> > Can we allow it for LSM programs too?
>
> yes, that's why I used struct bpf_prog as argument, so we could reach the

Thanks for adding the bpf_prog argument.

> program type.. but I was hoping we could do that in follow up patchset,

Sure. We can do it in a follow-up patch.

- KP

> because I assume there might be still some discussion about that?
>
> I plan to post new version today
>
> jirka
>
> >
> > - KP
> >
> > > +
> > > +BTF_ID_LIST(bpf_d_path_btf_ids)
> > > +BTF_ID(struct, path)
> > > +
> >
> > [...]
> >
> > >
> > >  /* integer value in 'imm' field of BPF_CALL instruction selects which helper
> > > --
> > > 2.25.4
> > >
> >
>

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

end of thread, back to index

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-01 17:03 [PATCH v9 bpf-next 00/14] bpf: Add d_path helper Jiri Olsa
2020-08-01 17:03 ` [PATCH v9 bpf-next 01/14] tools resolve_btfids: Add size check to get_id function Jiri Olsa
2020-08-05  6:00   ` Andrii Nakryiko
2020-08-01 17:03 ` [PATCH v9 bpf-next 02/14] tools resolve_btfids: Add support for set symbols Jiri Olsa
2020-08-05  6:04   ` Andrii Nakryiko
2020-08-01 17:03 ` [PATCH v9 bpf-next 03/14] bpf: Move btf_resolve_size into __btf_resolve_size Jiri Olsa
2020-08-01 17:03 ` [PATCH v9 bpf-next 04/14] bpf: Add elem_id pointer as argument to __btf_resolve_size Jiri Olsa
2020-08-01 17:03 ` [PATCH v9 bpf-next 05/14] bpf: Add type_id " Jiri Olsa
2020-08-05  6:05   ` Andrii Nakryiko
2020-08-01 17:03 ` [PATCH v9 bpf-next 06/14] bpf: Remove recursion call in btf_struct_access Jiri Olsa
2020-08-05  6:12   ` Andrii Nakryiko
2020-08-05 17:36     ` Jiri Olsa
2020-08-01 17:03 ` [PATCH v9 bpf-next 07/14] bpf: Factor btf_struct_access function Jiri Olsa
2020-08-05  6:18   ` Andrii Nakryiko
2020-08-01 17:03 ` [PATCH v9 bpf-next 08/14] bpf: Add btf_struct_ids_match function Jiri Olsa
2020-08-05  6:27   ` Andrii Nakryiko
2020-08-05 17:56     ` Jiri Olsa
2020-08-05 21:31       ` Jiri Olsa
2020-08-05 21:57         ` Andrii Nakryiko
2020-08-01 17:03 ` [PATCH v9 bpf-next 09/14] bpf: Add BTF_SET_START/END macros Jiri Olsa
2020-08-05  6:29   ` Andrii Nakryiko
2020-08-01 17:03 ` [PATCH v9 bpf-next 10/14] bpf: Add d_path helper Jiri Olsa
2020-08-02  3:13   ` Alexei Starovoitov
2020-08-02 18:26     ` Jiri Olsa
2020-08-05  6:35   ` Andrii Nakryiko
2020-08-05 17:58     ` Jiri Olsa
2020-08-05 21:01       ` Jiri Olsa
2020-08-05 21:09         ` Andrii Nakryiko
2020-08-07  0:31   ` KP Singh
2020-08-07  8:35     ` Jiri Olsa
2020-08-07  9:42       ` KP Singh
2020-08-01 17:03 ` [PATCH v9 bpf-next 11/14] bpf: Update .BTF_ids section in btf.rst with sets info Jiri Olsa
2020-08-01 17:03 ` [PATCH v9 bpf-next 12/14] selftests/bpf: Add verifier test for d_path helper Jiri Olsa
2020-08-01 17:03 ` [PATCH v9 bpf-next 13/14] selftests/bpf: Add " Jiri Olsa
2020-08-05  6:40   ` Andrii Nakryiko
2020-08-05 18:00     ` Jiri Olsa
2020-08-01 17:03 ` [PATCH v9 bpf-next 14/14] selftests/bpf: Add set test to resolve_btfids Jiri Olsa
2020-08-05  6:41   ` Andrii Nakryiko

Netdev Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/netdev/0 netdev/git/0.git
	git clone --mirror https://lore.kernel.org/netdev/1 netdev/git/1.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 netdev netdev/ https://lore.kernel.org/netdev \
		netdev@vger.kernel.org
	public-inbox-index netdev

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.netdev


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git