[PATCH v5 bpf-next 01/10] bpf: tcp: Convert deny-list for bpf_{get,set}sockopt() to allow-list.
flat view
WARM1d
IN BPF-NEXT: 5 (4M)
From: Kuniyuki Iwashima <kuniyu@google.com>
Date: 2026-10-08 03:16:08
Also in:
bpf
Subsystem:
networking [general], the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
3 review trailers; queued in bpf-next as 114ce944d015 on 2026-10-10.
Currently, four bpf_tcp_ops callbacks are not allowed to call bpf_setsockopt() and bpf_getsockopt(). However, the deny-list is fragile, and when a new callback is added, we might re-open a can of worms. [0][1] Let's convert it to allow-list. Note that it can be written as offsetof(,X) <= moff <= offsetof(,Y) but clang can optimise to similar code anyway. Link: https://lore.kernel.org/r/20220929070407.965581-5-martin.lau@linux.dev/ (local) #[0] Link: https://lore.kernel.org/bpf/20260421155804.135786-1-kafai.wan@linux.dev/ (local) #[1] Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com> Acked-by: Stanislav Fomichev <sdf@fomichev.me> Reviewed-by: Amery Hung <redacted> --- net/ipv4/bpf_tcp_ops.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-)
diff --git a/net/ipv4/bpf_tcp_ops.c b/net/ipv4/bpf_tcp_ops.c
index 681fed642999..1ada3b781bf1 100644
--- a/net/ipv4/bpf_tcp_ops.c
+++ b/net/ipv4/bpf_tcp_ops.c@@ -210,6 +210,24 @@ const struct bpf_func_proto bpf_tcp_ops_get_retval_proto = { .ret_type = RET_INTEGER, }; +static bool is_sockopt_supported(u32 moff) +{ + switch (moff) { + case offsetof(struct bpf_tcp_ops, active_established): + case offsetof(struct bpf_tcp_ops, passive_established): + case offsetof(struct bpf_tcp_ops, rto): + case offsetof(struct bpf_tcp_ops, rtt): + case offsetof(struct bpf_tcp_ops, set_state): + case offsetof(struct bpf_tcp_ops, retrans): + case offsetof(struct bpf_tcp_ops, connect): + case offsetof(struct bpf_tcp_ops, listen): + case offsetof(struct bpf_tcp_ops, parse_hdr): + return true; + } + + return false; +} + static const struct bpf_func_proto * get_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) {
@@ -221,22 +239,13 @@ get_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) case BPF_FUNC_sk_storage_delete: return &bpf_sk_storage_delete_proto; case BPF_FUNC_setsockopt: - /* The sk may be an unlocked listener (synack path) or NULL - * fullsock; disable for members that can run unlocked. - */ - if (moff == offsetof(struct bpf_tcp_ops, rwnd_init) || - moff == offsetof(struct bpf_tcp_ops, timeout_init) || - moff == offsetof(struct bpf_tcp_ops, hdr_opt_len) || - moff == offsetof(struct bpf_tcp_ops, write_hdr_opt)) - return NULL; - return &bpf_sk_setsockopt_proto; + if (is_sockopt_supported(moff)) + return &bpf_sk_setsockopt_proto; + return NULL; case BPF_FUNC_getsockopt: - if (moff == offsetof(struct bpf_tcp_ops, rwnd_init) || - moff == offsetof(struct bpf_tcp_ops, timeout_init) || - moff == offsetof(struct bpf_tcp_ops, hdr_opt_len) || - moff == offsetof(struct bpf_tcp_ops, write_hdr_opt)) - return NULL; - return &bpf_sk_getsockopt_proto; + if (is_sockopt_supported(moff)) + return &bpf_sk_getsockopt_proto; + return NULL; case BPF_FUNC_get_retval: if (moff == offsetof(struct bpf_tcp_ops, timeout_init) || moff == offsetof(struct bpf_tcp_ops, rwnd_init))
--
2.56.0.360.g66cac248cb-goog