diff options
| author | Kuniyuki Iwashima <kuniyu@google.com> | 2026-10-08 03:15:21 +0000 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2026-10-10 16:38:12 +0000 |
| commit | 114ce944d01500ffcbf9159a72806d7f633ad9ae (patch) | |
| tree | 0d9bf5874db22dcc3f790bd6e0208c38da774302 /net | |
| parent | 6335e6719fd323c345427b7cf2d5d17c28fdbc41 (diff) | |
bpf: tcp: Convert deny-list for bpf_{get,set}sockopt() to allow-list.
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.
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Reviewed-by: Amery Hung <ameryhung@gmail.com>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Link: https://lore.kernel.org/r/20220929070407.965581-5-martin.lau@linux.dev/ #[0]
Link: https://lore.kernel.org/bpf/20260421155804.135786-1-kafai.wan@linux.dev/ #[1]
Link: https://patch.msgid.link/20261008031604.256498-2-kuniyu@google.com
Diffstat (limited to 'net')
| -rw-r--r-- | net/ipv4/bpf_tcp_ops.c | 39 |
1 files 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)) |
