Merge tag 'dmaengine-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul...
[linux-2.6-block.git] / net / core / filter.c
index bb0136e7a8e422b010477333c811db79aaf56e3f..929358677183d5827b7cf2c54700cc34eb36544d 100644 (file)
@@ -80,6 +80,7 @@
 #include <net/tls.h>
 #include <net/xdp.h>
 #include <net/mptcp.h>
+#include <net/netfilter/nf_conntrack_bpf.h>
 
 static const struct bpf_func_proto *
 bpf_sk_base_func_proto(enum bpf_func_id func_id);
@@ -325,11 +326,11 @@ static u32 convert_skb_access(int skb_field, int dst_reg, int src_reg,
                                      offsetof(struct sk_buff, vlan_tci));
                break;
        case SKF_AD_VLAN_TAG_PRESENT:
-               *insn++ = BPF_LDX_MEM(BPF_B, dst_reg, src_reg, PKT_VLAN_PRESENT_OFFSET);
-               if (PKT_VLAN_PRESENT_BIT)
-                       *insn++ = BPF_ALU32_IMM(BPF_RSH, dst_reg, PKT_VLAN_PRESENT_BIT);
-               if (PKT_VLAN_PRESENT_BIT < 7)
-                       *insn++ = BPF_ALU32_IMM(BPF_AND, dst_reg, 1);
+               BUILD_BUG_ON(sizeof_field(struct sk_buff, vlan_all) != 4);
+               *insn++ = BPF_LDX_MEM(BPF_W, dst_reg, src_reg,
+                                     offsetof(struct sk_buff, vlan_all));
+               *insn++ = BPF_JMP_IMM(BPF_JEQ, dst_reg, 0, 1);
+               *insn++ = BPF_ALU32_IMM(BPF_MOV, dst_reg, 1);
                break;
        }
 
@@ -2124,6 +2125,11 @@ static int __bpf_redirect_no_mac(struct sk_buff *skb, struct net_device *dev,
 {
        unsigned int mlen = skb_network_offset(skb);
 
+       if (unlikely(skb->len <= mlen)) {
+               kfree_skb(skb);
+               return -ERANGE;
+       }
+
        if (mlen) {
                __skb_pull(skb, mlen);
 
@@ -2145,7 +2151,7 @@ static int __bpf_redirect_common(struct sk_buff *skb, struct net_device *dev,
                                 u32 flags)
 {
        /* Verify that a link layer header is carried */
-       if (unlikely(skb->mac_header >= skb->network_header)) {
+       if (unlikely(skb->mac_header >= skb->network_header || skb->len == 0)) {
                kfree_skb(skb);
                return -ERANGE;
        }
@@ -4104,7 +4110,10 @@ static const struct bpf_func_proto bpf_xdp_adjust_meta_proto = {
        .arg2_type      = ARG_ANYTHING,
 };
 
-/* XDP_REDIRECT works by a three-step process, implemented in the functions
+/**
+ * DOC: xdp redirect
+ *
+ * XDP_REDIRECT works by a three-step process, implemented in the functions
  * below:
  *
  * 1. The bpf_redirect() and bpf_redirect_map() helpers will lookup the target
@@ -4119,7 +4128,8 @@ static const struct bpf_func_proto bpf_xdp_adjust_meta_proto = {
  * 3. Before exiting its NAPI poll loop, the driver will call xdp_do_flush(),
  *    which will flush all the different bulk queues, thus completing the
  *    redirect.
- *
+ */
+/*
  * Pointers to the map entries will be kept around for this whole sequence of
  * steps, protected by RCU. However, there is no top-level rcu_read_lock() in
  * the core code; instead, the RCU protection relies on everything happening
@@ -4410,10 +4420,10 @@ static const struct bpf_func_proto bpf_xdp_redirect_proto = {
        .arg2_type      = ARG_ANYTHING,
 };
 
-BPF_CALL_3(bpf_xdp_redirect_map, struct bpf_map *, map, u32, ifindex,
+BPF_CALL_3(bpf_xdp_redirect_map, struct bpf_map *, map, u64, key,
           u64, flags)
 {
-       return map->ops->map_redirect(map, ifindex, flags);
+       return map->ops->map_redirect(map, key, flags);
 }
 
 static const struct bpf_func_proto bpf_xdp_redirect_map_proto = {
@@ -5621,6 +5631,15 @@ static const struct bpf_func_proto bpf_bind_proto = {
 };
 
 #ifdef CONFIG_XFRM
+
+#if (IS_BUILTIN(CONFIG_XFRM_INTERFACE) && IS_ENABLED(CONFIG_DEBUG_INFO_BTF)) || \
+    (IS_MODULE(CONFIG_XFRM_INTERFACE) && IS_ENABLED(CONFIG_DEBUG_INFO_BTF_MODULES))
+
+struct metadata_dst __percpu *xfrm_bpf_md_dst;
+EXPORT_SYMBOL_GPL(xfrm_bpf_md_dst);
+
+#endif
+
 BPF_CALL_5(bpf_skb_get_xfrm_state, struct sk_buff *, skb, u32, index,
           struct bpf_xfrm_state *, to, u32, size, u64, flags)
 {
@@ -6428,7 +6447,7 @@ static struct sock *sk_lookup(struct net *net, struct bpf_sock_tuple *tuple,
                else
                        sk = __udp4_lib_lookup(net, src4, tuple->ipv4.sport,
                                               dst4, tuple->ipv4.dport,
-                                              dif, sdif, &udp_table, NULL);
+                                              dif, sdif, net->ipv4.udp_table, NULL);
 #if IS_ENABLED(CONFIG_IPV6)
        } else {
                struct in6_addr *src6 = (struct in6_addr *)&tuple->ipv6.saddr;
@@ -6444,7 +6463,7 @@ static struct sock *sk_lookup(struct net *net, struct bpf_sock_tuple *tuple,
                                                            src6, tuple->ipv6.sport,
                                                            dst6, tuple->ipv6.dport,
                                                            dif, sdif,
-                                                           &udp_table, NULL);
+                                                           net->ipv4.udp_table, NULL);
 #endif
        }
 
@@ -7983,6 +8002,19 @@ xdp_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
        default:
                return bpf_sk_base_func_proto(func_id);
        }
+
+#if IS_MODULE(CONFIG_NF_CONNTRACK) && IS_ENABLED(CONFIG_DEBUG_INFO_BTF_MODULES)
+       /* The nf_conn___init type is used in the NF_CONNTRACK kfuncs. The
+        * kfuncs are defined in two different modules, and we want to be able
+        * to use them interchangably with the same BTF type ID. Because modules
+        * can't de-duplicate BTF IDs between each other, we need the type to be
+        * referenced in the vmlinux BTF or the verifier will get confused about
+        * the different types. So we add this dummy type reference which will
+        * be included in vmlinux BTF, allowing both modules to refer to the
+        * same type ID.
+        */
+       BTF_TYPE_EMIT(struct nf_conn___init);
+#endif
 }
 
 const struct bpf_func_proto bpf_sock_map_update_proto __weak;
@@ -8647,28 +8679,25 @@ static bool tc_cls_act_is_valid_access(int off, int size,
 DEFINE_MUTEX(nf_conn_btf_access_lock);
 EXPORT_SYMBOL_GPL(nf_conn_btf_access_lock);
 
-int (*nfct_btf_struct_access)(struct bpf_verifier_log *log, const struct btf *btf,
-                             const struct btf_type *t, int off, int size,
-                             enum bpf_access_type atype, u32 *next_btf_id,
-                             enum bpf_type_flag *flag);
+int (*nfct_btf_struct_access)(struct bpf_verifier_log *log,
+                             const struct bpf_reg_state *reg,
+                             int off, int size, enum bpf_access_type atype,
+                             u32 *next_btf_id, enum bpf_type_flag *flag);
 EXPORT_SYMBOL_GPL(nfct_btf_struct_access);
 
 static int tc_cls_act_btf_struct_access(struct bpf_verifier_log *log,
-                                       const struct btf *btf,
-                                       const struct btf_type *t, int off,
-                                       int size, enum bpf_access_type atype,
-                                       u32 *next_btf_id,
-                                       enum bpf_type_flag *flag)
+                                       const struct bpf_reg_state *reg,
+                                       int off, int size, enum bpf_access_type atype,
+                                       u32 *next_btf_id, enum bpf_type_flag *flag)
 {
        int ret = -EACCES;
 
        if (atype == BPF_READ)
-               return btf_struct_access(log, btf, t, off, size, atype, next_btf_id,
-                                        flag);
+               return btf_struct_access(log, reg, off, size, atype, next_btf_id, flag);
 
        mutex_lock(&nf_conn_btf_access_lock);
        if (nfct_btf_struct_access)
-               ret = nfct_btf_struct_access(log, btf, t, off, size, atype, next_btf_id, flag);
+               ret = nfct_btf_struct_access(log, reg, off, size, atype, next_btf_id, flag);
        mutex_unlock(&nf_conn_btf_access_lock);
 
        return ret;
@@ -8734,21 +8763,18 @@ void bpf_warn_invalid_xdp_action(struct net_device *dev, struct bpf_prog *prog,
 EXPORT_SYMBOL_GPL(bpf_warn_invalid_xdp_action);
 
 static int xdp_btf_struct_access(struct bpf_verifier_log *log,
-                                const struct btf *btf,
-                                const struct btf_type *t, int off,
-                                int size, enum bpf_access_type atype,
-                                u32 *next_btf_id,
-                                enum bpf_type_flag *flag)
+                                const struct bpf_reg_state *reg,
+                                int off, int size, enum bpf_access_type atype,
+                                u32 *next_btf_id, enum bpf_type_flag *flag)
 {
        int ret = -EACCES;
 
        if (atype == BPF_READ)
-               return btf_struct_access(log, btf, t, off, size, atype, next_btf_id,
-                                        flag);
+               return btf_struct_access(log, reg, off, size, atype, next_btf_id, flag);
 
        mutex_lock(&nf_conn_btf_access_lock);
        if (nfct_btf_struct_access)
-               ret = nfct_btf_struct_access(log, btf, t, off, size, atype, next_btf_id, flag);
+               ret = nfct_btf_struct_access(log, reg, off, size, atype, next_btf_id, flag);
        mutex_unlock(&nf_conn_btf_access_lock);
 
        return ret;
@@ -8921,6 +8947,10 @@ static bool sock_ops_is_valid_access(int off, int size,
                        bpf_ctx_record_field_size(info, size_default);
                        return bpf_ctx_narrow_access_ok(off, size,
                                                        size_default);
+               case offsetof(struct bpf_sock_ops, skb_hwtstamp):
+                       if (size != sizeof(__u64))
+                               return false;
+                       break;
                default:
                        if (size != size_default)
                                return false;
@@ -9104,21 +9134,21 @@ static struct bpf_insn *bpf_convert_tstamp_type_read(const struct bpf_insn *si,
        return insn;
 }
 
-static struct bpf_insn *bpf_convert_shinfo_access(const struct bpf_insn *si,
+static struct bpf_insn *bpf_convert_shinfo_access(__u8 dst_reg, __u8 skb_reg,
                                                  struct bpf_insn *insn)
 {
        /* si->dst_reg = skb_shinfo(SKB); */
 #ifdef NET_SKBUFF_DATA_USES_OFFSET
        *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, end),
-                             BPF_REG_AX, si->src_reg,
+                             BPF_REG_AX, skb_reg,
                              offsetof(struct sk_buff, end));
        *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, head),
-                             si->dst_reg, si->src_reg,
+                             dst_reg, skb_reg,
                              offsetof(struct sk_buff, head));
-       *insn++ = BPF_ALU64_REG(BPF_ADD, si->dst_reg, BPF_REG_AX);
+       *insn++ = BPF_ALU64_REG(BPF_ADD, dst_reg, BPF_REG_AX);
 #else
        *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, end),
-                             si->dst_reg, si->src_reg,
+                             dst_reg, skb_reg,
                              offsetof(struct sk_buff, end));
 #endif
 
@@ -9290,13 +9320,11 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct __sk_buff, vlan_present):
-               *target_size = 1;
-               *insn++ = BPF_LDX_MEM(BPF_B, si->dst_reg, si->src_reg,
-                                     PKT_VLAN_PRESENT_OFFSET);
-               if (PKT_VLAN_PRESENT_BIT)
-                       *insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg, PKT_VLAN_PRESENT_BIT);
-               if (PKT_VLAN_PRESENT_BIT < 7)
-                       *insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, 1);
+               *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
+                                     bpf_target_off(struct sk_buff,
+                                                    vlan_all, 4, target_size));
+               *insn++ = BPF_JMP_IMM(BPF_JEQ, si->dst_reg, 0, 1);
+               *insn++ = BPF_ALU32_IMM(BPF_MOV, si->dst_reg, 1);
                break;
 
        case offsetof(struct __sk_buff, vlan_tci):
@@ -9511,7 +9539,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct __sk_buff, gso_segs):
-               insn = bpf_convert_shinfo_access(si, insn);
+               insn = bpf_convert_shinfo_access(si->dst_reg, si->src_reg, insn);
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct skb_shared_info, gso_segs),
                                      si->dst_reg, si->dst_reg,
                                      bpf_target_off(struct skb_shared_info,
@@ -9519,7 +9547,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                                                     target_size));
                break;
        case offsetof(struct __sk_buff, gso_size):
-               insn = bpf_convert_shinfo_access(si, insn);
+               insn = bpf_convert_shinfo_access(si->dst_reg, si->src_reg, insn);
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct skb_shared_info, gso_size),
                                      si->dst_reg, si->dst_reg,
                                      bpf_target_off(struct skb_shared_info,
@@ -9546,7 +9574,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                BUILD_BUG_ON(sizeof_field(struct skb_shared_hwtstamps, hwtstamp) != 8);
                BUILD_BUG_ON(offsetof(struct skb_shared_hwtstamps, hwtstamp) != 0);
 
-               insn = bpf_convert_shinfo_access(si, insn);
+               insn = bpf_convert_shinfo_access(si->dst_reg, si->src_reg, insn);
                *insn++ = BPF_LDX_MEM(BPF_DW,
                                      si->dst_reg, si->dst_reg,
                                      bpf_target_off(struct skb_shared_info,
@@ -10396,6 +10424,25 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                                                       tcp_flags),
                                      si->dst_reg, si->dst_reg, off);
                break;
+       case offsetof(struct bpf_sock_ops, skb_hwtstamp): {
+               struct bpf_insn *jmp_on_null_skb;
+
+               *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_sock_ops_kern,
+                                                      skb),
+                                     si->dst_reg, si->src_reg,
+                                     offsetof(struct bpf_sock_ops_kern,
+                                              skb));
+               /* Reserve one insn to test skb == NULL */
+               jmp_on_null_skb = insn++;
+               insn = bpf_convert_shinfo_access(si->dst_reg, si->dst_reg, insn);
+               *insn++ = BPF_LDX_MEM(BPF_DW, si->dst_reg, si->dst_reg,
+                                     bpf_target_off(struct skb_shared_info,
+                                                    hwtstamps, 8,
+                                                    target_size));
+               *jmp_on_null_skb = BPF_JMP_IMM(BPF_JEQ, si->dst_reg, 0,
+                                              insn - jmp_on_null_skb - 1);
+               break;
+       }
        }
        return insn - insn_buf;
 }