]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: Disable unsafe helpers in TX timestamping callbacks
authorJason Xing <kerneljasonxing@gmail.com>
Thu, 20 Feb 2025 07:29:32 +0000 (15:29 +0800)
committerMartin KaFai Lau <martin.lau@kernel.org>
Thu, 20 Feb 2025 22:29:10 +0000 (14:29 -0800)
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
net/core/filter.c

index 7a20ddae76676e766a3abecded801fc2ba745fd5..90a8fbc2e09677bb45e208179cd751e010ebc166 100644 (file)
@@ -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.