/* gso_segs is allowed */
 
        if (!range_is_zero(__skb, offsetofend(struct __sk_buff, gso_segs),
+                          offsetof(struct __sk_buff, gso_size)))
+               return -EINVAL;
+
+       /* gso_size is allowed */
+
+       if (!range_is_zero(__skb, offsetofend(struct __sk_buff, gso_size),
                           sizeof(struct __sk_buff)))
                return -EINVAL;
 
        if (__skb->gso_segs > GSO_MAX_SEGS)
                return -EINVAL;
        skb_shinfo(skb)->gso_segs = __skb->gso_segs;
+       skb_shinfo(skb)->gso_size = __skb->gso_size;
 
        return 0;
 }
 
        return insn - insn_buf;
 }
 
+static struct bpf_insn *bpf_convert_shinfo_access(const struct bpf_insn *si,
+                                                 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,
+                             offsetof(struct sk_buff, end));
+       *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, head),
+                             si->dst_reg, si->src_reg,
+                             offsetof(struct sk_buff, head));
+       *insn++ = BPF_ALU64_REG(BPF_ADD, si->dst_reg, BPF_REG_AX);
+#else
+       *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, end),
+                             si->dst_reg, si->src_reg,
+                             offsetof(struct sk_buff, end));
+#endif
+
+       return insn;
+}
+
 static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                                  const struct bpf_insn *si,
                                  struct bpf_insn *insn_buf,
                break;
 
        case offsetof(struct __sk_buff, gso_segs):
-               /* 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,
-                                     offsetof(struct sk_buff, end));
-               *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, head),
-                                     si->dst_reg, si->src_reg,
-                                     offsetof(struct sk_buff, head));
-               *insn++ = BPF_ALU64_REG(BPF_ADD, si->dst_reg, BPF_REG_AX);
-#else
-               *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, end),
-                                     si->dst_reg, si->src_reg,
-                                     offsetof(struct sk_buff, end));
-#endif
+               insn = bpf_convert_shinfo_access(si, 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,
                                                     gso_segs, 2,
                                                     target_size));
                break;
+       case offsetof(struct __sk_buff, gso_size):
+               insn = bpf_convert_shinfo_access(si, 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,
+                                                    gso_size, 2,
+                                                    target_size));
+               break;
        case offsetof(struct __sk_buff, wire_len):
                BUILD_BUG_ON(sizeof_field(struct qdisc_skb_cb, pkt_len) != 4);