BPF List
 help / color / mirror / Atom feed
* [PATCH bpf-next v4] bpf: allow ksock connect/send calls from wq
@ 2026-10-14  9:57 Mahe Tardy
  2026-10-14 10:48 ` bot+bpf-ci
  0 siblings, 1 reply; 3+ messages in thread
From: Mahe Tardy @ 2026-10-14  9:57 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, alan.maguire, 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.

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 connect() or 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 connect() and
send() kfuncs are now allowed and work when called from workqueues.

Note that bpf_ksock_create() still checks for workqueue context
execution and makes sure the current->nsproxy is defined as we rely on
the network namespace to be defined (could be NULL in the case do_exit()
was called on the task before the wq was scheduled) and to be the one
from the task that triggered the SYSCALL bpf prog.

[^1]: https://lpc.events/event/20/contributions/2430/

Signed-off-by: Mahe Tardy <mahe.tardy@gmail.com>
---
I resent v2 as v3 instead of this fix by mistake, ignore v3.
v3: https://lore.kernel.org/bpf/20261014091450.19107-1-mahe.tardy@gmail.com/

 net/core/bpf_ksock.c                          | 27 +------
 .../selftests/bpf/prog_tests/ksock_wq.c       | 29 +++++--
 tools/testing/selftests/bpf/progs/ksock_wq.c  | 77 +++++++++++++++----
 3 files changed, 92 insertions(+), 41 deletions(-)

diff --git a/net/core/bpf_ksock.c b/net/core/bpf_ksock.c
index e9943aeeadd3..f74968397798 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();

 /**
@@ -59,7 +50,7 @@ __bpf_kfunc_start_defs();
  * This function may sleep (sock_create), so it can only be used
  * in sleepable BPF programs (SYSCALL).
  * It cannot be called from a BPF workqueue callback because that callback
- * does not retain the invoking task's namespace or security context.
+ * does not retain the invoking task's namespace.
  *
  * @opts:	Pointer to struct bpf_ksock_create_opts with socket parameters.
  * @opts__sz:	Size of the opts struct.
@@ -73,13 +64,9 @@ 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;
+	/* sock_create() derives the network namespace from current. */
+	if ((current->flags & PF_KTHREAD) || !current->nsproxy) {
+		err = -EPERM;
 		goto err_out;
 	}

@@ -165,9 +152,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 +231,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..cb50f9a1be2e 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"))
@@ -28,18 +38,27 @@ void test_ksock_wq(void)
 		goto out;

 	for (i = 0; i < CALLBACK_WAIT_RETRIES; i++) {
-		if (__atomic_load_n(&skel->bss->callback_done, __ATOMIC_ACQUIRE))
+		if (__atomic_load_n(&skel->bss->callback_done, __ATOMIC_ACQUIRE) == 2)
 			break;
 		usleep(CALLBACK_WAIT_US);
 	}
 	callback_done = __atomic_load_n(&skel->bss->callback_done,
 					__ATOMIC_ACQUIRE);
-	if (!ASSERT_EQ(callback_done, 1, "workqueue callback completed"))
+	if (!ASSERT_EQ(callback_done, 2, "workqueue callbacks completed"))
 		goto out;

-	ASSERT_EQ(skel->bss->create_err, -EOPNOTSUPP,
-		  "workqueue create rejected");
+	ASSERT_EQ(skel->bss->create_ret, -EPERM, "workqueue create rejected");
+
+	if (!ASSERT_EQ(skel->bss->connect_send_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..6ec6103e2518 100644
--- a/tools/testing/selftests/bpf/progs/ksock_wq.c
+++ b/tools/testing/selftests/bpf/progs/ksock_wq.c
@@ -2,9 +2,11 @@
 /* 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"
+#include "bpf_misc.h"
 #include "errno.h"
 #include "ksock_common.h"

@@ -14,15 +16,19 @@ struct ksock_wq_value {

 struct {
 	__uint(type, BPF_MAP_TYPE_ARRAY);
-	__uint(max_entries, 1);
+	__uint(max_entries, 2);
 	__type(key, u32);
 	__type(value, struct ksock_wq_value);
 } work_map SEC(".maps");

-int create_err;
+char send_data[] = "hello from bpf workqueue";
+
+__be16 remote_port;
+int connect_send_ret;
+int create_ret;
 u32 callback_done;

-static int ksock_wq_callback(void *map, int *key, void *value)
+static int ksock_wq_create(void *map, int *key, void *value)
 {
 	struct bpf_ksock_create_opts opts = {
 		.family = AF_INET,
@@ -35,7 +41,32 @@ static int ksock_wq_callback(void *map, int *key, void *value)
 	ks = bpf_ksock_create(&opts, sizeof(opts), &err);
 	if (ks)
 		bpf_ksock_release(ks);
-	create_err = err;
+	create_ret = err;
+	__sync_fetch_and_add(&callback_done, 1);
+	return 0;
+}
+
+static int ksock_wq_connect_send(void *map, int *key, void *value)
+{
+	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 = -ENOENT;
+
+	ks = ksock_ctx_get();
+	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:
+	connect_send_ret = err;
 	__sync_fetch_and_add(&callback_done, 1);
 	return 0;
 }
@@ -43,20 +74,40 @@ static int ksock_wq_callback(void *map, int *key, void *value)
 SEC("syscall")
 int ksock_wq_start(void *ctx)
 {
+	struct bpf_ksock_create_opts opts = {
+		.family = AF_INET,
+		.type = SOCK_DGRAM,
+		.protocol = IPPROTO_UDP,
+	};
 	struct ksock_wq_value *value;
-	u32 key = 0;
-	int err;
+	u32 key __aligned(8) = 0;
+	struct bpf_ksock *ks;
+	int err = 0;

-	value = bpf_map_lookup_elem(&work_map, &key);
-	if (!value)
-		return -ENOENT;
-	err = bpf_wq_init(&value->work, &work_map, 0);
-	if (err)
+	ks = bpf_ksock_create(&opts, sizeof(opts), &err);
+	if (!ks)
 		return err;
-	err = bpf_wq_set_callback(&value->work, ksock_wq_callback, 0);
+	err = ksock_ctx_insert(ks);
 	if (err)
 		return err;
-	return bpf_wq_start(&value->work, 0);
+	for (key = 0; key < 2; key++) {
+		value = bpf_map_lookup_elem(&work_map, &key);
+		if (!value)
+			return -ENOENT;
+		err = bpf_wq_init(&value->work, &work_map, 0);
+		if (err)
+			return err;
+		if (key)
+			err = bpf_wq_set_callback(&value->work, ksock_wq_create, 0);
+		else
+			err = bpf_wq_set_callback(&value->work, ksock_wq_connect_send, 0);
+		if (err)
+			return err;
+		err = bpf_wq_start(&value->work, 0);
+		if (err)
+			return err;
+	}
+	return 0;
 }

 char __license[] SEC("license") = "GPL";
--
2.43.0


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

* Re: [PATCH bpf-next v4] bpf: allow ksock connect/send calls from wq
  2026-10-14  9:57 [PATCH bpf-next v4] bpf: allow ksock connect/send calls from wq Mahe Tardy
@ 2026-10-14 10:48 ` bot+bpf-ci
  2026-10-14 11:04   ` Mahe Tardy
  0 siblings, 1 reply; 3+ messages in thread
From: bot+bpf-ci @ 2026-10-14 10:48 UTC (permalink / raw)
  To: mahe.tardy, bpf
  Cc: andrii, ast, daniel, davem, eddyz87, edumazet, john.fastabend,
	kuba, liamwisehart, martin.lau, pabeni, song, netdev, sdf.kernel,
	ameryhung, kuniyu, memxor, jiayuan.chen, alan.maguire, mahe.tardy,
	ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, mason,
	ihor.solodrai

[-- Attachment #1: Type: text/plain, Size: 5860 bytes --]

> bpf: allow ksock connect/send calls from wq

TL;DR:
- Changelog's nsproxy explanation looks wrong, and it omits newly allowed
  task_work and LSM-kthread contexts
- bpf_ksock_create() error change to -EPERM may be indistinguishable from LSM
  denial

> bpf: allow ksock connect/send calls from wq
>
> 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.
>
> 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 connect() or 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 connect() and
> send() kfuncs are now allowed and work when called from workqueues.
>
> Note that bpf_ksock_create() still checks for workqueue context
> execution and makes sure the current->nsproxy is defined as we rely on
> the network namespace to be defined (could be NULL in the case do_exit()
> was called on the task before the wq was scheduled) and to be the one
> from the task that triggered the SYSCALL bpf prog.
>
> [^1]: https://lpc.events/event/20/contributions/2430/
>
> Signed-off-by: Mahe Tardy <mahe.tardy@gmail.com>

Is the nsproxy explanation in the last paragraph accurate?  The changelog
says current->nsproxy "could be NULL in the case do_exit() was called on the
task before the wq was scheduled".

A bpf_wq callback runs from bpf_wq_work() on a kworker, so current is the
kworker.  Its nsproxy is init_nsproxy and is never NULL, and the PF_KTHREAD
test already rejects it.  The triggering task calling do_exit() has no
effect on the kworker's nsproxy.

The case where !PF_KTHREAD && current->nsproxy == NULL comes from
bpf_task_work callbacks.  bpf_task_work_schedule_signal() and
bpf_task_work_schedule_resume() are registered for BPF_PROG_TYPE_UNSPEC, and
is_async_cb_sleepable() returns true for them.  Their callbacks run via
exit_task_work() after exit_nsproxy_namespaces() in do_exit():

    kernel/exit.c:do_exit() {
        ...
        exit_files(tsk);
        exit_fs(tsk);
        ...
        exit_nsproxy_namespaces(tsk);
        exit_task_work(tsk);
        ...
    }

The removed comment in bpf_ksock_has_user_task_context() described this
correctly:

    Task work can run from do_exit() after exit_nsproxy_namespaces()
    cleared current->nsproxy, while current is still not a kthread.

The replacement comment in bpf_ksock_create(), "sock_create() derives the
network namespace from current.", no longer says why nsproxy can be NULL.

In the task_work case, current is the task the work was queued on.  That is
not necessarily the task that ran the SYSCALL program, so "to be the one
from the task that triggered the SYSCALL bpf prog" is not guaranteed either.

The changelog also describes the change as only allowing connect/send from
workqueues.  Removing the runtime check from bpf_ksock_connect() and
bpf_ksock_send() also newly allows:

- connect/send from bpf_task_work callbacks running in exiting tasks
  (nsproxy, fs, files and mm already torn down)
- bpf_ksock_send() from LSM programs running in kernel threads

Neither is mentioned.  No functional breakage was found in those paths,
because UDP connect/send use sock_net(sk) rather than current->nsproxy.

Should the changelog and the comment describe the contexts that are actually
allowed and why?

> diff --git a/net/core/bpf_ksock.c b/net/core/bpf_ksock.c
> index e9943aeeadd3..f74968397798 100644
> --- a/net/core/bpf_ksock.c
> +++ b/net/core/bpf_ksock.c

[ ... ]

> @@ -73,13 +64,9 @@ 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;
> +	/* sock_create() derives the network namespace from current. */
> +	if ((current->flags & PF_KTHREAD) || !current->nsproxy) {
> +		err = -EPERM;
                ^^^^

Was the change of the error reported through err__uninit from -EOPNOTSUPP to
-EPERM intentional?  The changelog doesn't mention it.

-EPERM is also a normal result of the sock_create() call further down.
__sock_create() calls security_socket_create(), and LSMs, BPF LSM programs
in particular, commonly deny with -EPERM.

After this change, can a BPF program that gets NULL with err == -EPERM tell
"called from a workqueue/kthread context" apart from "socket creation denied
by LSM policy"?

Programs written against the original 7ae4eb14c5f9 semantics that check for
-EOPNOTSUPP would also silently stop matching.  If the change is
intentional, could the changelog explain it?  Otherwise, keeping -EOPNOTSUPP
would preserve the unambiguous signal.

>  		goto err_out;
>  	}
>


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/38548134159

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

* Re: [PATCH bpf-next v4] bpf: allow ksock connect/send calls from wq
  2026-10-14 10:48 ` bot+bpf-ci
@ 2026-10-14 11:04   ` Mahe Tardy
  0 siblings, 0 replies; 3+ messages in thread
From: Mahe Tardy @ 2026-10-14 11:04 UTC (permalink / raw)
  To: bot+bpf-ci
  Cc: bpf, andrii, ast, daniel, davem, eddyz87, edumazet,
	john.fastabend, kuba, liamwisehart, martin.lau, pabeni, song,
	netdev, sdf.kernel, ameryhung, kuniyu, memxor, jiayuan.chen,
	alan.maguire, martin.lau, yonghong.song, mason, ihor.solodrai

On Wed, Oct 14, 2026 at 10:48:26AM +0000, bot+bpf-ci@kernel.org wrote:
> > bpf: allow ksock connect/send calls from wq
> 
> TL;DR:
> - Changelog's nsproxy explanation looks wrong, and it omits newly allowed
>   task_work and LSM-kthread contexts
> - bpf_ksock_create() error change to -EPERM may be indistinguishable from LSM
>   denial

Valid review: I'll push changes for those two points (changing error
back to EOPNOTSUPP and improve the changelog) if we need a v5.

> 
> > bpf: allow ksock connect/send calls from wq
> >
> > 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.
> >
> > 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 connect() or 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 connect() and
> > send() kfuncs are now allowed and work when called from workqueues.
> >
> > Note that bpf_ksock_create() still checks for workqueue context
> > execution and makes sure the current->nsproxy is defined as we rely on
> > the network namespace to be defined (could be NULL in the case do_exit()
> > was called on the task before the wq was scheduled) and to be the one
> > from the task that triggered the SYSCALL bpf prog.
> >
> > [^1]: https://lpc.events/event/20/contributions/2430/
> >
> > Signed-off-by: Mahe Tardy <mahe.tardy@gmail.com>
> 
> Is the nsproxy explanation in the last paragraph accurate?  The changelog
> says current->nsproxy "could be NULL in the case do_exit() was called on the
> task before the wq was scheduled".
> 
> A bpf_wq callback runs from bpf_wq_work() on a kworker, so current is the
> kworker.  Its nsproxy is init_nsproxy and is never NULL, and the PF_KTHREAD
> test already rejects it.  The triggering task calling do_exit() has no
> effect on the kworker's nsproxy.
> 
> The case where !PF_KTHREAD && current->nsproxy == NULL comes from
> bpf_task_work callbacks.  

Yes indeed this is for taskwork not workqueues in which we could face a
NULL current->nsproxy. I should update the changelog.

> bpf_task_work_schedule_signal() and
> bpf_task_work_schedule_resume() are registered for BPF_PROG_TYPE_UNSPEC, and
> is_async_cb_sleepable() returns true for them.  Their callbacks run via
> exit_task_work() after exit_nsproxy_namespaces() in do_exit():
> 
>     kernel/exit.c:do_exit() {
>         ...
>         exit_files(tsk);
>         exit_fs(tsk);
>         ...
>         exit_nsproxy_namespaces(tsk);
>         exit_task_work(tsk);
>         ...
>     }
> 
> The removed comment in bpf_ksock_has_user_task_context() described this
> correctly:
> 
>     Task work can run from do_exit() after exit_nsproxy_namespaces()
>     cleared current->nsproxy, while current is still not a kthread.
> 
> The replacement comment in bpf_ksock_create(), "sock_create() derives the
> network namespace from current.", no longer says why nsproxy can be NULL.

I might just keep this in the changelog instead of a code comment.

> In the task_work case, current is the task the work was queued on.  That is
> not necessarily the task that ran the SYSCALL program, so "to be the one
> from the task that triggered the SYSCALL bpf prog" is not guaranteed either.
> 
> The changelog also describes the change as only allowing connect/send from
> workqueues.  Removing the runtime check from bpf_ksock_connect() and
> bpf_ksock_send() also newly allows:
> 
> - connect/send from bpf_task_work callbacks running in exiting tasks
>   (nsproxy, fs, files and mm already torn down)
> - bpf_ksock_send() from LSM programs running in kernel threads
> 
> Neither is mentioned.  No functional breakage was found in those paths,
> because UDP connect/send use sock_net(sk) rather than current->nsproxy.
> 
> Should the changelog and the comment describe the contexts that are actually
> allowed and why?

Not sure we should mention this since those paths are safe since not
using current->nsproxy but the net associated with the socket. Might add
a line about it but this was generally the goal of this patch.

> 
> > diff --git a/net/core/bpf_ksock.c b/net/core/bpf_ksock.c
> > index e9943aeeadd3..f74968397798 100644
> > --- a/net/core/bpf_ksock.c
> > +++ b/net/core/bpf_ksock.c
> 
> [ ... ]
> 
> > @@ -73,13 +64,9 @@ 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;
> > +	/* sock_create() derives the network namespace from current. */
> > +	if ((current->flags & PF_KTHREAD) || !current->nsproxy) {
> > +		err = -EPERM;
>                 ^^^^
> 
> Was the change of the error reported through err__uninit from -EOPNOTSUPP to
> -EPERM intentional?  The changelog doesn't mention it.
> 
> -EPERM is also a normal result of the sock_create() call further down.
> __sock_create() calls security_socket_create(), and LSMs, BPF LSM programs
> in particular, commonly deny with -EPERM.
> 
> After this change, can a BPF program that gets NULL with err == -EPERM tell
> "called from a workqueue/kthread context" apart from "socket creation denied
> by LSM policy"?
> 
> Programs written against the original 7ae4eb14c5f9 semantics that check for
> -EOPNOTSUPP would also silently stop matching.  If the change is
> intentional, could the changelog explain it?  Otherwise, keeping -EOPNOTSUPP
> would preserve the unambiguous signal.

Maybe we can keep EOPNOTSUPP, no strong preference but the confusion
with LSM denial might be enough to justify this.

> 
> >  		goto err_out;
> >  	}
> >
> 
> 
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
> 
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/38548134159


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

end of thread, other threads:[~2026-10-14 11:04 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-14  9:57 [PATCH bpf-next v4] bpf: allow ksock connect/send calls from wq Mahe Tardy
2026-10-14 10:48 ` bot+bpf-ci
2026-10-14 11:04   ` Mahe Tardy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox