Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: airoha: Validate egress gdm port in airoha_ppe_foe_entry_prepare()

Dev pointer in airoha_ppe_foe_entry_prepare routine is not strictly
a device allocated by airoha_eth driver since it is an egress device
and the flowtable can contain even wlan, pppoe or vlan devices. E.g:

flowtable ft {
hook ingress priority filter
devices = { eth1, lan1, lan2, lan3, lan4, wlan0 }
flags offload ^
|
"not allocated by airoha_eth" --
}

In this case airoha_get_dsa_port() will just return the original device
pointer and we can't assume netdev priv pointer points to an
airoha_gdm_port struct.
Fix the issue validating egress gdm port in airoha_ppe_foe_entry_prepare
routine before accessing net_device priv pointer.

Fixes: 00a7678310fe ("net: airoha: Introduce flowtable offload support")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20250401-airoha-validate-egress-gdm-port-v4-1-c7315d33ce10@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Lorenzo Bianconi and committed by
Jakub Kicinski
09bccf56 a58d8828

+22 -2
+13
drivers/net/ethernet/airoha/airoha_eth.c
··· 2454 2454 } 2455 2455 } 2456 2456 2457 + bool airoha_is_valid_gdm_port(struct airoha_eth *eth, 2458 + struct airoha_gdm_port *port) 2459 + { 2460 + int i; 2461 + 2462 + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { 2463 + if (eth->ports[i] == port) 2464 + return true; 2465 + } 2466 + 2467 + return false; 2468 + } 2469 + 2457 2470 static int airoha_alloc_gdm_port(struct airoha_eth *eth, 2458 2471 struct device_node *np, int index) 2459 2472 {
+3
drivers/net/ethernet/airoha/airoha_eth.h
··· 532 532 #define airoha_qdma_clear(qdma, offset, val) \ 533 533 airoha_rmw((qdma)->regs, (offset), (val), 0) 534 534 535 + bool airoha_is_valid_gdm_port(struct airoha_eth *eth, 536 + struct airoha_gdm_port *port); 537 + 535 538 void airoha_ppe_check_skb(struct airoha_ppe *ppe, u16 hash); 536 539 int airoha_ppe_setup_tc_block_cb(enum tc_setup_type type, void *type_data, 537 540 void *cb_priv);
+6 -2
drivers/net/ethernet/airoha/airoha_ppe.c
··· 197 197 #endif 198 198 } 199 199 200 - static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe, 200 + static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth, 201 + struct airoha_foe_entry *hwe, 201 202 struct net_device *dev, int type, 202 203 struct airoha_flow_data *data, 203 204 int l4proto) ··· 225 224 if (dev) { 226 225 struct airoha_gdm_port *port = netdev_priv(dev); 227 226 u8 pse_port; 227 + 228 + if (!airoha_is_valid_gdm_port(eth, port)) 229 + return -EINVAL; 228 230 229 231 if (dsa_port >= 0) 230 232 pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id; ··· 637 633 !is_valid_ether_addr(data.eth.h_dest)) 638 634 return -EINVAL; 639 635 640 - err = airoha_ppe_foe_entry_prepare(&hwe, odev, offload_type, 636 + err = airoha_ppe_foe_entry_prepare(eth, &hwe, odev, offload_type, 641 637 &data, l4proto); 642 638 if (err) 643 639 return err;