Merge tag 'h8300-for-linus-20190617' of git://git.sourceforge.jp/gitroot/uclinux...
[linux-2.6-block.git] / net / core / filter.c
index f615e42cf4eff2336a699cf146be801a1efb1ef7..47f6386fb17afbd41c2685097b9eac75d92c634b 100644 (file)
@@ -62,6 +62,7 @@
 #include <net/inet_hashtables.h>
 #include <net/inet6_hashtables.h>
 #include <net/ip_fib.h>
+#include <net/nexthop.h>
 #include <net/flow.h>
 #include <net/arp.h>
 #include <net/ipv6.h>
@@ -2157,8 +2158,8 @@ BPF_CALL_2(bpf_redirect, u32, ifindex, u64, flags)
        if (unlikely(flags & ~(BPF_F_INGRESS)))
                return TC_ACT_SHOT;
 
-       ri->ifindex = ifindex;
        ri->flags = flags;
+       ri->tgt_index = ifindex;
 
        return TC_ACT_REDIRECT;
 }
@@ -2168,8 +2169,8 @@ int skb_do_redirect(struct sk_buff *skb)
        struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
        struct net_device *dev;
 
-       dev = dev_get_by_index_rcu(dev_net(skb->dev), ri->ifindex);
-       ri->ifindex = 0;
+       dev = dev_get_by_index_rcu(dev_net(skb->dev), ri->tgt_index);
+       ri->tgt_index = 0;
        if (unlikely(!dev)) {
                kfree_skb(skb);
                return -EINVAL;
@@ -3487,11 +3488,11 @@ xdp_do_redirect_slow(struct net_device *dev, struct xdp_buff *xdp,
                     struct bpf_prog *xdp_prog, struct bpf_redirect_info *ri)
 {
        struct net_device *fwd;
-       u32 index = ri->ifindex;
+       u32 index = ri->tgt_index;
        int err;
 
        fwd = dev_get_by_index_rcu(dev_net(dev), index);
-       ri->ifindex = 0;
+       ri->tgt_index = 0;
        if (unlikely(!fwd)) {
                err = -EINVAL;
                goto err;
@@ -3522,7 +3523,6 @@ static int __bpf_tx_xdp_map(struct net_device *dev_rx, void *fwd,
                err = dev_map_enqueue(dst, xdp, dev_rx);
                if (unlikely(err))
                        return err;
-               __dev_map_insert_ctx(map, index);
                break;
        }
        case BPF_MAP_TYPE_CPUMAP: {
@@ -3531,7 +3531,6 @@ static int __bpf_tx_xdp_map(struct net_device *dev_rx, void *fwd,
                err = cpu_map_enqueue(rcpu, xdp, dev_rx);
                if (unlikely(err))
                        return err;
-               __cpu_map_insert_ctx(map, index);
                break;
        }
        case BPF_MAP_TYPE_XSKMAP: {
@@ -3605,18 +3604,14 @@ static int xdp_do_redirect_map(struct net_device *dev, struct xdp_buff *xdp,
                               struct bpf_prog *xdp_prog, struct bpf_map *map,
                               struct bpf_redirect_info *ri)
 {
-       u32 index = ri->ifindex;
-       void *fwd = NULL;
+       u32 index = ri->tgt_index;
+       void *fwd = ri->tgt_value;
        int err;
 
-       ri->ifindex = 0;
+       ri->tgt_index = 0;
+       ri->tgt_value = NULL;
        WRITE_ONCE(ri->map, NULL);
 
-       fwd = __xdp_map_lookup_elem(map, index);
-       if (unlikely(!fwd)) {
-               err = -EINVAL;
-               goto err;
-       }
        if (ri->map_to_flush && unlikely(ri->map_to_flush != map))
                xdp_do_flush_map();
 
@@ -3652,19 +3647,14 @@ static int xdp_do_generic_redirect_map(struct net_device *dev,
                                       struct bpf_map *map)
 {
        struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
-       u32 index = ri->ifindex;
-       void *fwd = NULL;
+       u32 index = ri->tgt_index;
+       void *fwd = ri->tgt_value;
        int err = 0;
 
-       ri->ifindex = 0;
+       ri->tgt_index = 0;
+       ri->tgt_value = NULL;
        WRITE_ONCE(ri->map, NULL);
 
-       fwd = __xdp_map_lookup_elem(map, index);
-       if (unlikely(!fwd)) {
-               err = -EINVAL;
-               goto err;
-       }
-
        if (map->map_type == BPF_MAP_TYPE_DEVMAP) {
                struct bpf_dtab_netdev *dst = fwd;
 
@@ -3696,14 +3686,14 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
 {
        struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
        struct bpf_map *map = READ_ONCE(ri->map);
-       u32 index = ri->ifindex;
+       u32 index = ri->tgt_index;
        struct net_device *fwd;
        int err = 0;
 
        if (map)
                return xdp_do_generic_redirect_map(dev, skb, xdp, xdp_prog,
                                                   map);
-       ri->ifindex = 0;
+       ri->tgt_index = 0;
        fwd = dev_get_by_index_rcu(dev_net(dev), index);
        if (unlikely(!fwd)) {
                err = -EINVAL;
@@ -3731,8 +3721,9 @@ BPF_CALL_2(bpf_xdp_redirect, u32, ifindex, u64, flags)
        if (unlikely(flags))
                return XDP_ABORTED;
 
-       ri->ifindex = ifindex;
        ri->flags = flags;
+       ri->tgt_index = ifindex;
+       ri->tgt_value = NULL;
        WRITE_ONCE(ri->map, NULL);
 
        return XDP_REDIRECT;
@@ -3751,11 +3742,23 @@ BPF_CALL_3(bpf_xdp_redirect_map, struct bpf_map *, map, u32, ifindex,
 {
        struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
 
-       if (unlikely(flags))
+       /* Lower bits of the flags are used as return code on lookup failure */
+       if (unlikely(flags > XDP_TX))
                return XDP_ABORTED;
 
-       ri->ifindex = ifindex;
+       ri->tgt_value = __xdp_map_lookup_elem(map, ifindex);
+       if (unlikely(!ri->tgt_value)) {
+               /* If the lookup fails we want to clear out the state in the
+                * redirect_info struct completely, so that if an eBPF program
+                * performs multiple lookups, the last one always takes
+                * precedence.
+                */
+               WRITE_ONCE(ri->map, NULL);
+               return flags;
+       }
+
        ri->flags = flags;
+       ri->tgt_index = ifindex;
        WRITE_ONCE(ri->map, map);
 
        return XDP_REDIRECT;
@@ -4670,7 +4673,7 @@ static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
        if (res.type != RTN_UNICAST)
                return BPF_FIB_LKUP_RET_NOT_FWDED;
 
-       if (res.fi->fib_nhs > 1)
+       if (fib_info_num_path(res.fi) > 1)
                fib_select_path(net, &res, &fl4, NULL);
 
        if (check_mtu) {
@@ -4737,7 +4740,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
                return -ENODEV;
 
        idev = __in6_dev_get_safely(dev);
-       if (unlikely(!idev || !net->ipv6.devconf_all->forwarding))
+       if (unlikely(!idev || !idev->cnf.forwarding))
                return BPF_FIB_LKUP_RET_FWD_DISABLED;
 
        if (flags & BPF_FIB_LOOKUP_OUTPUT) {
@@ -5191,54 +5194,6 @@ static const struct bpf_func_proto bpf_lwt_seg6_adjust_srh_proto = {
 };
 #endif /* CONFIG_IPV6_SEG6_BPF */
 
-#define CONVERT_COMMON_TCP_SOCK_FIELDS(md_type, CONVERT)               \
-do {                                                                   \
-       switch (si->off) {                                              \
-       case offsetof(md_type, snd_cwnd):                               \
-               CONVERT(snd_cwnd); break;                               \
-       case offsetof(md_type, srtt_us):                                \
-               CONVERT(srtt_us); break;                                \
-       case offsetof(md_type, snd_ssthresh):                           \
-               CONVERT(snd_ssthresh); break;                           \
-       case offsetof(md_type, rcv_nxt):                                \
-               CONVERT(rcv_nxt); break;                                \
-       case offsetof(md_type, snd_nxt):                                \
-               CONVERT(snd_nxt); break;                                \
-       case offsetof(md_type, snd_una):                                \
-               CONVERT(snd_una); break;                                \
-       case offsetof(md_type, mss_cache):                              \
-               CONVERT(mss_cache); break;                              \
-       case offsetof(md_type, ecn_flags):                              \
-               CONVERT(ecn_flags); break;                              \
-       case offsetof(md_type, rate_delivered):                         \
-               CONVERT(rate_delivered); break;                         \
-       case offsetof(md_type, rate_interval_us):                       \
-               CONVERT(rate_interval_us); break;                       \
-       case offsetof(md_type, packets_out):                            \
-               CONVERT(packets_out); break;                            \
-       case offsetof(md_type, retrans_out):                            \
-               CONVERT(retrans_out); break;                            \
-       case offsetof(md_type, total_retrans):                          \
-               CONVERT(total_retrans); break;                          \
-       case offsetof(md_type, segs_in):                                \
-               CONVERT(segs_in); break;                                \
-       case offsetof(md_type, data_segs_in):                           \
-               CONVERT(data_segs_in); break;                           \
-       case offsetof(md_type, segs_out):                               \
-               CONVERT(segs_out); break;                               \
-       case offsetof(md_type, data_segs_out):                          \
-               CONVERT(data_segs_out); break;                          \
-       case offsetof(md_type, lost_out):                               \
-               CONVERT(lost_out); break;                               \
-       case offsetof(md_type, sacked_out):                             \
-               CONVERT(sacked_out); break;                             \
-       case offsetof(md_type, bytes_received):                         \
-               CONVERT(bytes_received); break;                         \
-       case offsetof(md_type, bytes_acked):                            \
-               CONVERT(bytes_acked); break;                            \
-       }                                                               \
-} while (0)
-
 #ifdef CONFIG_INET
 static struct sock *sk_lookup(struct net *net, struct bpf_sock_tuple *tuple,
                              int dif, int sdif, u8 family, u8 proto)
@@ -5589,7 +5544,8 @@ static const struct bpf_func_proto bpf_sock_addr_sk_lookup_udp_proto = {
 bool bpf_tcp_sock_is_valid_access(int off, int size, enum bpf_access_type type,
                                  struct bpf_insn_access_aux *info)
 {
-       if (off < 0 || off >= offsetofend(struct bpf_tcp_sock, bytes_acked))
+       if (off < 0 || off >= offsetofend(struct bpf_tcp_sock,
+                                         icsk_retransmits))
                return false;
 
        if (off % size != 0)
@@ -5620,8 +5576,19 @@ u32 bpf_tcp_sock_convert_ctx_access(enum bpf_access_type type,
                                      offsetof(struct tcp_sock, FIELD)); \
        } while (0)
 
-       CONVERT_COMMON_TCP_SOCK_FIELDS(struct bpf_tcp_sock,
-                                      BPF_TCP_SOCK_GET_COMMON);
+#define BPF_INET_SOCK_GET_COMMON(FIELD)                                        \
+       do {                                                            \
+               BUILD_BUG_ON(FIELD_SIZEOF(struct inet_connection_sock,  \
+                                         FIELD) >                      \
+                            FIELD_SIZEOF(struct bpf_tcp_sock, FIELD)); \
+               *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(                 \
+                                       struct inet_connection_sock,    \
+                                       FIELD),                         \
+                                     si->dst_reg, si->src_reg,         \
+                                     offsetof(                         \
+                                       struct inet_connection_sock,    \
+                                       FIELD));                        \
+       } while (0)
 
        if (insn > insn_buf)
                return insn - insn_buf;
@@ -5637,6 +5604,81 @@ u32 bpf_tcp_sock_convert_ctx_access(enum bpf_access_type type,
                                      offsetof(struct tcp_sock, rtt_min) +
                                      offsetof(struct minmax_sample, v));
                break;
+       case offsetof(struct bpf_tcp_sock, snd_cwnd):
+               BPF_TCP_SOCK_GET_COMMON(snd_cwnd);
+               break;
+       case offsetof(struct bpf_tcp_sock, srtt_us):
+               BPF_TCP_SOCK_GET_COMMON(srtt_us);
+               break;
+       case offsetof(struct bpf_tcp_sock, snd_ssthresh):
+               BPF_TCP_SOCK_GET_COMMON(snd_ssthresh);
+               break;
+       case offsetof(struct bpf_tcp_sock, rcv_nxt):
+               BPF_TCP_SOCK_GET_COMMON(rcv_nxt);
+               break;
+       case offsetof(struct bpf_tcp_sock, snd_nxt):
+               BPF_TCP_SOCK_GET_COMMON(snd_nxt);
+               break;
+       case offsetof(struct bpf_tcp_sock, snd_una):
+               BPF_TCP_SOCK_GET_COMMON(snd_una);
+               break;
+       case offsetof(struct bpf_tcp_sock, mss_cache):
+               BPF_TCP_SOCK_GET_COMMON(mss_cache);
+               break;
+       case offsetof(struct bpf_tcp_sock, ecn_flags):
+               BPF_TCP_SOCK_GET_COMMON(ecn_flags);
+               break;
+       case offsetof(struct bpf_tcp_sock, rate_delivered):
+               BPF_TCP_SOCK_GET_COMMON(rate_delivered);
+               break;
+       case offsetof(struct bpf_tcp_sock, rate_interval_us):
+               BPF_TCP_SOCK_GET_COMMON(rate_interval_us);
+               break;
+       case offsetof(struct bpf_tcp_sock, packets_out):
+               BPF_TCP_SOCK_GET_COMMON(packets_out);
+               break;
+       case offsetof(struct bpf_tcp_sock, retrans_out):
+               BPF_TCP_SOCK_GET_COMMON(retrans_out);
+               break;
+       case offsetof(struct bpf_tcp_sock, total_retrans):
+               BPF_TCP_SOCK_GET_COMMON(total_retrans);
+               break;
+       case offsetof(struct bpf_tcp_sock, segs_in):
+               BPF_TCP_SOCK_GET_COMMON(segs_in);
+               break;
+       case offsetof(struct bpf_tcp_sock, data_segs_in):
+               BPF_TCP_SOCK_GET_COMMON(data_segs_in);
+               break;
+       case offsetof(struct bpf_tcp_sock, segs_out):
+               BPF_TCP_SOCK_GET_COMMON(segs_out);
+               break;
+       case offsetof(struct bpf_tcp_sock, data_segs_out):
+               BPF_TCP_SOCK_GET_COMMON(data_segs_out);
+               break;
+       case offsetof(struct bpf_tcp_sock, lost_out):
+               BPF_TCP_SOCK_GET_COMMON(lost_out);
+               break;
+       case offsetof(struct bpf_tcp_sock, sacked_out):
+               BPF_TCP_SOCK_GET_COMMON(sacked_out);
+               break;
+       case offsetof(struct bpf_tcp_sock, bytes_received):
+               BPF_TCP_SOCK_GET_COMMON(bytes_received);
+               break;
+       case offsetof(struct bpf_tcp_sock, bytes_acked):
+               BPF_TCP_SOCK_GET_COMMON(bytes_acked);
+               break;
+       case offsetof(struct bpf_tcp_sock, dsack_dups):
+               BPF_TCP_SOCK_GET_COMMON(dsack_dups);
+               break;
+       case offsetof(struct bpf_tcp_sock, delivered):
+               BPF_TCP_SOCK_GET_COMMON(delivered);
+               break;
+       case offsetof(struct bpf_tcp_sock, delivered_ce):
+               BPF_TCP_SOCK_GET_COMMON(delivered_ce);
+               break;
+       case offsetof(struct bpf_tcp_sock, icsk_retransmits):
+               BPF_INET_SOCK_GET_COMMON(icsk_retransmits);
+               break;
        }
 
        return insn - insn_buf;
@@ -5650,7 +5692,7 @@ BPF_CALL_1(bpf_tcp_sock, struct sock *, sk)
        return (unsigned long)NULL;
 }
 
-static const struct bpf_func_proto bpf_tcp_sock_proto = {
+const struct bpf_func_proto bpf_tcp_sock_proto = {
        .func           = bpf_tcp_sock,
        .gpl_only       = false,
        .ret_type       = RET_PTR_TO_TCP_SOCK_OR_NULL,
@@ -5694,6 +5736,46 @@ BPF_CALL_1(bpf_skb_ecn_set_ce, struct sk_buff *, skb)
        return INET_ECN_set_ce(skb);
 }
 
+bool bpf_xdp_sock_is_valid_access(int off, int size, enum bpf_access_type type,
+                                 struct bpf_insn_access_aux *info)
+{
+       if (off < 0 || off >= offsetofend(struct bpf_xdp_sock, queue_id))
+               return false;
+
+       if (off % size != 0)
+               return false;
+
+       switch (off) {
+       default:
+               return size == sizeof(__u32);
+       }
+}
+
+u32 bpf_xdp_sock_convert_ctx_access(enum bpf_access_type type,
+                                   const struct bpf_insn *si,
+                                   struct bpf_insn *insn_buf,
+                                   struct bpf_prog *prog, u32 *target_size)
+{
+       struct bpf_insn *insn = insn_buf;
+
+#define BPF_XDP_SOCK_GET(FIELD)                                                \
+       do {                                                            \
+               BUILD_BUG_ON(FIELD_SIZEOF(struct xdp_sock, FIELD) >     \
+                            FIELD_SIZEOF(struct bpf_xdp_sock, FIELD)); \
+               *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct xdp_sock, FIELD),\
+                                     si->dst_reg, si->src_reg,         \
+                                     offsetof(struct xdp_sock, FIELD)); \
+       } while (0)
+
+       switch (si->off) {
+       case offsetof(struct bpf_xdp_sock, queue_id):
+               BPF_XDP_SOCK_GET(queue_id);
+               break;
+       }
+
+       return insn - insn_buf;
+}
+
 static const struct bpf_func_proto bpf_skb_ecn_set_ce_proto = {
        .func           = bpf_skb_ecn_set_ce,
        .gpl_only       = false,
@@ -5896,6 +5978,10 @@ sock_addr_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
        case BPF_FUNC_skc_lookup_tcp:
                return &bpf_sock_addr_skc_lookup_tcp_proto;
 #endif /* CONFIG_INET */
+       case BPF_FUNC_sk_storage_get:
+               return &bpf_sk_storage_get_proto;
+       case BPF_FUNC_sk_storage_delete:
+               return &bpf_sk_storage_delete_proto;
        default:
                return bpf_base_func_proto(func_id);
        }
@@ -5933,6 +6019,10 @@ cg_skb_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
                return &bpf_sk_storage_get_proto;
        case BPF_FUNC_sk_storage_delete:
                return &bpf_sk_storage_delete_proto;
+#ifdef CONFIG_SOCK_CGROUP_DATA
+       case BPF_FUNC_skb_cgroup_id:
+               return &bpf_skb_cgroup_id_proto;
+#endif
 #ifdef CONFIG_INET
        case BPF_FUNC_tcp_sock:
                return &bpf_tcp_sock_proto;
@@ -6113,6 +6203,14 @@ sock_ops_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
                return &bpf_get_local_storage_proto;
        case BPF_FUNC_perf_event_output:
                return &bpf_sockopt_event_output_proto;
+       case BPF_FUNC_sk_storage_get:
+               return &bpf_sk_storage_get_proto;
+       case BPF_FUNC_sk_storage_delete:
+               return &bpf_sk_storage_delete_proto;
+#ifdef CONFIG_INET
+       case BPF_FUNC_tcp_sock:
+               return &bpf_tcp_sock_proto;
+#endif /* CONFIG_INET */
        default:
                return bpf_base_func_proto(func_id);
        }
@@ -6792,6 +6890,16 @@ static bool sock_addr_is_valid_access(int off, int size,
                        if (!bpf_ctx_narrow_access_ok(off, size, size_default))
                                return false;
                } else {
+                       if (bpf_ctx_wide_store_ok(off, size,
+                                                 struct bpf_sock_addr,
+                                                 user_ip6))
+                               return true;
+
+                       if (bpf_ctx_wide_store_ok(off, size,
+                                                 struct bpf_sock_addr,
+                                                 msg_src_ip6))
+                               return true;
+
                        if (size != size_default)
                                return false;
                }
@@ -6800,6 +6908,13 @@ static bool sock_addr_is_valid_access(int off, int size,
                if (size != size_default)
                        return false;
                break;
+       case offsetof(struct bpf_sock_addr, sk):
+               if (type != BPF_READ)
+                       return false;
+               if (size != sizeof(__u64))
+                       return false;
+               info->reg_type = PTR_TO_SOCKET;
+               break;
        default:
                if (type == BPF_READ) {
                        if (size != size_default)
@@ -6843,6 +6958,11 @@ static bool sock_ops_is_valid_access(int off, int size,
                        if (size != sizeof(__u64))
                                return false;
                        break;
+               case offsetof(struct bpf_sock_ops, sk):
+                       if (size != sizeof(__u64))
+                               return false;
+                       info->reg_type = PTR_TO_SOCKET_OR_NULL;
+                       break;
                default:
                        if (size != size_default)
                                return false;
@@ -7620,9 +7740,6 @@ static u32 xdp_convert_ctx_access(enum bpf_access_type type,
 /* SOCK_ADDR_STORE_NESTED_FIELD_OFF() has semantic similar to
  * SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF() but for store operation.
  *
- * It doesn't support SIZE argument though since narrow stores are not
- * supported for now.
- *
  * In addition it uses Temporary Field TF (member of struct S) as the 3rd
  * "register" since two registers available in convert_ctx_access are not
  * enough: we can't override neither SRC, since it contains value to store, nor
@@ -7630,7 +7747,7 @@ static u32 xdp_convert_ctx_access(enum bpf_access_type type,
  * instructions. But we need a temporary place to save pointer to nested
  * structure whose field we want to store to.
  */
-#define SOCK_ADDR_STORE_NESTED_FIELD_OFF(S, NS, F, NF, OFF, TF)                       \
+#define SOCK_ADDR_STORE_NESTED_FIELD_OFF(S, NS, F, NF, SIZE, OFF, TF)         \
        do {                                                                   \
                int tmp_reg = BPF_REG_9;                                       \
                if (si->src_reg == tmp_reg || si->dst_reg == tmp_reg)          \
@@ -7641,8 +7758,7 @@ static u32 xdp_convert_ctx_access(enum bpf_access_type type,
                                      offsetof(S, TF));                        \
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(S, F), tmp_reg,         \
                                      si->dst_reg, offsetof(S, F));            \
-               *insn++ = BPF_STX_MEM(                                         \
-                       BPF_FIELD_SIZEOF(NS, NF), tmp_reg, si->src_reg,        \
+               *insn++ = BPF_STX_MEM(SIZE, tmp_reg, si->src_reg,              \
                        bpf_target_off(NS, NF, FIELD_SIZEOF(NS, NF),           \
                                       target_size)                            \
                                + OFF);                                        \
@@ -7654,8 +7770,8 @@ static u32 xdp_convert_ctx_access(enum bpf_access_type type,
                                                      TF)                      \
        do {                                                                   \
                if (type == BPF_WRITE) {                                       \
-                       SOCK_ADDR_STORE_NESTED_FIELD_OFF(S, NS, F, NF, OFF,    \
-                                                        TF);                  \
+                       SOCK_ADDR_STORE_NESTED_FIELD_OFF(S, NS, F, NF, SIZE,   \
+                                                        OFF, TF);             \
                } else {                                                       \
                        SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF(                  \
                                S, NS, F, NF, SIZE, OFF);  \
@@ -7750,6 +7866,11 @@ static u32 sock_addr_convert_ctx_access(enum bpf_access_type type,
                        struct bpf_sock_addr_kern, struct in6_addr, t_ctx,
                        s6_addr32[0], BPF_SIZE(si->code), off, tmp_reg);
                break;
+       case offsetof(struct bpf_sock_addr, sk):
+               *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_sock_addr_kern, sk),
+                                     si->dst_reg, si->src_reg,
+                                     offsetof(struct bpf_sock_addr_kern, sk));
+               break;
        }
 
        return insn - insn_buf;
@@ -7837,9 +7958,6 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                        SOCK_OPS_GET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ);        \
        } while (0)
 
-       CONVERT_COMMON_TCP_SOCK_FIELDS(struct bpf_sock_ops,
-                                      SOCK_OPS_GET_TCP_SOCK_FIELD);
-
        if (insn > insn_buf)
                return insn - insn_buf;
 
@@ -8009,6 +8127,82 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                SOCK_OPS_GET_OR_SET_FIELD(sk_txhash, sk_txhash,
                                          struct sock, type);
                break;
+       case offsetof(struct bpf_sock_ops, snd_cwnd):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(snd_cwnd);
+               break;
+       case offsetof(struct bpf_sock_ops, srtt_us):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(srtt_us);
+               break;
+       case offsetof(struct bpf_sock_ops, snd_ssthresh):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(snd_ssthresh);
+               break;
+       case offsetof(struct bpf_sock_ops, rcv_nxt):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(rcv_nxt);
+               break;
+       case offsetof(struct bpf_sock_ops, snd_nxt):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(snd_nxt);
+               break;
+       case offsetof(struct bpf_sock_ops, snd_una):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(snd_una);
+               break;
+       case offsetof(struct bpf_sock_ops, mss_cache):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(mss_cache);
+               break;
+       case offsetof(struct bpf_sock_ops, ecn_flags):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(ecn_flags);
+               break;
+       case offsetof(struct bpf_sock_ops, rate_delivered):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(rate_delivered);
+               break;
+       case offsetof(struct bpf_sock_ops, rate_interval_us):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(rate_interval_us);
+               break;
+       case offsetof(struct bpf_sock_ops, packets_out):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(packets_out);
+               break;
+       case offsetof(struct bpf_sock_ops, retrans_out):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(retrans_out);
+               break;
+       case offsetof(struct bpf_sock_ops, total_retrans):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(total_retrans);
+               break;
+       case offsetof(struct bpf_sock_ops, segs_in):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(segs_in);
+               break;
+       case offsetof(struct bpf_sock_ops, data_segs_in):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(data_segs_in);
+               break;
+       case offsetof(struct bpf_sock_ops, segs_out):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(segs_out);
+               break;
+       case offsetof(struct bpf_sock_ops, data_segs_out):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(data_segs_out);
+               break;
+       case offsetof(struct bpf_sock_ops, lost_out):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(lost_out);
+               break;
+       case offsetof(struct bpf_sock_ops, sacked_out):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(sacked_out);
+               break;
+       case offsetof(struct bpf_sock_ops, bytes_received):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(bytes_received);
+               break;
+       case offsetof(struct bpf_sock_ops, bytes_acked):
+               SOCK_OPS_GET_TCP_SOCK_FIELD(bytes_acked);
+               break;
+       case offsetof(struct bpf_sock_ops, sk):
+               *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+                                               struct bpf_sock_ops_kern,
+                                               is_fullsock),
+                                     si->dst_reg, si->src_reg,
+                                     offsetof(struct bpf_sock_ops_kern,
+                                              is_fullsock));
+               *insn++ = BPF_JMP_IMM(BPF_JEQ, si->dst_reg, 0, 1);
+               *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+                                               struct bpf_sock_ops_kern, sk),
+                                     si->dst_reg, si->src_reg,
+                                     offsetof(struct bpf_sock_ops_kern, sk));
+               break;
        }
        return insn - insn_buf;
 }