mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-26 00:41:17 +00:00
53 lines
1.6 KiB
Diff
53 lines
1.6 KiB
Diff
|
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
|
||
|
@@ -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,16 +576,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);
|