mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-30 21:44:27 -04:00 
			
		
		
		
	Fix corner cases in DSA offload Add refcounting fix for flow offload Fix VLAN untagging issue on MT7986 Signed-off-by: Felix Fietkau <nbd@nbd.name>
		
			
				
	
	
		
			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);
 |