aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/net
diff options
context:
space:
mode:
authorJason Xing <kerneljasonxing@gmail.com>2025-02-20 15:29:32 +0800
committerMartin KaFai Lau <martin.lau@kernel.org>2025-02-20 14:29:10 -0800
commit2958624b25305142e24203165ff65409ba9dd9d7 (patch)
tree5d1bb28eae490c7f297b47f3c7f7056a47b2871f /net
parentbpf: Prevent unsafe access to the sock fields in the BPF timestamping callback (diff)
downloadwireguard-linux-2958624b25305142e24203165ff65409ba9dd9d7.tar.xz
wireguard-linux-2958624b25305142e24203165ff65409ba9dd9d7.zip
bpf: Disable unsafe helpers in TX timestamping callbacks
New TX timestamping sock_ops callbacks will be added in the subsequent patch. Some of the existing BPF helpers will not be safe to be used in the TX timestamping callbacks. The bpf_sock_ops_setsockopt, bpf_sock_ops_getsockopt, and bpf_sock_ops_cb_flags_set require owning the sock lock. TX timestamping callbacks will not own the lock. The bpf_sock_ops_load_hdr_opt needs the skb->data pointing to the TCP header. This will not be true in the TX timestamping callbacks. At the beginning of these helpers, this patch checks the bpf_sock->op to ensure these helpers are used by the existing sock_ops callbacks only. Signed-off-by: Jason Xing <kerneljasonxing@gmail.com> Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> Link: https://patch.msgid.link/20250220072940.99994-5-kerneljasonxing@gmail.com
Diffstat (limited to 'net')
-rw-r--r--net/core/filter.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index 7a20ddae7667..90a8fbc2e096 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -5524,6 +5524,11 @@ static int __bpf_setsockopt(struct sock *sk, int level, int optname,
return -EINVAL;
}
+static bool is_locked_tcp_sock_ops(struct bpf_sock_ops_kern *bpf_sock)
+{
+ return bpf_sock->op <= BPF_SOCK_OPS_WRITE_HDR_OPT_CB;
+}
+
static int _bpf_setsockopt(struct sock *sk, int level, int optname,
char *optval, int optlen)
{
@@ -5674,6 +5679,9 @@ static const struct bpf_func_proto bpf_sock_addr_getsockopt_proto = {
BPF_CALL_5(bpf_sock_ops_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
int, level, int, optname, char *, optval, int, optlen)
{
+ if (!is_locked_tcp_sock_ops(bpf_sock))
+ return -EOPNOTSUPP;
+
return _bpf_setsockopt(bpf_sock->sk, level, optname, optval, optlen);
}
@@ -5759,6 +5767,9 @@ static int bpf_sock_ops_get_syn(struct bpf_sock_ops_kern *bpf_sock,
BPF_CALL_5(bpf_sock_ops_getsockopt, struct bpf_sock_ops_kern *, bpf_sock,
int, level, int, optname, char *, optval, int, optlen)
{
+ if (!is_locked_tcp_sock_ops(bpf_sock))
+ return -EOPNOTSUPP;
+
if (IS_ENABLED(CONFIG_INET) && level == SOL_TCP &&
optname >= TCP_BPF_SYN && optname <= TCP_BPF_SYN_MAC) {
int ret, copy_len = 0;
@@ -5801,6 +5812,9 @@ BPF_CALL_2(bpf_sock_ops_cb_flags_set, struct bpf_sock_ops_kern *, bpf_sock,
struct sock *sk = bpf_sock->sk;
int val = argval & BPF_SOCK_OPS_ALL_CB_FLAGS;
+ if (!is_locked_tcp_sock_ops(bpf_sock))
+ return -EOPNOTSUPP;
+
if (!IS_ENABLED(CONFIG_INET) || !sk_fullsock(sk))
return -EINVAL;
@@ -7610,6 +7624,9 @@ BPF_CALL_4(bpf_sock_ops_load_hdr_opt, struct bpf_sock_ops_kern *, bpf_sock,
u8 search_kind, search_len, copy_len, magic_len;
int ret;
+ if (!is_locked_tcp_sock_ops(bpf_sock))
+ return -EOPNOTSUPP;
+
/* 2 byte is the minimal option len except TCPOPT_NOP and
* TCPOPT_EOL which are useless for the bpf prog to learn
* and this helper disallow loading them also.