* [PATCH bpf-next 1/2] bpf: Add bpf_ksock_bind() kfunc
@ 2026-10-22 18:16 Mahe Tardy
2026-10-22 18:16 ` [PATCH bpf-next 2/2] selftests/bpf: Test " Mahe Tardy
2026-10-22 18:45 ` [PATCH bpf-next 1/2] bpf: Add " bot+bpf-ci
0 siblings, 2 replies; 6+ messages in thread
From: Mahe Tardy @ 2026-10-22 18:16 UTC (permalink / raw)
To: bpf
Cc: andrii, ast, daniel, davem, willemb, eddyz87, edumazet,
john.fastabend, kuba, horms, liamwisehart, martin.lau, pabeni,
song, netdev, sdf.kernel, yonghong.song, jolsa, kuniyu, memxor,
emil, almagui, Mahe Tardy
Part of the effort to make ksock have all basic socket operations. This
is for example useful when replying to a peer which expects a message
from a particular source port.
Signed-off-by: Mahe Tardy <mahe.tardy@gmail.com>
---
net/core/bpf_ksock.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/net/core/bpf_ksock.c b/net/core/bpf_ksock.c
index 37168f43c16c..c7b487d90cd0 100644
--- a/net/core/bpf_ksock.c
+++ b/net/core/bpf_ksock.c
@@ -178,6 +178,33 @@ bpf_ksock_create(const struct bpf_ksock_create_opts *opts, u32 opts__sz,
return NULL;
}
+/**
+ * bpf_ksock_bind() - Bind a BPF kernel socket to a local address.
+ * @ks: The BPF kernel socket context.
+ * @addr: Pointer to an IPv4 or IPv6 socket address.
+ * @addr__sz: Size of the address union.
+ *
+ * Binds the socket to the specified local address and port. A port of zero
+ * selects an ephemeral port.
+ *
+ * This function may sleep, so it can only be used in sleepable BPF programs
+ * (SYSCALL).
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+__bpf_kfunc int bpf_ksock_bind(struct bpf_ksock *ks,
+ const union bpf_ksock_addr *addr, u32 addr__sz)
+{
+ struct sockaddr_storage sa;
+ int addrlen;
+
+ addrlen = bpf_ksock_addr_to_sockaddr(addr, addr__sz, &sa);
+ if (addrlen < 0)
+ return addrlen;
+
+ return __sys_bind_socket(ks->sock, &sa, addrlen);
+}
+
/**
* bpf_ksock_connect() - Connect a BPF kernel socket to a remote address.
* @ks: The BPF kernel socket context.
@@ -285,6 +312,7 @@ __bpf_kfunc_end_defs();
BTF_KFUNCS_START(ksock_init_kfunc_btf_ids)
BTF_ID_FLAGS(func, bpf_ksock_create, KF_ACQUIRE | KF_RET_NULL | KF_SLEEPABLE)
BTF_ID_FLAGS(func, bpf_ksock_connect, KF_SLEEPABLE)
+BTF_ID_FLAGS(func, bpf_ksock_bind, KF_SLEEPABLE)
BTF_KFUNCS_END(ksock_init_kfunc_btf_ids)
static const struct btf_kfunc_id_set ksock_init_kfunc_set = {
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH bpf-next 2/2] selftests/bpf: Test bpf_ksock_bind() kfunc
2026-10-22 18:16 [PATCH bpf-next 1/2] bpf: Add bpf_ksock_bind() kfunc Mahe Tardy
@ 2026-10-22 18:16 ` Mahe Tardy
2026-10-22 18:45 ` [PATCH bpf-next 1/2] bpf: Add " bot+bpf-ci
1 sibling, 0 replies; 6+ messages in thread
From: Mahe Tardy @ 2026-10-22 18:16 UTC (permalink / raw)
To: bpf
Cc: andrii, ast, daniel, davem, willemb, eddyz87, edumazet,
john.fastabend, kuba, horms, liamwisehart, martin.lau, pabeni,
song, netdev, sdf.kernel, yonghong.song, jolsa, kuniyu, memxor,
emil, almagui, Mahe Tardy
Reuse the existing basic ksock test to also bind to a specific source
and verify that the source address was respected when receiving.
Signed-off-by: Mahe Tardy <mahe.tardy@gmail.com>
---
.../testing/selftests/bpf/prog_tests/ksock.c | 22 ++++++++++++++-----
.../selftests/bpf/progs/ksock_common.h | 2 ++
tools/testing/selftests/bpf/progs/ksock_lsm.c | 18 +++++++++++----
3 files changed, 33 insertions(+), 9 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/ksock.c b/tools/testing/selftests/bpf/prog_tests/ksock.c
index dd6b167623d9..9827aeccf3f5 100644
--- a/tools/testing/selftests/bpf/prog_tests/ksock.c
+++ b/tools/testing/selftests/bpf/prog_tests/ksock.c
@@ -10,6 +10,7 @@
#define NS_TEST "ksock_lsm_ns"
#define RECV_PORT 7777
+#define LOCAL_KSOCK_PORT 6666
#define RECV_TIMEOUT_SEC 5
struct ksock_test_env {
@@ -63,6 +64,8 @@ void test_ksock_lsm(void)
.sin_family = AF_INET,
.sin_addr.s_addr = htonl(INADDR_LOOPBACK),
};
+ struct sockaddr_in src_addr = {};
+ socklen_t src_addrlen = sizeof(src_addr);
struct ksock_lsm *skel;
char recv_data[sizeof(skel->data->send_data)] = {};
ssize_t n;
@@ -76,9 +79,10 @@ void test_ksock_lsm(void)
if (!ksock_test_env_setup(&env))
goto fail;
- /* Step 1: Run the setup SYSCALL prog to create the ksock */
+ /* Step 1: Create, bind, and connect the ksock from the SYSCALL prog. */
skel->bss->ipv4_remote = htonl(INADDR_LOOPBACK);
skel->bss->remote_port = RECV_PORT;
+ skel->bss->local_port = LOCAL_KSOCK_PORT;
err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.ksock_setup),
&opts);
if (!ASSERT_OK(err, "ksock_setup run"))
@@ -108,10 +112,18 @@ void test_ksock_lsm(void)
"LSM send bytes"))
goto fail;
- n = recvfrom(env.rfd, recv_data, sizeof(recv_data), 0, NULL, NULL);
- if (ASSERT_EQ(n, sizeof(recv_data), "recvfrom len"))
- ASSERT_MEMEQ(recv_data, skel->data->send_data, sizeof(recv_data),
- "payload match");
+ n = recvfrom(env.rfd, recv_data, sizeof(recv_data), MSG_TRUNC,
+ (struct sockaddr *)&src_addr, &src_addrlen);
+ if (!ASSERT_EQ(n, sizeof(recv_data), "recvfrom len"))
+ goto fail;
+ if (!ASSERT_EQ(ntohs(src_addr.sin_port), LOCAL_KSOCK_PORT,
+ "source address port"))
+ goto fail;
+ if (!ASSERT_EQ(ntohl(src_addr.sin_addr.s_addr), INADDR_LOOPBACK + 1,
+ "source address ip"))
+ goto fail;
+ ASSERT_MEMEQ(recv_data, skel->data->send_data, sizeof(recv_data),
+ "payload match");
fail:
if (tfd >= 0)
diff --git a/tools/testing/selftests/bpf/progs/ksock_common.h b/tools/testing/selftests/bpf/progs/ksock_common.h
index 2a32cff2fbe9..87321f4ba4f5 100644
--- a/tools/testing/selftests/bpf/progs/ksock_common.h
+++ b/tools/testing/selftests/bpf/progs/ksock_common.h
@@ -11,6 +11,8 @@
struct bpf_ksock *bpf_ksock_create(const struct bpf_ksock_create_opts *opts,
u32 opts__sz, int *err__uninit) __ksym;
+int bpf_ksock_bind(struct bpf_ksock *ks, const union bpf_ksock_addr *addr,
+ u32 addr__sz) __ksym;
int bpf_ksock_connect(struct bpf_ksock *ks, const union bpf_ksock_addr *addr,
u32 addr__sz) __ksym;
struct bpf_ksock *bpf_ksock_acquire(struct bpf_ksock *ks) __ksym;
diff --git a/tools/testing/selftests/bpf/progs/ksock_lsm.c b/tools/testing/selftests/bpf/progs/ksock_lsm.c
index 9808451098ef..28da777eea6c 100644
--- a/tools/testing/selftests/bpf/progs/ksock_lsm.c
+++ b/tools/testing/selftests/bpf/progs/ksock_lsm.c
@@ -10,6 +10,7 @@
char send_data[32] = "hello from bpf ksock";
+__u16 local_port;
__be32 ipv4_remote;
__u16 remote_port;
int target_pid;
@@ -32,19 +33,28 @@ int ksock_setup(void *ctx)
return err;
addr.sin.sin_family = AF_INET;
+ addr.sin.sin_port = bpf_htons(local_port);
+ addr.sin.sin_addr.s_addr = bpf_htonl(0x7f000002); /* 127.0.0.2 */
+
+ err = bpf_ksock_bind(ks, &addr, sizeof(addr));
+ if (err)
+ goto err_release;
+
addr.sin.sin_port = bpf_htons(remote_port);
addr.sin.sin_addr.s_addr = ipv4_remote;
err = bpf_ksock_connect(ks, &addr, sizeof(addr));
- if (err) {
- bpf_ksock_release(ks);
- return err;
- }
+ if (err)
+ goto err_release;
err = ksock_ctx_insert(ks);
if (err && err != -EEXIST)
return err;
return 0;
+
+err_release:
+ bpf_ksock_release(ks);
+ return err;
}
SEC("lsm.s/socket_bind")
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: Add bpf_ksock_bind() kfunc
2026-10-22 18:16 [PATCH bpf-next 1/2] bpf: Add bpf_ksock_bind() kfunc Mahe Tardy
2026-10-22 18:16 ` [PATCH bpf-next 2/2] selftests/bpf: Test " Mahe Tardy
@ 2026-10-22 18:45 ` bot+bpf-ci
2026-10-23 8:42 ` Mahe Tardy
1 sibling, 1 reply; 6+ messages in thread
From: bot+bpf-ci @ 2026-10-22 18:45 UTC (permalink / raw)
To: mahe.tardy, bpf
Cc: andrii, ast, daniel, davem, willemb, eddyz87, edumazet,
john.fastabend, kuba, horms, liamwisehart, martin.lau, pabeni,
song, netdev, sdf.kernel, yonghong.song, jolsa, kuniyu, memxor,
emil, almagui, mahe.tardy, ast, andrii, daniel, martin.lau,
eddyz87, yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 3606 bytes --]
> bpf: Add bpf_ksock_bind() kfunc
TL;DR: bpf_ksock_bind() called from a bpf_wq callback runs with kworker's full
capabilities, so a CAP_BPF-only SYSCALL program may bypass the privileged-port
(CAP_NET_BIND_SERVICE) check; the review asks whether to block it.
> diff --git a/net/core/bpf_ksock.c b/net/core/bpf_ksock.c
> index 37168f43c16c..c7b487d90cd0 100644
> --- a/net/core/bpf_ksock.c
> +++ b/net/core/bpf_ksock.c
[ ... ]
> @@ -178,6 +178,33 @@ bpf_ksock_create(const struct bpf_ksock_create_opts *opts, u32 opts__sz,
> return NULL;
> }
>
> +/**
> + * bpf_ksock_bind() - Bind a BPF kernel socket to a local address.
[ ... ]
> +__bpf_kfunc int bpf_ksock_bind(struct bpf_ksock *ks,
> + const union bpf_ksock_addr *addr, u32 addr__sz)
> +{
> + struct sockaddr_storage sa;
> + int addrlen;
> +
> + addrlen = bpf_ksock_addr_to_sockaddr(addr, addr__sz, &sa);
> + if (addrlen < 0)
> + return addrlen;
> +
> + return __sys_bind_socket(ks->sock, &sa, addrlen);
> +}
> +
Can the CAP_NET_BIND_SERVICE check for privileged ports be bypassed when
this runs from a bpf_wq callback?
bpf_ksock_bind() is added to ksock_init_kfunc_btf_ids, the same set as
bpf_ksock_connect(). Commit 60bbe76a3f9e ("bpf: Allow ksock connect/send
calls from wq") made the kfuncs in this set callable from bpf_wq callbacks
of SYSCALL programs, and tools/testing/selftests/bpf/progs/ksock_wq.c
already calls bpf_ksock_connect() from such a callback.
bpf_wq_work() runs that callback in a kworker, where current->cred is
init_cred with cap_effective set to CAP_FULL_SET (see init/init_task.c).
The bind path is:
bpf_ksock_bind()
__sys_bind_socket()
security_socket_bind()
inet_bind() -> inet_bind_sk() -> __inet_bind()
and __inet_bind() then does:
snum = ntohs(addr->sin_port);
err = -EACCES;
if (!(flags & BIND_NO_CAP_NET_BIND_SERVICE) &&
snum && inet_port_requires_bind_service(net, snum) &&
!ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
goto out;
__inet6_bind() has the same check. With init_cred, cap_capable_helper()
walks up to init_user_ns and finds the capability raised, so the check
passes for any netns.
For example, a task holding only CAP_BPF can load a SYSCALL program, since
is_net_admin_prog_type() does not ask for CAP_NET_ADMIN for that type.
Such a program could bind its ksock to UDP port 53, 123 or 514 from a wq
callback, while the same call made synchronously from the SYSCALL program
returns -EACCES. A bpf_task_work callback looks like it has the same
problem in a different form, since the check would be evaluated against
whichever task the work was scheduled on.
Commit 60bbe76a3f9e only argued about LSM checks ("bypassing LSM checks for
BPF-created sockets could be acceptable"), and connect and send on a UDP
ksock have no capability gate. bind appears to be the first ksock
operation that does, and the commit message does not address the wq
context.
Should bpf_ksock_bind() refuse to run from kthread context, the way
bpf_ksock_create() does with its PF_KTHREAD check? Alternatively, should
it be kept out of the set that is reachable from wq callbacks, or should
the commit message state that bypassing the privileged-port check is
intended?
No fix for this was found in the provided range; 76406b1f799f
("selftests/bpf: Test bpf_ksock_bind() kfunc") only adds tests.
---
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/39831790314
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: Add bpf_ksock_bind() kfunc
2026-10-22 18:45 ` [PATCH bpf-next 1/2] bpf: Add " bot+bpf-ci
@ 2026-10-23 8:42 ` Mahe Tardy
2026-10-23 16:05 ` Alan Maguire
0 siblings, 1 reply; 6+ messages in thread
From: Mahe Tardy @ 2026-10-23 8:42 UTC (permalink / raw)
To: bot+bpf-ci
Cc: bpf, andrii, ast, daniel, davem, willemb, eddyz87, edumazet,
john.fastabend, kuba, horms, liamwisehart, martin.lau, pabeni,
song, netdev, sdf.kernel, yonghong.song, jolsa, kuniyu, memxor,
emil, almagui, martin.lau, mason, ihor.solodrai
On Thu, Oct 22, 2026 at 06:45:34PM +0000, bot+bpf-ci@kernel.org wrote:
> > bpf: Add bpf_ksock_bind() kfunc
>
> TL;DR: bpf_ksock_bind() called from a bpf_wq callback runs with kworker's full
> capabilities, so a CAP_BPF-only SYSCALL program may bypass the privileged-port
> (CAP_NET_BIND_SERVICE) check; the review asks whether to block it.
Honestly don't know if it makes sense to prevent it given you are
creating this kernel socket from a BPF context, if anyone with more
experience on this can help?
If the answer is yes, I imagine preventing bind() to run from a
workqueue is the easy answer so that all creds are respected as usual
and it's not a huge limitation (we mostly care about being able to
send()/sendto() from a wq).
>
> > diff --git a/net/core/bpf_ksock.c b/net/core/bpf_ksock.c
> > index 37168f43c16c..c7b487d90cd0 100644
> > --- a/net/core/bpf_ksock.c
> > +++ b/net/core/bpf_ksock.c
>
> [ ... ]
>
> > @@ -178,6 +178,33 @@ bpf_ksock_create(const struct bpf_ksock_create_opts *opts, u32 opts__sz,
> > return NULL;
> > }
> >
> > +/**
> > + * bpf_ksock_bind() - Bind a BPF kernel socket to a local address.
>
> [ ... ]
>
> > +__bpf_kfunc int bpf_ksock_bind(struct bpf_ksock *ks,
> > + const union bpf_ksock_addr *addr, u32 addr__sz)
> > +{
> > + struct sockaddr_storage sa;
> > + int addrlen;
> > +
> > + addrlen = bpf_ksock_addr_to_sockaddr(addr, addr__sz, &sa);
> > + if (addrlen < 0)
> > + return addrlen;
> > +
> > + return __sys_bind_socket(ks->sock, &sa, addrlen);
> > +}
> > +
>
> Can the CAP_NET_BIND_SERVICE check for privileged ports be bypassed when
> this runs from a bpf_wq callback?
>
> bpf_ksock_bind() is added to ksock_init_kfunc_btf_ids, the same set as
> bpf_ksock_connect(). Commit 60bbe76a3f9e ("bpf: Allow ksock connect/send
> calls from wq") made the kfuncs in this set callable from bpf_wq callbacks
> of SYSCALL programs, and tools/testing/selftests/bpf/progs/ksock_wq.c
> already calls bpf_ksock_connect() from such a callback.
>
> bpf_wq_work() runs that callback in a kworker, where current->cred is
> init_cred with cap_effective set to CAP_FULL_SET (see init/init_task.c).
>
> The bind path is:
>
> bpf_ksock_bind()
> __sys_bind_socket()
> security_socket_bind()
> inet_bind() -> inet_bind_sk() -> __inet_bind()
>
> and __inet_bind() then does:
>
> snum = ntohs(addr->sin_port);
> err = -EACCES;
> if (!(flags & BIND_NO_CAP_NET_BIND_SERVICE) &&
> snum && inet_port_requires_bind_service(net, snum) &&
> !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
> goto out;
>
> __inet6_bind() has the same check. With init_cred, cap_capable_helper()
> walks up to init_user_ns and finds the capability raised, so the check
> passes for any netns.
>
> For example, a task holding only CAP_BPF can load a SYSCALL program, since
> is_net_admin_prog_type() does not ask for CAP_NET_ADMIN for that type.
> Such a program could bind its ksock to UDP port 53, 123 or 514 from a wq
> callback, while the same call made synchronously from the SYSCALL program
> returns -EACCES. A bpf_task_work callback looks like it has the same
> problem in a different form, since the check would be evaluated against
> whichever task the work was scheduled on.
>
> Commit 60bbe76a3f9e only argued about LSM checks ("bypassing LSM checks for
> BPF-created sockets could be acceptable"), and connect and send on a UDP
> ksock have no capability gate. bind appears to be the first ksock
> operation that does, and the commit message does not address the wq
> context.
>
> Should bpf_ksock_bind() refuse to run from kthread context, the way
> bpf_ksock_create() does with its PF_KTHREAD check? Alternatively, should
> it be kept out of the set that is reachable from wq callbacks, or should
> the commit message state that bypassing the privileged-port check is
> intended?
>
> No fix for this was found in the provided range; 76406b1f799f
> ("selftests/bpf: Test bpf_ksock_bind() kfunc") only adds tests.
>
>
> ---
> 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/39831790314
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: Add bpf_ksock_bind() kfunc
2026-10-23 8:42 ` Mahe Tardy
@ 2026-10-23 16:05 ` Alan Maguire
2026-10-23 17:10 ` Mahe Tardy
0 siblings, 1 reply; 6+ messages in thread
From: Alan Maguire @ 2026-10-23 16:05 UTC (permalink / raw)
To: Mahe Tardy, bot+bpf-ci
Cc: bpf, andrii, ast, daniel, davem, willemb, eddyz87, edumazet,
john.fastabend, kuba, horms, liamwisehart, martin.lau, pabeni,
song, netdev, sdf.kernel, yonghong.song, jolsa, kuniyu, memxor,
emil, martin.lau, mason, ihor.solodrai
On 10/23/26 9:42 AM, Mahe Tardy wrote:
> On Thu, Oct 22, 2026 at 06:45:34PM +0000, bot+bpf-ci@kernel.org wrote:
>>> bpf: Add bpf_ksock_bind() kfunc
>>
>> TL;DR: bpf_ksock_bind() called from a bpf_wq callback runs with kworker's full
>> capabilities, so a CAP_BPF-only SYSCALL program may bypass the privileged-port
>> (CAP_NET_BIND_SERVICE) check; the review asks whether to block it.
>
> Honestly don't know if it makes sense to prevent it given you are
> creating this kernel socket from a BPF context, if anyone with more
> experience on this can help?
>
> If the answer is yes, I imagine preventing bind() to run from a
> workqueue is the easy answer so that all creds are respected as usual
> and it's not a huge limitation (we mostly care about being able to
> send()/sendto() from a wq).
>
I suppose one way out of this would be to forbid bind()ing to the privileged
port range; that would sidestep the issue I think. Hard to know how restrictive
that would be in terms of real use cases, what do you think?
>>
>>> diff --git a/net/core/bpf_ksock.c b/net/core/bpf_ksock.c
>>> index 37168f43c16c..c7b487d90cd0 100644
>>> --- a/net/core/bpf_ksock.c
>>> +++ b/net/core/bpf_ksock.c
>>
>> [ ... ]
>>
>>> @@ -178,6 +178,33 @@ bpf_ksock_create(const struct bpf_ksock_create_opts *opts, u32 opts__sz,
>>> return NULL;
>>> }
>>>
>>> +/**
>>> + * bpf_ksock_bind() - Bind a BPF kernel socket to a local address.
>>
>> [ ... ]
>>
>>> +__bpf_kfunc int bpf_ksock_bind(struct bpf_ksock *ks,
>>> + const union bpf_ksock_addr *addr, u32 addr__sz)
>>> +{
>>> + struct sockaddr_storage sa;
>>> + int addrlen;
>>> +
>>> + addrlen = bpf_ksock_addr_to_sockaddr(addr, addr__sz, &sa);
>>> + if (addrlen < 0)
>>> + return addrlen;
>>> +
>>> + return __sys_bind_socket(ks->sock, &sa, addrlen);
>>> +}
>>> +
>>
>> Can the CAP_NET_BIND_SERVICE check for privileged ports be bypassed when
>> this runs from a bpf_wq callback?
>>
>> bpf_ksock_bind() is added to ksock_init_kfunc_btf_ids, the same set as
>> bpf_ksock_connect(). Commit 60bbe76a3f9e ("bpf: Allow ksock connect/send
>> calls from wq") made the kfuncs in this set callable from bpf_wq callbacks
>> of SYSCALL programs, and tools/testing/selftests/bpf/progs/ksock_wq.c
>> already calls bpf_ksock_connect() from such a callback.
>>
>> bpf_wq_work() runs that callback in a kworker, where current->cred is
>> init_cred with cap_effective set to CAP_FULL_SET (see init/init_task.c).
>>
>> The bind path is:
>>
>> bpf_ksock_bind()
>> __sys_bind_socket()
>> security_socket_bind()
>> inet_bind() -> inet_bind_sk() -> __inet_bind()
>>
>> and __inet_bind() then does:
>>
>> snum = ntohs(addr->sin_port);
>> err = -EACCES;
>> if (!(flags & BIND_NO_CAP_NET_BIND_SERVICE) &&
>> snum && inet_port_requires_bind_service(net, snum) &&
>> !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
>> goto out;
>>
>> __inet6_bind() has the same check. With init_cred, cap_capable_helper()
>> walks up to init_user_ns and finds the capability raised, so the check
>> passes for any netns.
>>
>> For example, a task holding only CAP_BPF can load a SYSCALL program, since
>> is_net_admin_prog_type() does not ask for CAP_NET_ADMIN for that type.
>> Such a program could bind its ksock to UDP port 53, 123 or 514 from a wq
>> callback, while the same call made synchronously from the SYSCALL program
>> returns -EACCES. A bpf_task_work callback looks like it has the same
>> problem in a different form, since the check would be evaluated against
>> whichever task the work was scheduled on.
>>
>> Commit 60bbe76a3f9e only argued about LSM checks ("bypassing LSM checks for
>> BPF-created sockets could be acceptable"), and connect and send on a UDP
>> ksock have no capability gate. bind appears to be the first ksock
>> operation that does, and the commit message does not address the wq
>> context.
>>
>> Should bpf_ksock_bind() refuse to run from kthread context, the way
>> bpf_ksock_create() does with its PF_KTHREAD check? Alternatively, should
>> it be kept out of the set that is reachable from wq callbacks, or should
>> the commit message state that bypassing the privileged-port check is
>> intended?
>>
>> No fix for this was found in the provided range; 76406b1f799f
>> ("selftests/bpf: Test bpf_ksock_bind() kfunc") only adds tests.
>>
>>
>> ---
>> 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/39831790314
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: Add bpf_ksock_bind() kfunc
2026-10-23 16:05 ` Alan Maguire
@ 2026-10-23 17:10 ` Mahe Tardy
0 siblings, 0 replies; 6+ messages in thread
From: Mahe Tardy @ 2026-10-23 17:10 UTC (permalink / raw)
To: Alan Maguire
Cc: bot+bpf-ci, bpf, andrii, ast, daniel, davem, willemb, eddyz87,
edumazet, john.fastabend, kuba, horms, liamwisehart, martin.lau,
pabeni, song, netdev, sdf.kernel, yonghong.song, jolsa, kuniyu,
memxor, emil, martin.lau, mason, ihor.solodrai
On Fri, Oct 23, 2026 at 05:05:10PM +0100, Alan Maguire wrote:
> On 10/23/26 9:42 AM, Mahe Tardy wrote:
> > On Thu, Oct 22, 2026 at 06:45:34PM +0000, bot+bpf-ci@kernel.org wrote:
> >>> bpf: Add bpf_ksock_bind() kfunc
> >>
> >> TL;DR: bpf_ksock_bind() called from a bpf_wq callback runs with kworker's full
> >> capabilities, so a CAP_BPF-only SYSCALL program may bypass the privileged-port
> >> (CAP_NET_BIND_SERVICE) check; the review asks whether to block it.
> >
> > Honestly don't know if it makes sense to prevent it given you are
> > creating this kernel socket from a BPF context, if anyone with more
> > experience on this can help?
> >
> > If the answer is yes, I imagine preventing bind() to run from a
> > workqueue is the easy answer so that all creds are respected as usual
> > and it's not a huge limitation (we mostly care about being able to
> > send()/sendto() from a wq).
> >
>
> I suppose one way out of this would be to forbid bind()ing to the privileged
> port range; that would sidestep the issue I think. Hard to know how restrictive
> that would be in terms of real use cases, what do you think?
Yeah this is another way around it but I wonder if keeping the ability
to bind from a wq is more important than beeing able to bind on a
privileged port.
Otherwise we can probably guard bind with:
if (current->flags & PF_KTHREAD)
no
If the assumption is correct i.e. you can load and run any SYSCALL bpf
program with just CAP_BPF, then indeed having this would allow you to
circumvent a CAP_NET_BIND_SERVICE check which is kinda unexpected even
if we could maybe discuss that those are BPF sockets, which are pretty
limited for now, etc. The reason why I'm thinking like this:
- I already tried to import existing network resources limitation when
writing the initial patch set, like limit the number of BPF sockets,
and I was told it was unecessary.
- I did this whole annoying dance with LSM hooks so that ksock goes
through them and I was kinda told that it was maybe also unecessary.
But the more I think about this the more I think the concern is valid.
> >>
> >>> diff --git a/net/core/bpf_ksock.c b/net/core/bpf_ksock.c
> >>> index 37168f43c16c..c7b487d90cd0 100644
> >>> --- a/net/core/bpf_ksock.c
> >>> +++ b/net/core/bpf_ksock.c
> >>
[...]
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-23 17:10 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-22 18:16 [PATCH bpf-next 1/2] bpf: Add bpf_ksock_bind() kfunc Mahe Tardy
2026-10-22 18:16 ` [PATCH bpf-next 2/2] selftests/bpf: Test " Mahe Tardy
2026-10-22 18:45 ` [PATCH bpf-next 1/2] bpf: Add " bot+bpf-ci
2026-10-23 8:42 ` Mahe Tardy
2026-10-23 16:05 ` Alan Maguire
2026-10-23 17:10 ` Mahe Tardy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox