summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorMartin KaFai Lau <martin.lau@kernel.org>2024-08-08 15:31:26 -0700
committerMartin KaFai Lau <martin.lau@kernel.org>2024-08-08 17:03:44 -0700
commit39e8111ce5ce76039a80eaf6dd71ae8bb6866f95 (patch)
tree02383dbd43496165fd24a77847bd1198bfc5dd82 /net
parent91d516d4de48532d967a77967834e00c8c53dfe6 (diff)
parentd53050934e66dbee64caed1309cef963a416c52f (diff)
Merge branch 'add TCP_BPF_SOCK_OPS_CB_FLAGS to bpf_*sockopt()'
Alan Maguire says: ==================== As previously discussed here [1], long-lived sockets can miss a chance to set additional callbacks if a sock ops program was not attached early in their lifetime. Adding support to bpf_setsockopt() to set callback flags (and bpf_getsockopt() to retrieve them) provides other opportunities to enable callbacks, either directly via a cgroup/setsockopt intercepted setsockopt() or via a socket iterator. Patch 1 adds bpf_[get|set]sockopt() support; patch 2 adds testing for it via a sockops programs, along with verification via a cgroup/getsockopt program. Changes since v1 [2]: - Removed unneeded READ_ONCE() (Martin, patch 1) - Reworked sockopt test to leave existing tests undisturbed while adding test_nonstandard_opt() test to cover the TCP_BPF_SOCK_OPS_CB_FLAGS case; test verifies that value set via bpf_setsockopt() is what we expect via a call to getsockopt() which is caught by a cgroup/getsockopt program to provide the flags value (Martin, patch 2) - Removed unneeded iterator test (Martin) [1] https://lore.kernel.org/bpf/f42f157b-6e52-dd4d-3d97-9b86c84c0b00@oracle.com/ [2] https://lore.kernel.org/bpf/20240802152929.2695863-1-alan.maguire@oracle.com/ ==================== Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Diffstat (limited to 'net')
-rw-r--r--net/core/filter.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index f3c72cf86099..d96a50f3f016 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -5278,6 +5278,11 @@ static int bpf_sol_tcp_setsockopt(struct sock *sk, int optname,
return -EINVAL;
inet_csk(sk)->icsk_rto_min = timeout;
break;
+ case TCP_BPF_SOCK_OPS_CB_FLAGS:
+ if (val & ~(BPF_SOCK_OPS_ALL_CB_FLAGS))
+ return -EINVAL;
+ tp->bpf_sock_ops_cb_flags = val;
+ break;
default:
return -EINVAL;
}
@@ -5366,6 +5371,17 @@ static int sol_tcp_sockopt(struct sock *sk, int optname,
if (*optlen < 1)
return -EINVAL;
break;
+ case TCP_BPF_SOCK_OPS_CB_FLAGS:
+ if (*optlen != sizeof(int))
+ return -EINVAL;
+ if (getopt) {
+ struct tcp_sock *tp = tcp_sk(sk);
+ int cb_flags = tp->bpf_sock_ops_cb_flags;
+
+ memcpy(optval, &cb_flags, *optlen);
+ return 0;
+ }
+ return bpf_sol_tcp_setsockopt(sk, optname, optval, *optlen);
default:
if (getopt)
return -EINVAL;