* [PATCH bpf-next] bpf: allow ksock kfuncs call from wq
@ 2026-10-13 16:31 Mahe Tardy
0 siblings, 0 replies; only message in thread
From: Mahe Tardy @ 2026-10-13 16:31 UTC (permalink / raw)
To: bpf
Cc: andrii, ast, daniel, davem, eddyz87, edumazet, john.fastabend,
kuba, liamwisehart, martin.lau, pabeni, song, netdev, sdf.kernel,
ameryhung, kuniyu, memxor, jiayuan.chen, Mahe Tardy
In the initial implementation in '7ae4eb14c5f9 ("bpf: Add ksock
kfuncs")', it was decided to let the ksock kfuncs go through the LSM
hooks instead of by-passing them, and thus to disallow the use of the
kfuncs from asynchronous workqueues as the credentials would be
different than the task context that triggered the kfuncs.
After some discussions, in particular at Plumbers 2026 at the
presentation introducing this new ksock API[^1], it was agreed that
by-passing the LSM from socket created by BPF programs should be okay
and thus that the process context switch from kthread executing the
workqueues wouldn't be an issue. Note also that in some BPF prog
execution context in which we could extend the ksock kfuncs, like
networking executing via softirq, the current task might be some
unrelated kernel thread.
For now, the ksock kfuncs still trigger the LSM hooks but we relax the
constraint on not using the workqueues as it will be useful for users
triggering send() from non-sleepable programs (like tracing, support
will be extended in future patches).
Also adapt test_ksock_wq() added in 'c93cbdb13f99 ("selftests/bpf: Add
ksock test for async callback guard")' to test that the kfuncs are now
allowed and work when called from workqueues.
[^1]: https://lpc.events/event/20/contributions/2430/
Signed-off-by: Mahe Tardy <mahe.tardy@gmail.com>
---
net/core/bpf_ksock.c | 25 -------------------
.../selftests/bpf/prog_tests/ksock_wq.c | 23 ++++++++++++++---
tools/testing/selftests/bpf/progs/ksock_wq.c | 24 +++++++++++++++---
3 files changed, 40 insertions(+), 32 deletions(-)
diff --git a/net/core/bpf_ksock.c b/net/core/bpf_ksock.c
index e9943aeeadd3..21d5fd1eb403 100644
--- a/net/core/bpf_ksock.c
+++ b/net/core/bpf_ksock.c
@@ -37,15 +37,6 @@ static void ksock_release_work_fn(struct work_struct *work)
kfree(ks);
}
-static bool bpf_ksock_has_user_task_context(void)
-{
- /*
- * Task work can run from do_exit() after exit_nsproxy_namespaces()
- * cleared current->nsproxy, while current is still not a kthread.
- */
- return !(current->flags & PF_KTHREAD) && current->nsproxy;
-}
-
__bpf_kfunc_start_defs();
/**
@@ -73,16 +64,6 @@ bpf_ksock_create(const struct bpf_ksock_create_opts *opts, u32 opts__sz,
struct bpf_ksock *ks;
int err;
- /*
- * sock_create() derives the network namespace, credentials, and cgroup
- * from current. Kernel threads, including BPF workqueue callbacks, do
- * not carry the context of the task that invoked the BPF program.
- */
- if (!bpf_ksock_has_user_task_context()) {
- err = -EOPNOTSUPP;
- goto err_out;
- }
-
if (!opts || opts__sz != sizeof(struct bpf_ksock_create_opts)) {
err = -EINVAL;
goto err_out;
@@ -165,9 +146,6 @@ __bpf_kfunc int bpf_ksock_connect(struct bpf_ksock *ks,
struct sockaddr_storage sa;
int addrlen;
- if (!bpf_ksock_has_user_task_context())
- return -EOPNOTSUPP;
-
if (!addr || addr__sz != sizeof(*addr))
return -EINVAL;
@@ -247,9 +225,6 @@ __bpf_kfunc int bpf_ksock_send(struct bpf_ksock *ks, const void *data,
};
int ret;
- if (!bpf_ksock_has_user_task_context())
- return -EOPNOTSUPP;
-
ret = kernel_sendmsg(ks->sock, &msg, &iov, 1, data__sz);
return ret;
diff --git a/tools/testing/selftests/bpf/prog_tests/ksock_wq.c b/tools/testing/selftests/bpf/prog_tests/ksock_wq.c
index d6dc20b8f95b..708e42abc57e 100644
--- a/tools/testing/selftests/bpf/prog_tests/ksock_wq.c
+++ b/tools/testing/selftests/bpf/prog_tests/ksock_wq.c
@@ -4,6 +4,7 @@
#include <unistd.h>
#include "test_progs.h"
+#include "network_helpers.h"
#include "ksock_wq.skel.h"
#define CALLBACK_WAIT_RETRIES 1000
@@ -13,13 +14,22 @@ void test_ksock_wq(void)
{
LIBBPF_OPTS(bpf_test_run_opts, opts);
struct ksock_wq *skel;
+ char recv_data[sizeof(skel->data->send_data)];
u32 callback_done;
- int err, i;
+ int err, i, port, rfd;
skel = ksock_wq__open_and_load();
if (!ASSERT_OK_PTR(skel, "ksock_wq open and load"))
return;
+ rfd = start_server(AF_INET, SOCK_DGRAM, "127.0.0.1", 0, 1000);
+ if (!ASSERT_OK_FD(rfd, "receiver socket"))
+ goto out;
+ port = get_socket_local_port(rfd);
+ if (!ASSERT_GE(port, 0, "receiver port"))
+ goto out;
+ skel->bss->remote_port = port;
+
err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.ksock_wq_start),
&opts);
if (!ASSERT_OK(err, "run ksock_wq_start"))
@@ -37,9 +47,16 @@ void test_ksock_wq(void)
if (!ASSERT_EQ(callback_done, 1, "workqueue callback completed"))
goto out;
- ASSERT_EQ(skel->bss->create_err, -EOPNOTSUPP,
- "workqueue create rejected");
+ if (!ASSERT_EQ(skel->bss->callback_ret, sizeof(recv_data),
+ "workqueue send bytes"))
+ goto out;
+ err = recv(rfd, recv_data, sizeof(recv_data), 0);
+ if (ASSERT_EQ(err, sizeof(recv_data), "recv len"))
+ ASSERT_MEMEQ(recv_data, skel->data->send_data, sizeof(recv_data),
+ "payload match");
out:
+ if (rfd >= 0)
+ close(rfd);
ksock_wq__destroy(skel);
}
diff --git a/tools/testing/selftests/bpf/progs/ksock_wq.c b/tools/testing/selftests/bpf/progs/ksock_wq.c
index 16a1873d132e..0633ae048518 100644
--- a/tools/testing/selftests/bpf/progs/ksock_wq.c
+++ b/tools/testing/selftests/bpf/progs/ksock_wq.c
@@ -2,6 +2,7 @@
/* Copyright (c) 2026 Isovalent */
#include "vmlinux.h"
+#include <bpf/bpf_endian.h>
#include <bpf/bpf_helpers.h>
#include "bpf_experimental.h"
#include "bpf_tracing_net.h"
@@ -19,7 +20,10 @@ struct {
__type(value, struct ksock_wq_value);
} work_map SEC(".maps");
-int create_err;
+char send_data[] = "hello from bpf workqueue";
+
+__be16 remote_port;
+int callback_ret;
u32 callback_done;
static int ksock_wq_callback(void *map, int *key, void *value)
@@ -29,13 +33,25 @@ static int ksock_wq_callback(void *map, int *key, void *value)
.type = SOCK_DGRAM,
.protocol = IPPROTO_UDP,
};
+ union bpf_ksock_addr addr = {
+ .sin = {
+ .sin_family = AF_INET,
+ .sin_port = remote_port,
+ .sin_addr.s_addr = bpf_htonl(0x7f000001),
+ },
+ };
struct bpf_ksock *ks;
int err = 0;
ks = bpf_ksock_create(&opts, sizeof(opts), &err);
- if (ks)
- bpf_ksock_release(ks);
- create_err = err;
+ if (!ks)
+ goto out;
+ err = bpf_ksock_connect(ks, &addr, sizeof(addr));
+ if (!err)
+ err = bpf_ksock_send(ks, send_data, sizeof(send_data));
+ bpf_ksock_release(ks);
+out:
+ callback_ret = err;
__sync_fetch_and_add(&callback_done, 1);
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-13 16:31 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-13 16:31 [PATCH bpf-next] bpf: allow ksock kfuncs call from wq Mahe Tardy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox