[RAMEN9610-21776]ANDROID: net: bpf: permit redirect from ingress L3 to egress L2...
[GitHub/LineageOS/android_kernel_motorola_exynos9610.git] / net / core / filter.c
index 6ae94f825f72eb810b5252e10dd89cae66f8cbef..549c49b63218a5dd0daf157a28299782bac28d05 100644 (file)
@@ -457,6 +457,10 @@ do_pass:
                            convert_bpf_extensions(fp, &insn))
                                break;
 
+                       if (fp->code == (BPF_ALU | BPF_DIV | BPF_X) ||
+                           fp->code == (BPF_ALU | BPF_MOD | BPF_X))
+                               *insn++ = BPF_MOV32_REG(BPF_REG_X, BPF_REG_X);
+
                        *insn = BPF_RAW_INSN(fp->code, BPF_REG_A, BPF_REG_X, 0, fp->k);
                        break;
 
@@ -1053,11 +1057,9 @@ static struct bpf_prog *bpf_migrate_filter(struct bpf_prog *fp)
                 */
                goto out_err_free;
 
-       /* We are guaranteed to never error here with cBPF to eBPF
-        * transitions, since there's no issue with type compatibility
-        * checks on program arrays.
-        */
        fp = bpf_prog_select_runtime(fp, &err);
+       if (err)
+               goto out_err_free;
 
        kfree(old_prog);
        return fp;
@@ -1712,18 +1714,19 @@ static inline int __bpf_tx_skb(struct net_device *dev, struct sk_buff *skb)
 static int __bpf_redirect_no_mac(struct sk_buff *skb, struct net_device *dev,
                                 u32 flags)
 {
-       /* skb->mac_len is not set on normal egress */
-       unsigned int mlen = skb->network_header - skb->mac_header;
+       unsigned int mlen = skb_network_offset(skb);
 
-       __skb_pull(skb, mlen);
+       if (mlen) {
+               __skb_pull(skb, mlen);
 
-       /* At ingress, the mac header has already been pulled once.
-        * At egress, skb_pospull_rcsum has to be done in case that
-        * the skb is originated from ingress (i.e. a forwarded skb)
-        * to ensure that rcsum starts at net header.
-        */
-       if (!skb_at_tc_ingress(skb))
-               skb_postpull_rcsum(skb, skb_mac_header(skb), mlen);
+               /* At ingress, the mac header has already been pulled once.
+                * At egress, skb_pospull_rcsum has to be done in case that
+                * the skb is originated from ingress (i.e. a forwarded skb)
+                * to ensure that rcsum starts at net header.
+                */
+               if (!skb_at_tc_ingress(skb))
+                       skb_postpull_rcsum(skb, skb_mac_header(skb), mlen);
+       }
        skb_pop_mac_header(skb);
        skb_reset_mac_len(skb);
        return flags & BPF_F_INGRESS ?
@@ -2278,6 +2281,8 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 len_diff)
 
 static u32 __bpf_skb_max_len(const struct sk_buff *skb)
 {
+       if (skb_at_tc_ingress(skb) || !skb->dev)
+               return SKB_MAX_ALLOC;
        return skb->dev->mtu + skb->dev->hard_header_len;
 }
 
@@ -3078,10 +3083,12 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
                /* Only some socketops are supported */
                switch (optname) {
                case SO_RCVBUF:
+                       val = min_t(u32, val, sysctl_rmem_max);
                        sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
                        sk->sk_rcvbuf = max_t(int, val * 2, SOCK_MIN_RCVBUF);
                        break;
                case SO_SNDBUF:
+                       val = min_t(u32, val, sysctl_wmem_max);
                        sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
                        sk->sk_sndbuf = max_t(int, val * 2, SOCK_MIN_SNDBUF);
                        break;
@@ -3099,7 +3106,10 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
                        sk->sk_rcvlowat = val ? : 1;
                        break;
                case SO_MARK:
-                       sk->sk_mark = val;
+                       if (sk->sk_mark != val) {
+                               sk->sk_mark = val;
+                               sk_dst_reset(sk);
+                       }
                        break;
                default:
                        ret = -EINVAL;
@@ -3125,7 +3135,7 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
                        /* Only some options are supported */
                        switch (optname) {
                        case TCP_BPF_IW:
-                               if (val <= 0 || tp->data_segs_out > 0)
+                               if (val <= 0 || tp->data_segs_out > tp->syn_data)
                                        ret = -EINVAL;
                                else
                                        tp->snd_cwnd = val;