* [PATCH bpf-next v3 2/6] bpf: Add a bpf_sock_from_file helper
2020-11-26 16:44 [PATCH bpf-next v3 1/6] net: Remove the err argument from sock_from_file Florent Revest
@ 2020-11-26 16:44 ` Florent Revest
2020-11-26 16:44 ` [PATCH bpf-next v3 3/6] bpf: Expose bpf_sk_storage_* to iterator programs Florent Revest
` (4 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Florent Revest @ 2020-11-26 16:44 UTC (permalink / raw)
To: bpf
Cc: viro, davem, kuba, ast, daniel, kafai, yhs, andrii, kpsingh,
revest, linux-kernel, netdev, KP Singh
While eBPF programs can check whether a file is a socket by file->f_op
== &socket_file_ops, they cannot convert the void private_data pointer
to a struct socket BTF pointer. In order to do this a new helper
wrapping sock_from_file is added.
This is useful to tracing programs but also other program types
inheriting this set of helpers such as iterators or LSM programs.
Signed-off-by: Florent Revest <revest@google.com>
Acked-by: KP Singh <kpsingh@google.com>
Acked-by: Martin KaFai Lau <kafai@fb.com>
---
include/uapi/linux/bpf.h | 9 +++++++++
kernel/trace/bpf_trace.c | 20 ++++++++++++++++++++
scripts/bpf_helpers_doc.py | 4 ++++
tools/include/uapi/linux/bpf.h | 9 +++++++++
4 files changed, 42 insertions(+)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index c3458ec1f30a..a92b2b7d331b 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -3817,6 +3817,14 @@ union bpf_attr {
* The **hash_algo** is returned on success,
* **-EOPNOTSUP** if IMA is disabled or **-EINVAL** if
* invalid arguments are passed.
+ *
+ * struct socket *bpf_sock_from_file(struct file *file)
+ * Description
+ * If the given file represents a socket, returns the associated
+ * socket.
+ * Return
+ * A pointer to a struct socket on success or NULL if the file is
+ * not a socket.
*/
#define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \
@@ -3981,6 +3989,7 @@ union bpf_attr {
FN(bprm_opts_set), \
FN(ktime_get_coarse_ns), \
FN(ima_inode_hash), \
+ FN(sock_from_file), \
/* */
/* 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 d255bc9b2bfa..d0aac9eac2d8 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -1260,6 +1260,24 @@ const struct bpf_func_proto bpf_snprintf_btf_proto = {
.arg5_type = ARG_ANYTHING,
};
+BPF_CALL_1(bpf_sock_from_file, struct file *, file)
+{
+ return (unsigned long) sock_from_file(file);
+}
+
+BTF_ID_LIST(bpf_sock_from_file_btf_ids)
+BTF_ID(struct, socket)
+BTF_ID(struct, file)
+
+static const struct bpf_func_proto bpf_sock_from_file_proto = {
+ .func = bpf_sock_from_file,
+ .gpl_only = false,
+ .ret_type = RET_PTR_TO_BTF_ID_OR_NULL,
+ .ret_btf_id = &bpf_sock_from_file_btf_ids[0],
+ .arg1_type = ARG_PTR_TO_BTF_ID,
+ .arg1_btf_id = &bpf_sock_from_file_btf_ids[1],
+};
+
const struct bpf_func_proto *
bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
{
@@ -1356,6 +1374,8 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
return &bpf_per_cpu_ptr_proto;
case BPF_FUNC_bpf_this_cpu_ptr:
return &bpf_this_cpu_ptr_proto;
+ case BPF_FUNC_sock_from_file:
+ return &bpf_sock_from_file_proto;
default:
return NULL;
}
diff --git a/scripts/bpf_helpers_doc.py b/scripts/bpf_helpers_doc.py
index 8b829748d488..867ada23281c 100755
--- a/scripts/bpf_helpers_doc.py
+++ b/scripts/bpf_helpers_doc.py
@@ -437,6 +437,8 @@ class PrinterHelpers(Printer):
'struct path',
'struct btf_ptr',
'struct inode',
+ 'struct socket',
+ 'struct file',
]
known_types = {
'...',
@@ -482,6 +484,8 @@ class PrinterHelpers(Printer):
'struct path',
'struct btf_ptr',
'struct inode',
+ 'struct socket',
+ 'struct file',
}
mapped_types = {
'u8': '__u8',
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index c3458ec1f30a..a92b2b7d331b 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -3817,6 +3817,14 @@ union bpf_attr {
* The **hash_algo** is returned on success,
* **-EOPNOTSUP** if IMA is disabled or **-EINVAL** if
* invalid arguments are passed.
+ *
+ * struct socket *bpf_sock_from_file(struct file *file)
+ * Description
+ * If the given file represents a socket, returns the associated
+ * socket.
+ * Return
+ * A pointer to a struct socket on success or NULL if the file is
+ * not a socket.
*/
#define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \
@@ -3981,6 +3989,7 @@ union bpf_attr {
FN(bprm_opts_set), \
FN(ktime_get_coarse_ns), \
FN(ima_inode_hash), \
+ FN(sock_from_file), \
/* */
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
--
2.29.2.454.gaff20da3a2-goog
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH bpf-next v3 3/6] bpf: Expose bpf_sk_storage_* to iterator programs
2020-11-26 16:44 [PATCH bpf-next v3 1/6] net: Remove the err argument from sock_from_file Florent Revest
2020-11-26 16:44 ` [PATCH bpf-next v3 2/6] bpf: Add a bpf_sock_from_file helper Florent Revest
@ 2020-11-26 16:44 ` Florent Revest
2020-11-26 22:58 ` KP Singh
2020-11-26 16:44 ` [PATCH bpf-next v3 4/6] bpf: Add an iterator selftest for bpf_sk_storage_delete Florent Revest
` (3 subsequent siblings)
5 siblings, 1 reply; 11+ messages in thread
From: Florent Revest @ 2020-11-26 16:44 UTC (permalink / raw)
To: bpf
Cc: viro, davem, kuba, ast, daniel, kafai, yhs, andrii, kpsingh,
revest, linux-kernel, netdev
Iterators are currently used to expose kernel information to userspace
over fast procfs-like files but iterators could also be used to
manipulate local storage. For example, the task_file iterator could be
used to initialize a socket local storage with associations between
processes and sockets or to selectively delete local storage values.
Signed-off-by: Florent Revest <revest@google.com>
Acked-by: Martin KaFai Lau <kafai@fb.com>
---
net/core/bpf_sk_storage.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/core/bpf_sk_storage.c b/net/core/bpf_sk_storage.c
index a32037daa933..4edd033e899c 100644
--- a/net/core/bpf_sk_storage.c
+++ b/net/core/bpf_sk_storage.c
@@ -394,6 +394,7 @@ static bool bpf_sk_storage_tracing_allowed(const struct bpf_prog *prog)
* use the bpf_sk_storage_(get|delete) helper.
*/
switch (prog->expected_attach_type) {
+ case BPF_TRACE_ITER:
case BPF_TRACE_RAW_TP:
/* bpf_sk_storage has no trace point */
return true;
--
2.29.2.454.gaff20da3a2-goog
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH bpf-next v3 3/6] bpf: Expose bpf_sk_storage_* to iterator programs
2020-11-26 16:44 ` [PATCH bpf-next v3 3/6] bpf: Expose bpf_sk_storage_* to iterator programs Florent Revest
@ 2020-11-26 22:58 ` KP Singh
0 siblings, 0 replies; 11+ messages in thread
From: KP Singh @ 2020-11-26 22:58 UTC (permalink / raw)
To: Florent Revest
Cc: bpf, Al Viro, David S. Miller, Jakub Kicinski,
Alexei Starovoitov, Daniel Borkmann, Martin KaFai Lau,
Yonghong Song, Andrii Nakryiko, Florent Revest, open list,
Networking
On Thu, Nov 26, 2020 at 5:45 PM Florent Revest <revest@chromium.org> wrote:
>
> Iterators are currently used to expose kernel information to userspace
> over fast procfs-like files but iterators could also be used to
> manipulate local storage. For example, the task_file iterator could be
> used to initialize a socket local storage with associations between
> processes and sockets or to selectively delete local storage values.
>
> Signed-off-by: Florent Revest <revest@google.com>
> Acked-by: Martin KaFai Lau <kafai@fb.com>
Acked-by: KP Singh <kpsingh@google.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH bpf-next v3 4/6] bpf: Add an iterator selftest for bpf_sk_storage_delete
2020-11-26 16:44 [PATCH bpf-next v3 1/6] net: Remove the err argument from sock_from_file Florent Revest
2020-11-26 16:44 ` [PATCH bpf-next v3 2/6] bpf: Add a bpf_sock_from_file helper Florent Revest
2020-11-26 16:44 ` [PATCH bpf-next v3 3/6] bpf: Expose bpf_sk_storage_* to iterator programs Florent Revest
@ 2020-11-26 16:44 ` Florent Revest
2020-11-26 16:44 ` [PATCH bpf-next v3 5/6] bpf: Add an iterator selftest for bpf_sk_storage_get Florent Revest
` (2 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Florent Revest @ 2020-11-26 16:44 UTC (permalink / raw)
To: bpf
Cc: viro, davem, kuba, ast, daniel, kafai, yhs, andrii, kpsingh,
revest, linux-kernel, netdev
The eBPF program iterates over all entries (well, only one) of a socket
local storage map and deletes them all. The test makes sure that the
entry is indeed deleted.
Signed-off-by: Florent Revest <revest@google.com>
Acked-by: Martin KaFai Lau <kafai@fb.com>
---
.../selftests/bpf/prog_tests/bpf_iter.c | 64 +++++++++++++++++++
.../progs/bpf_iter_bpf_sk_storage_helpers.c | 23 +++++++
2 files changed, 87 insertions(+)
create mode 100644 tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c
diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
index 448885b95eed..bb4a638f2e6f 100644
--- a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
+++ b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
@@ -20,6 +20,7 @@
#include "bpf_iter_bpf_percpu_hash_map.skel.h"
#include "bpf_iter_bpf_array_map.skel.h"
#include "bpf_iter_bpf_percpu_array_map.skel.h"
+#include "bpf_iter_bpf_sk_storage_helpers.skel.h"
#include "bpf_iter_bpf_sk_storage_map.skel.h"
#include "bpf_iter_test_kern5.skel.h"
#include "bpf_iter_test_kern6.skel.h"
@@ -913,6 +914,67 @@ static void test_bpf_percpu_array_map(void)
bpf_iter_bpf_percpu_array_map__destroy(skel);
}
+/* An iterator program deletes all local storage in a map. */
+static void test_bpf_sk_storage_delete(void)
+{
+ DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts);
+ struct bpf_iter_bpf_sk_storage_helpers *skel;
+ union bpf_iter_link_info linfo;
+ int err, len, map_fd, iter_fd;
+ struct bpf_link *link;
+ int sock_fd = -1;
+ __u32 val = 42;
+ char buf[64];
+
+ skel = bpf_iter_bpf_sk_storage_helpers__open_and_load();
+ if (CHECK(!skel, "bpf_iter_bpf_sk_storage_helpers__open_and_load",
+ "skeleton open_and_load failed\n"))
+ return;
+
+ map_fd = bpf_map__fd(skel->maps.sk_stg_map);
+
+ sock_fd = socket(AF_INET6, SOCK_STREAM, 0);
+ if (CHECK(sock_fd < 0, "socket", "errno: %d\n", errno))
+ goto out;
+ err = bpf_map_update_elem(map_fd, &sock_fd, &val, BPF_NOEXIST);
+ if (CHECK(err, "map_update", "map_update failed\n"))
+ goto out;
+
+ memset(&linfo, 0, sizeof(linfo));
+ linfo.map.map_fd = map_fd;
+ opts.link_info = &linfo;
+ opts.link_info_len = sizeof(linfo);
+ link = bpf_program__attach_iter(skel->progs.delete_bpf_sk_storage_map,
+ &opts);
+ if (CHECK(IS_ERR(link), "attach_iter", "attach_iter failed\n"))
+ goto out;
+
+ iter_fd = bpf_iter_create(bpf_link__fd(link));
+ if (CHECK(iter_fd < 0, "create_iter", "create_iter failed\n"))
+ goto free_link;
+
+ /* do some tests */
+ while ((len = read(iter_fd, buf, sizeof(buf))) > 0)
+ ;
+ if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno)))
+ goto close_iter;
+
+ /* test results */
+ err = bpf_map_lookup_elem(map_fd, &sock_fd, &val);
+ if (CHECK(!err || errno != ENOENT, "bpf_map_lookup_elem",
+ "map value wasn't deleted (err=%d, errno=%d)\n", err, errno))
+ goto close_iter;
+
+close_iter:
+ close(iter_fd);
+free_link:
+ bpf_link__destroy(link);
+out:
+ if (sock_fd >= 0)
+ close(sock_fd);
+ bpf_iter_bpf_sk_storage_helpers__destroy(skel);
+}
+
static void test_bpf_sk_storage_map(void)
{
DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts);
@@ -1067,6 +1129,8 @@ void test_bpf_iter(void)
test_bpf_percpu_array_map();
if (test__start_subtest("bpf_sk_storage_map"))
test_bpf_sk_storage_map();
+ if (test__start_subtest("bpf_sk_storage_delete"))
+ test_bpf_sk_storage_delete();
if (test__start_subtest("rdonly-buf-out-of-bound"))
test_rdonly_buf_out_of_bound();
if (test__start_subtest("buf-neg-offset"))
diff --git a/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c b/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c
new file mode 100644
index 000000000000..01ff3235e413
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2020 Google LLC. */
+#include "bpf_iter.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+char _license[] SEC("license") = "GPL";
+
+struct {
+ __uint(type, BPF_MAP_TYPE_SK_STORAGE);
+ __uint(map_flags, BPF_F_NO_PREALLOC);
+ __type(key, int);
+ __type(value, int);
+} sk_stg_map SEC(".maps");
+
+SEC("iter/bpf_sk_storage_map")
+int delete_bpf_sk_storage_map(struct bpf_iter__bpf_sk_storage_map *ctx)
+{
+ if (ctx->sk)
+ bpf_sk_storage_delete(&sk_stg_map, ctx->sk);
+
+ return 0;
+}
--
2.29.2.454.gaff20da3a2-goog
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH bpf-next v3 5/6] bpf: Add an iterator selftest for bpf_sk_storage_get
2020-11-26 16:44 [PATCH bpf-next v3 1/6] net: Remove the err argument from sock_from_file Florent Revest
` (2 preceding siblings ...)
2020-11-26 16:44 ` [PATCH bpf-next v3 4/6] bpf: Add an iterator selftest for bpf_sk_storage_delete Florent Revest
@ 2020-11-26 16:44 ` Florent Revest
2020-11-27 7:00 ` Yonghong Song
2020-11-26 16:44 ` [PATCH bpf-next v3 6/6] bpf: Test bpf_sk_storage_get in tcp iterators Florent Revest
2020-11-26 22:58 ` [PATCH bpf-next v3 1/6] net: Remove the err argument from sock_from_file KP Singh
5 siblings, 1 reply; 11+ messages in thread
From: Florent Revest @ 2020-11-26 16:44 UTC (permalink / raw)
To: bpf
Cc: viro, davem, kuba, ast, daniel, kafai, yhs, andrii, kpsingh,
revest, linux-kernel, netdev
The eBPF program iterates over all files and tasks. For all socket
files, it stores the tgid of the last task it encountered with a handle
to that socket. This is a heuristic for finding the "owner" of a socket
similar to what's done by lsof, ss, netstat or fuser. Potentially, this
information could be used from a cgroup_skb/*gress hook to try to
associate network traffic with processes.
The test makes sure that a socket it created is tagged with prog_tests's
pid.
Signed-off-by: Florent Revest <revest@google.com>
---
.../selftests/bpf/prog_tests/bpf_iter.c | 40 +++++++++++++++++++
.../progs/bpf_iter_bpf_sk_storage_helpers.c | 25 ++++++++++++
2 files changed, 65 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
index bb4a638f2e6f..9336d0f18331 100644
--- a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
+++ b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
@@ -975,6 +975,44 @@ static void test_bpf_sk_storage_delete(void)
bpf_iter_bpf_sk_storage_helpers__destroy(skel);
}
+/* This creates a socket and its local storage. It then runs a task_iter BPF
+ * program that replaces the existing socket local storage with the tgid of the
+ * only task owning a file descriptor to this socket, this process, prog_tests.
+ */
+static void test_bpf_sk_storage_get(void)
+{
+ struct bpf_iter_bpf_sk_storage_helpers *skel;
+ int err, map_fd, val = -1;
+ int sock_fd = -1;
+
+ skel = bpf_iter_bpf_sk_storage_helpers__open_and_load();
+ if (CHECK(!skel, "bpf_iter_bpf_sk_storage_helpers__open_and_load",
+ "skeleton open_and_load failed\n"))
+ return;
+
+ sock_fd = socket(AF_INET6, SOCK_STREAM, 0);
+ if (CHECK(sock_fd < 0, "socket", "errno: %d\n", errno))
+ goto out;
+
+ map_fd = bpf_map__fd(skel->maps.sk_stg_map);
+
+ err = bpf_map_update_elem(map_fd, &sock_fd, &val, BPF_NOEXIST);
+ if (CHECK(err, "bpf_map_update_elem", "map_update_failed\n"))
+ goto close_socket;
+
+ do_dummy_read(skel->progs.fill_socket_owner);
+
+ err = bpf_map_lookup_elem(map_fd, &sock_fd, &val);
+ CHECK(err || val != getpid(), "bpf_map_lookup_elem",
+ "map value wasn't set correctly (expected %d, got %d, err=%d)\n",
+ getpid(), val, err);
+
+close_socket:
+ close(sock_fd);
+out:
+ bpf_iter_bpf_sk_storage_helpers__destroy(skel);
+}
+
static void test_bpf_sk_storage_map(void)
{
DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts);
@@ -1131,6 +1169,8 @@ void test_bpf_iter(void)
test_bpf_sk_storage_map();
if (test__start_subtest("bpf_sk_storage_delete"))
test_bpf_sk_storage_delete();
+ if (test__start_subtest("bpf_sk_storage_get"))
+ test_bpf_sk_storage_get();
if (test__start_subtest("rdonly-buf-out-of-bound"))
test_rdonly_buf_out_of_bound();
if (test__start_subtest("buf-neg-offset"))
diff --git a/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c b/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c
index 01ff3235e413..d7a7a802d172 100644
--- a/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c
+++ b/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c
@@ -21,3 +21,28 @@ int delete_bpf_sk_storage_map(struct bpf_iter__bpf_sk_storage_map *ctx)
return 0;
}
+
+SEC("iter/task_file")
+int fill_socket_owner(struct bpf_iter__task_file *ctx)
+{
+ struct task_struct *task = ctx->task;
+ struct file *file = ctx->file;
+ struct socket *sock;
+ int *sock_tgid;
+
+ if (!task || !file || task->tgid != task->pid)
+ return 0;
+
+ sock = bpf_sock_from_file(file);
+ if (!sock)
+ return 0;
+
+ sock_tgid = bpf_sk_storage_get(&sk_stg_map, sock->sk, 0, 0);
+ if (!sock_tgid)
+ return 0;
+
+ *sock_tgid = task->tgid;
+
+ return 0;
+}
+
--
2.29.2.454.gaff20da3a2-goog
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH bpf-next v3 5/6] bpf: Add an iterator selftest for bpf_sk_storage_get
2020-11-26 16:44 ` [PATCH bpf-next v3 5/6] bpf: Add an iterator selftest for bpf_sk_storage_get Florent Revest
@ 2020-11-27 7:00 ` Yonghong Song
2020-11-27 9:21 ` Florent Revest
0 siblings, 1 reply; 11+ messages in thread
From: Yonghong Song @ 2020-11-27 7:00 UTC (permalink / raw)
To: Florent Revest, bpf
Cc: viro, davem, kuba, ast, daniel, kafai, andrii, kpsingh, revest,
linux-kernel, netdev
On 11/26/20 8:44 AM, Florent Revest wrote:
> The eBPF program iterates over all files and tasks. For all socket
> files, it stores the tgid of the last task it encountered with a handle
> to that socket. This is a heuristic for finding the "owner" of a socket
> similar to what's done by lsof, ss, netstat or fuser. Potentially, this
> information could be used from a cgroup_skb/*gress hook to try to
> associate network traffic with processes.
>
> The test makes sure that a socket it created is tagged with prog_tests's
> pid.
>
> Signed-off-by: Florent Revest <revest@google.com>
Ack with two minor comments below.
Acked-by: Yonghong Song <yhs@fb.com>
> ---
> .../selftests/bpf/prog_tests/bpf_iter.c | 40 +++++++++++++++++++
> .../progs/bpf_iter_bpf_sk_storage_helpers.c | 25 ++++++++++++
> 2 files changed, 65 insertions(+)
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
> index bb4a638f2e6f..9336d0f18331 100644
> --- a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
> +++ b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
> @@ -975,6 +975,44 @@ static void test_bpf_sk_storage_delete(void)
> bpf_iter_bpf_sk_storage_helpers__destroy(skel);
> }
>
> +/* This creates a socket and its local storage. It then runs a task_iter BPF
> + * program that replaces the existing socket local storage with the tgid of the
> + * only task owning a file descriptor to this socket, this process, prog_tests.
> + */
> +static void test_bpf_sk_storage_get(void)
> +{
> + struct bpf_iter_bpf_sk_storage_helpers *skel;
> + int err, map_fd, val = -1;
> + int sock_fd = -1;
> +
> + skel = bpf_iter_bpf_sk_storage_helpers__open_and_load();
> + if (CHECK(!skel, "bpf_iter_bpf_sk_storage_helpers__open_and_load",
> + "skeleton open_and_load failed\n"))
> + return;
> +
> + sock_fd = socket(AF_INET6, SOCK_STREAM, 0);
> + if (CHECK(sock_fd < 0, "socket", "errno: %d\n", errno))
> + goto out;
> +
> + map_fd = bpf_map__fd(skel->maps.sk_stg_map);
> +
> + err = bpf_map_update_elem(map_fd, &sock_fd, &val, BPF_NOEXIST);
> + if (CHECK(err, "bpf_map_update_elem", "map_update_failed\n"))
> + goto close_socket;
> +
> + do_dummy_read(skel->progs.fill_socket_owner);
> +
> + err = bpf_map_lookup_elem(map_fd, &sock_fd, &val);
> + CHECK(err || val != getpid(), "bpf_map_lookup_elem",
> + "map value wasn't set correctly (expected %d, got %d, err=%d)\n",
> + getpid(), val, err);
> +
> +close_socket:
> + close(sock_fd);
> +out:
> + bpf_iter_bpf_sk_storage_helpers__destroy(skel);
> +}
> +
> static void test_bpf_sk_storage_map(void)
> {
> DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts);
> @@ -1131,6 +1169,8 @@ void test_bpf_iter(void)
> test_bpf_sk_storage_map();
> if (test__start_subtest("bpf_sk_storage_delete"))
> test_bpf_sk_storage_delete();
> + if (test__start_subtest("bpf_sk_storage_get"))
> + test_bpf_sk_storage_get();
> if (test__start_subtest("rdonly-buf-out-of-bound"))
> test_rdonly_buf_out_of_bound();
> if (test__start_subtest("buf-neg-offset"))
> diff --git a/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c b/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c
> index 01ff3235e413..d7a7a802d172 100644
> --- a/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c
> +++ b/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c
> @@ -21,3 +21,28 @@ int delete_bpf_sk_storage_map(struct bpf_iter__bpf_sk_storage_map *ctx)
>
> return 0;
> }
> +
> +SEC("iter/task_file")
> +int fill_socket_owner(struct bpf_iter__task_file *ctx)
> +{
> + struct task_struct *task = ctx->task;
> + struct file *file = ctx->file;
> + struct socket *sock;
> + int *sock_tgid;
> +
> + if (!task || !file || task->tgid != task->pid)
task->tgid != task->pid is not needed here.
The task_file iterator already tries to skip task with task->pid
if its file table is the same as task->tgid.
> + return 0;
> +
> + sock = bpf_sock_from_file(file);
> + if (!sock)
> + return 0;
> +
> + sock_tgid = bpf_sk_storage_get(&sk_stg_map, sock->sk, 0, 0);
> + if (!sock_tgid)
> + return 0;
> +
> + *sock_tgid = task->tgid;
> +
> + return 0;
> +}
> +
Extra empty line.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH bpf-next v3 5/6] bpf: Add an iterator selftest for bpf_sk_storage_get
2020-11-27 7:00 ` Yonghong Song
@ 2020-11-27 9:21 ` Florent Revest
0 siblings, 0 replies; 11+ messages in thread
From: Florent Revest @ 2020-11-27 9:21 UTC (permalink / raw)
To: Yonghong Song, bpf
Cc: viro, davem, kuba, ast, daniel, kafai, andrii, kpsingh, revest,
linux-kernel, netdev
On Thu, 2020-11-26 at 23:00 -0800, Yonghong Song wrote:
> On 11/26/20 8:44 AM, Florent Revest wrote:
> > +SEC("iter/task_file")
> > +int fill_socket_owner(struct bpf_iter__task_file *ctx)
> > +{
> > + struct task_struct *task = ctx->task;
> > + struct file *file = ctx->file;
> > + struct socket *sock;
> > + int *sock_tgid;
> > +
> > + if (!task || !file || task->tgid != task->pid)
>
> task->tgid != task->pid is not needed here.
> The task_file iterator already tries to skip task with task->pid
> if its file table is the same as task->tgid.
Good to know!
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH bpf-next v3 6/6] bpf: Test bpf_sk_storage_get in tcp iterators
2020-11-26 16:44 [PATCH bpf-next v3 1/6] net: Remove the err argument from sock_from_file Florent Revest
` (3 preceding siblings ...)
2020-11-26 16:44 ` [PATCH bpf-next v3 5/6] bpf: Add an iterator selftest for bpf_sk_storage_get Florent Revest
@ 2020-11-26 16:44 ` Florent Revest
2020-11-27 7:02 ` Yonghong Song
2020-11-26 22:58 ` [PATCH bpf-next v3 1/6] net: Remove the err argument from sock_from_file KP Singh
5 siblings, 1 reply; 11+ messages in thread
From: Florent Revest @ 2020-11-26 16:44 UTC (permalink / raw)
To: bpf
Cc: viro, davem, kuba, ast, daniel, kafai, yhs, andrii, kpsingh,
revest, linux-kernel, netdev
This extends the existing bpf_sk_storage_get test where a socket is
created and tagged with its creator's pid by a task_file iterator.
A TCP iterator is now also used at the end of the test to negate the
values already stored in the local storage. The test therefore expects
-getpid() to be stored in the local storage.
Signed-off-by: Florent Revest <revest@google.com>
---
.../selftests/bpf/prog_tests/bpf_iter.c | 13 +++++++++++++
.../progs/bpf_iter_bpf_sk_storage_helpers.c | 18 ++++++++++++++++++
2 files changed, 31 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
index 9336d0f18331..b8362147c9e3 100644
--- a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
+++ b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
@@ -978,6 +978,8 @@ static void test_bpf_sk_storage_delete(void)
/* This creates a socket and its local storage. It then runs a task_iter BPF
* program that replaces the existing socket local storage with the tgid of the
* only task owning a file descriptor to this socket, this process, prog_tests.
+ * It then runs a tcp socket iterator that negates the value in the existing
+ * socket local storage, the test verifies that the resulting value is -pid.
*/
static void test_bpf_sk_storage_get(void)
{
@@ -994,6 +996,10 @@ static void test_bpf_sk_storage_get(void)
if (CHECK(sock_fd < 0, "socket", "errno: %d\n", errno))
goto out;
+ err = listen(sock_fd, 1);
+ if (CHECK(err != 0, "listen", "errno: %d\n", errno))
+ goto out;
+
map_fd = bpf_map__fd(skel->maps.sk_stg_map);
err = bpf_map_update_elem(map_fd, &sock_fd, &val, BPF_NOEXIST);
@@ -1007,6 +1013,13 @@ static void test_bpf_sk_storage_get(void)
"map value wasn't set correctly (expected %d, got %d, err=%d)\n",
getpid(), val, err);
+ do_dummy_read(skel->progs.negate_socket_local_storage);
+
+ err = bpf_map_lookup_elem(map_fd, &sock_fd, &val);
+ CHECK(err || val != -getpid(), "bpf_map_lookup_elem",
+ "map value wasn't set correctly (expected %d, got %d, err=%d)\n",
+ -getpid(), val, err);
+
close_socket:
close(sock_fd);
out:
diff --git a/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c b/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c
index d7a7a802d172..b3f0cb139c55 100644
--- a/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c
+++ b/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c
@@ -46,3 +46,21 @@ int fill_socket_owner(struct bpf_iter__task_file *ctx)
return 0;
}
+SEC("iter/tcp")
+int negate_socket_local_storage(struct bpf_iter__tcp *ctx)
+{
+ struct sock_common *sk_common = ctx->sk_common;
+ int *sock_tgid;
+
+ if (!sk_common)
+ return 0;
+
+ sock_tgid = bpf_sk_storage_get(&sk_stg_map, sk_common, 0, 0);
+ if (!sock_tgid)
+ return 0;
+
+ *sock_tgid = -*sock_tgid;
+
+ return 0;
+}
+
--
2.29.2.454.gaff20da3a2-goog
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH bpf-next v3 6/6] bpf: Test bpf_sk_storage_get in tcp iterators
2020-11-26 16:44 ` [PATCH bpf-next v3 6/6] bpf: Test bpf_sk_storage_get in tcp iterators Florent Revest
@ 2020-11-27 7:02 ` Yonghong Song
0 siblings, 0 replies; 11+ messages in thread
From: Yonghong Song @ 2020-11-27 7:02 UTC (permalink / raw)
To: Florent Revest, bpf
Cc: viro, davem, kuba, ast, daniel, kafai, andrii, kpsingh, revest,
linux-kernel, netdev
On 11/26/20 8:44 AM, Florent Revest wrote:
> This extends the existing bpf_sk_storage_get test where a socket is
> created and tagged with its creator's pid by a task_file iterator.
>
> A TCP iterator is now also used at the end of the test to negate the
> values already stored in the local storage. The test therefore expects
> -getpid() to be stored in the local storage.
>
> Signed-off-by: Florent Revest <revest@google.com>
Ack with a minor comment below.
Acked-by: Yonghong Song <yhs@fb.com>
> ---
> .../selftests/bpf/prog_tests/bpf_iter.c | 13 +++++++++++++
> .../progs/bpf_iter_bpf_sk_storage_helpers.c | 18 ++++++++++++++++++
> 2 files changed, 31 insertions(+)
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
> index 9336d0f18331..b8362147c9e3 100644
> --- a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
> +++ b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
> @@ -978,6 +978,8 @@ static void test_bpf_sk_storage_delete(void)
> /* This creates a socket and its local storage. It then runs a task_iter BPF
> * program that replaces the existing socket local storage with the tgid of the
> * only task owning a file descriptor to this socket, this process, prog_tests.
> + * It then runs a tcp socket iterator that negates the value in the existing
> + * socket local storage, the test verifies that the resulting value is -pid.
> */
> static void test_bpf_sk_storage_get(void)
> {
> @@ -994,6 +996,10 @@ static void test_bpf_sk_storage_get(void)
> if (CHECK(sock_fd < 0, "socket", "errno: %d\n", errno))
> goto out;
>
> + err = listen(sock_fd, 1);
> + if (CHECK(err != 0, "listen", "errno: %d\n", errno))
> + goto out;
> +
> map_fd = bpf_map__fd(skel->maps.sk_stg_map);
>
> err = bpf_map_update_elem(map_fd, &sock_fd, &val, BPF_NOEXIST);
> @@ -1007,6 +1013,13 @@ static void test_bpf_sk_storage_get(void)
> "map value wasn't set correctly (expected %d, got %d, err=%d)\n",
> getpid(), val, err);
>
> + do_dummy_read(skel->progs.negate_socket_local_storage);
> +
> + err = bpf_map_lookup_elem(map_fd, &sock_fd, &val);
> + CHECK(err || val != -getpid(), "bpf_map_lookup_elem",
> + "map value wasn't set correctly (expected %d, got %d, err=%d)\n",
> + -getpid(), val, err);
> +
> close_socket:
> close(sock_fd);
> out:
> diff --git a/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c b/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c
> index d7a7a802d172..b3f0cb139c55 100644
> --- a/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c
> +++ b/tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c
> @@ -46,3 +46,21 @@ int fill_socket_owner(struct bpf_iter__task_file *ctx)
> return 0;
> }
>
> +SEC("iter/tcp")
> +int negate_socket_local_storage(struct bpf_iter__tcp *ctx)
> +{
> + struct sock_common *sk_common = ctx->sk_common;
> + int *sock_tgid;
> +
> + if (!sk_common)
> + return 0;
> +
> + sock_tgid = bpf_sk_storage_get(&sk_stg_map, sk_common, 0, 0);
> + if (!sock_tgid)
> + return 0;
> +
> + *sock_tgid = -*sock_tgid;
> +
> + return 0;
> +}
> +
extra empty line here.
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH bpf-next v3 1/6] net: Remove the err argument from sock_from_file
2020-11-26 16:44 [PATCH bpf-next v3 1/6] net: Remove the err argument from sock_from_file Florent Revest
` (4 preceding siblings ...)
2020-11-26 16:44 ` [PATCH bpf-next v3 6/6] bpf: Test bpf_sk_storage_get in tcp iterators Florent Revest
@ 2020-11-26 22:58 ` KP Singh
5 siblings, 0 replies; 11+ messages in thread
From: KP Singh @ 2020-11-26 22:58 UTC (permalink / raw)
To: Florent Revest
Cc: bpf, Al Viro, David S. Miller, Jakub Kicinski,
Alexei Starovoitov, Daniel Borkmann, Martin KaFai Lau,
Yonghong Song, Andrii Nakryiko, Florent Revest, open list,
Networking
On Thu, Nov 26, 2020 at 5:45 PM Florent Revest <revest@chromium.org> wrote:
>
> Currently, the sock_from_file prototype takes an "err" pointer that is
> either not set or set to -ENOTSOCK IFF the returned socket is NULL. This
> makes the error redundant and it is ignored by a few callers.
>
> This patch simplifies the API by letting callers deduce the error based
> on whether the returned socket is NULL or not.
>
> Suggested-by: Al Viro <viro@zeniv.linux.org.uk>
> Signed-off-by: Florent Revest <revest@google.com>
Reviewed-by: KP Singh <kpsingh@google.com>
^ permalink raw reply [flat|nested] 11+ messages in thread