kernel: move mediatek flow offload refcount fix and fix a logic error
authorFelix Fietkau <nbd@nbd.name>
Mon, 20 Mar 2023 17:06:23 +0000 (18:06 +0100)
committerFelix Fietkau <nbd@nbd.name>
Mon, 20 Mar 2023 20:28:19 +0000 (21:28 +0100)
Move it to pending, since it wasn't actually accepted upstream yet.
Fixes potential issues when doing offload between multiple MACs.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
target/linux/generic/backport-5.15/730-11-v6.3-net-ethernet-mtk_eth_soc-fix-flow_offload-related-re.patch [deleted file]
target/linux/generic/pending-5.15/735-net-ethernet-mtk_eth_soc-fix-flow_offload-related-re.patch [new file with mode: 0644]

diff --git a/target/linux/generic/backport-5.15/730-11-v6.3-net-ethernet-mtk_eth_soc-fix-flow_offload-related-re.patch b/target/linux/generic/backport-5.15/730-11-v6.3-net-ethernet-mtk_eth_soc-fix-flow_offload-related-re.patch
deleted file mode 100644 (file)
index 54e48df..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Thu, 17 Nov 2022 11:58:21 +0100
-Subject: [PATCH] net: ethernet: mtk_eth_soc: fix flow_offload related refcount
- bug
-
-Since we call flow_block_cb_decref on FLOW_BLOCK_UNBIND, we need to call
-flow_block_cb_incref unconditionally, even for a newly allocated cb.
-Fixes a use-after-free bug
-
-Fixes: 502e84e2382d ("net: ethernet: mtk_eth_soc: add flow offloading support")
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
-+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
-@@ -554,6 +554,7 @@ mtk_eth_setup_tc_block(struct net_device
-       struct mtk_eth *eth = mac->hw;
-       static LIST_HEAD(block_cb_list);
-       struct flow_block_cb *block_cb;
-+      bool register_block = false;
-       flow_setup_cb_t *cb;
-       if (!eth->soc->offload_version)
-@@ -568,16 +569,20 @@ mtk_eth_setup_tc_block(struct net_device
-       switch (f->command) {
-       case FLOW_BLOCK_BIND:
-               block_cb = flow_block_cb_lookup(f->block, cb, dev);
--              if (block_cb) {
--                      flow_block_cb_incref(block_cb);
--                      return 0;
-+              if (!block_cb) {
-+                      block_cb = flow_block_cb_alloc(cb, dev, dev, NULL);
-+                      if (IS_ERR(block_cb))
-+                              return PTR_ERR(block_cb);
-+
-+                      register_block = true;
-               }
--              block_cb = flow_block_cb_alloc(cb, dev, dev, NULL);
--              if (IS_ERR(block_cb))
--                      return PTR_ERR(block_cb);
--              flow_block_cb_add(block_cb, f);
--              list_add_tail(&block_cb->driver_list, &block_cb_list);
-+              flow_block_cb_incref(block_cb);
-+
-+              if (register_block) {
-+                      flow_block_cb_add(block_cb, f);
-+                      list_add_tail(&block_cb->driver_list, &block_cb_list);
-+              }
-               return 0;
-       case FLOW_BLOCK_UNBIND:
-               block_cb = flow_block_cb_lookup(f->block, cb, dev);
diff --git a/target/linux/generic/pending-5.15/735-net-ethernet-mtk_eth_soc-fix-flow_offload-related-re.patch b/target/linux/generic/pending-5.15/735-net-ethernet-mtk_eth_soc-fix-flow_offload-related-re.patch
new file mode 100644 (file)
index 0000000..acbdec2
--- /dev/null
@@ -0,0 +1,61 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Mon, 20 Mar 2023 15:49:15 +0100
+Subject: [PATCH] net: ethernet: mtk_eth_soc: fix flow_offload related refcount
+ bug
+
+Since we call flow_block_cb_decref on FLOW_BLOCK_UNBIND, we need to call
+flow_block_cb_incref unconditionally, even for a newly allocated cb.
+Fixes a use-after-free bug. Also fix the accidentally inverted refcount
+check on unbind.
+
+Fixes: 502e84e2382d ("net: ethernet: mtk_eth_soc: add flow offloading support")
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+@@ -561,6 +561,7 @@ mtk_eth_setup_tc_block(struct net_device
+       struct mtk_eth *eth = mac->hw;
+       static LIST_HEAD(block_cb_list);
+       struct flow_block_cb *block_cb;
++      bool register_block = false;
+       flow_setup_cb_t *cb;
+       if (!eth->soc->offload_version)
+@@ -575,23 +576,27 @@ mtk_eth_setup_tc_block(struct net_device
+       switch (f->command) {
+       case FLOW_BLOCK_BIND:
+               block_cb = flow_block_cb_lookup(f->block, cb, dev);
+-              if (block_cb) {
+-                      flow_block_cb_incref(block_cb);
+-                      return 0;
++              if (!block_cb) {
++                      block_cb = flow_block_cb_alloc(cb, dev, dev, NULL);
++                      if (IS_ERR(block_cb))
++                              return PTR_ERR(block_cb);
++
++                      register_block = true;
+               }
+-              block_cb = flow_block_cb_alloc(cb, dev, dev, NULL);
+-              if (IS_ERR(block_cb))
+-                      return PTR_ERR(block_cb);
+-              flow_block_cb_add(block_cb, f);
+-              list_add_tail(&block_cb->driver_list, &block_cb_list);
++              flow_block_cb_incref(block_cb);
++
++              if (register_block) {
++                      flow_block_cb_add(block_cb, f);
++                      list_add_tail(&block_cb->driver_list, &block_cb_list);
++              }
+               return 0;
+       case FLOW_BLOCK_UNBIND:
+               block_cb = flow_block_cb_lookup(f->block, cb, dev);
+               if (!block_cb)
+                       return -ENOENT;
+-              if (flow_block_cb_decref(block_cb)) {
++              if (!flow_block_cb_decref(block_cb)) {
+                       flow_block_cb_remove(block_cb, f);
+                       list_del(&block_cb->driver_list);
+               }