| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/06/25 08:29 | flow | patch-triage |
1mArgs:null Results: {
"EnableConfigs": [
"NET_DSA",
"NET_DSA_LOOP",
"NET_DSA_TAG_AR9331",
"NET_DSA_TAG_BRCM",
"NET_DSA_TAG_BRCM_LEGACY",
"NET_DSA_TAG_BRCM_PREPEND",
"NET_DSA_TAG_HELLCREEK",
"NET_DSA_TAG_GSWIP",
"NET_DSA_TAG_DSA",
"NET_DSA_TAG_EDSA",
"NET_DSA_TAG_MTK",
"NET_DSA_TAG_MXL_862XX",
"NET_DSA_TAG_MXL_GSW1XX",
"NET_DSA_TAG_KSZ",
"NET_DSA_TAG_NETC",
"NET_DSA_TAG_OCELOT",
"NET_DSA_TAG_OCELOT_8021Q",
"NET_DSA_TAG_QCA",
"NET_DSA_TAG_RTL4_A",
"NET_DSA_TAG_RTL8_4",
"NET_DSA_TAG_RZN1_A5PSW",
"NET_DSA_TAG_LAN9303",
"NET_DSA_TAG_SJA1105",
"NET_DSA_TAG_TRAILER",
"NET_DSA_TAG_VSC73XX_8021Q",
"NET_DSA_TAG_XRS700X",
"NET_DSA_TAG_YT921X"
],
"FocusSymbols": [
"dsa_switch_rcv",
"dsa_user_xmit",
"ar9331_tag_rcv",
"brcm_tag_xmit_ll",
"brcm_tag_rcv_ll",
"dsa_rcv_ll",
"edsa_rcv",
"ksz_common_rcv",
"ocelot_rcv",
"qca_tag_rcv",
"sja1105_rcv",
"trailer_rcv"
],
"Reasoning": "The patch refactors skb memory management in the DSA (Distributed Switch Architecture) subsystem. It shifts the responsibility of freeing the skb on error paths from the core DSA functions (dsa_user_xmit, dsa_switch_rcv) to the individual tagger drivers. This is a functional change that could introduce memory leaks or double frees if any error path in a tagger driver is missed or mishandled. The code is reachable in a virtualized environment by using the dsa_loop mock-up switch driver and dynamically changing the tagging protocol via sysfs.",
"WorthFuzzing": true
} |
| 1/1 | 2026/06/25 08:29 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 674e8998377cc6f17cb29ffc6655f92fc39a19f7\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Thu Jun 25 08:29:04 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/net/dsa/tag.c b/net/dsa/tag.c\nindex 79ad105902d978..991732d6eae2c3 100644\n--- a/net/dsa/tag.c\n+++ b/net/dsa/tag.c\n@@ -79,15 +79,16 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,\n \t\tif (likely(skb-\u003edev)) {\n \t\t\tdsa_default_offload_fwd_mark(skb);\n \t\t\tnskb = skb;\n+\t\t} else {\n+\t\t\t/* Just drop the skb if we can't find the user */\n+\t\t\tkfree_skb(skb);\n \t\t}\n \t} else {\n \t\tnskb = cpu_dp-\u003ercv(skb, dev);\n \t}\n \n-\tif (!nskb) {\n-\t\tkfree_skb(skb);\n+\tif (!nskb)\n \t\treturn 0;\n-\t}\n \n \tskb = nskb;\n \tskb_push(skb, ETH_HLEN);\n@@ -107,11 +108,10 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,\n \n \tif (unlikely(cpu_dp-\u003eds-\u003euntag_bridge_pvid ||\n \t\t cpu_dp-\u003eds-\u003euntag_vlan_aware_bridge_pvid)) {\n+\t\t/* dsa_software_vlan_untag() drops skb on failure */\n \t\tnskb = dsa_software_vlan_untag(skb);\n-\t\tif (!nskb) {\n-\t\t\tkfree_skb(skb);\n+\t\tif (!nskb)\n \t\t\treturn 0;\n-\t\t}\n \t\tskb = nskb;\n \t}\n \ndiff --git a/net/dsa/tag_ar9331.c b/net/dsa/tag_ar9331.c\nindex cbb588ca73aaf5..2e2388143b0251 100644\n--- a/net/dsa/tag_ar9331.c\n+++ b/net/dsa/tag_ar9331.c\n@@ -51,8 +51,10 @@ static struct sk_buff *ar9331_tag_rcv(struct sk_buff *skb,\n \tu8 ver, port;\n \tu16 hdr;\n \n-\tif (unlikely(!pskb_may_pull(skb, AR9331_HDR_LEN)))\n+\tif (unlikely(!pskb_may_pull(skb, AR9331_HDR_LEN))) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \thdr = le16_to_cpu(*(__le16 *)skb_mac_header(skb));\n \n@@ -60,12 +62,14 @@ static struct sk_buff *ar9331_tag_rcv(struct sk_buff *skb,\n \tif (unlikely(ver != AR9331_HDR_VERSION)) {\n \t\tnetdev_warn_once(ndev, \"%s:%i wrong header version 0x%2x\\n\",\n \t\t\t\t __func__, __LINE__, hdr);\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \n \tif (unlikely(hdr \u0026 AR9331_HDR_FROM_CPU)) {\n \t\tnetdev_warn_once(ndev, \"%s:%i packet should not be from cpu 0x%2x\\n\",\n \t\t\t\t __func__, __LINE__, hdr);\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \n@@ -75,8 +79,10 @@ static struct sk_buff *ar9331_tag_rcv(struct sk_buff *skb,\n \tport = FIELD_GET(AR9331_HDR_PORT_NUM_MASK, hdr);\n \n \tskb-\u003edev = dsa_conduit_find_user(ndev, 0, port);\n-\tif (!skb-\u003edev)\n+\tif (!skb-\u003edev) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \treturn skb;\n }\ndiff --git a/net/dsa/tag_brcm.c b/net/dsa/tag_brcm.c\nindex cf94204390543f..411e3b57d16af5 100644\n--- a/net/dsa/tag_brcm.c\n+++ b/net/dsa/tag_brcm.c\n@@ -102,9 +102,9 @@ static struct sk_buff *brcm_tag_xmit_ll(struct sk_buff *skb,\n \t * (including FCS and tag) because the length verification is done after\n \t * the Broadcom tag is stripped off the ingress packet.\n \t *\n-\t * Let dsa_user_xmit() free the SKB\n+\t * Free the SKB on error.\n \t */\n-\tif (__skb_put_padto(skb, ETH_ZLEN + BRCM_TAG_LEN, false))\n+\tif (skb_put_padto(skb, ETH_ZLEN + BRCM_TAG_LEN))\n \t\treturn NULL;\n \n \tskb_push(skb, BRCM_TAG_LEN);\n@@ -151,27 +151,35 @@ static struct sk_buff *brcm_tag_rcv_ll(struct sk_buff *skb,\n \tint source_port;\n \tu8 *brcm_tag;\n \n-\tif (unlikely(!pskb_may_pull(skb, BRCM_TAG_LEN)))\n+\tif (unlikely(!pskb_may_pull(skb, BRCM_TAG_LEN))) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tbrcm_tag = skb-\u003edata - offset;\n \n \t/* The opcode should never be different than 0b000 */\n-\tif (unlikely((brcm_tag[0] \u003e\u003e BRCM_OPCODE_SHIFT) \u0026 BRCM_OPCODE_MASK))\n+\tif (unlikely((brcm_tag[0] \u003e\u003e BRCM_OPCODE_SHIFT) \u0026 BRCM_OPCODE_MASK)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* We should never see a reserved reason code without knowing how to\n \t * handle it\n \t */\n-\tif (unlikely(brcm_tag[2] \u0026 BRCM_EG_RC_RSVD))\n+\tif (unlikely(brcm_tag[2] \u0026 BRCM_EG_RC_RSVD)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* Locate which port this is coming from */\n \tsource_port = brcm_tag[3] \u0026 BRCM_EG_PID_MASK;\n \n \tskb-\u003edev = dsa_conduit_find_user(dev, 0, source_port);\n-\tif (!skb-\u003edev)\n+\tif (!skb-\u003edev) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* Remove Broadcom tag and update checksum */\n \tskb_pull_rcsum(skb, BRCM_TAG_LEN);\n@@ -228,8 +236,10 @@ static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,\n \t__be16 *proto;\n \tu8 *brcm_tag;\n \n-\tif (unlikely(!pskb_may_pull(skb, BRCM_LEG_TAG_LEN + VLAN_HLEN)))\n+\tif (unlikely(!pskb_may_pull(skb, BRCM_LEG_TAG_LEN + VLAN_HLEN))) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tbrcm_tag = dsa_etype_header_pos_rx(skb);\n \tproto = (__be16 *)(brcm_tag + BRCM_LEG_TAG_LEN);\n@@ -237,8 +247,10 @@ static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,\n \tsource_port = brcm_tag[5] \u0026 BRCM_LEG_PORT_ID;\n \n \tskb-\u003edev = dsa_conduit_find_user(dev, 0, source_port);\n-\tif (!skb-\u003edev)\n+\tif (!skb-\u003edev) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* The internal switch in BCM63XX SoCs always tags on egress on the CPU\n \t * port. We use VID 0 internally for untagged traffic, so strip the tag\n@@ -273,10 +285,8 @@ static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb,\n \t * need to make sure that packets are at least 70 bytes\n \t * (including FCS and tag) because the length verification is done after\n \t * the Broadcom tag is stripped off the ingress packet.\n-\t *\n-\t * Let dsa_user_xmit() free the SKB\n \t */\n-\tif (__skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN, false))\n+\tif (skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN))\n \t\treturn NULL;\n \n \tskb_push(skb, BRCM_LEG_TAG_LEN);\n@@ -325,10 +335,8 @@ static struct sk_buff *brcm_leg_fcs_tag_xmit(struct sk_buff *skb,\n \t * need to make sure that packets are at least 70 bytes (including FCS\n \t * and tag) because the length verification is done after the Broadcom\n \t * tag is stripped off the ingress packet.\n-\t *\n-\t * Let dsa_user_xmit() free the SKB.\n \t */\n-\tif (__skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN, false))\n+\tif (skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN))\n \t\treturn NULL;\n \n \tfcs_len = skb-\u003elen;\n@@ -351,8 +359,9 @@ static struct sk_buff *brcm_leg_fcs_tag_xmit(struct sk_buff *skb,\n \tbrcm_tag[5] = dp-\u003eindex \u0026 BRCM_LEG_PORT_ID;\n \n \t/* Original FCS value */\n-\tif (__skb_pad(skb, ETH_FCS_LEN, false))\n+\tif (skb_pad(skb, ETH_FCS_LEN))\n \t\treturn NULL;\n+\n \tskb_put_data(skb, \u0026fcs_val, ETH_FCS_LEN);\n \n \treturn skb;\ndiff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c\nindex 2a2c4fb61a65c6..d5ffee35fbb53b 100644\n--- a/net/dsa/tag_dsa.c\n+++ b/net/dsa/tag_dsa.c\n@@ -224,6 +224,7 @@ static struct sk_buff *dsa_rcv_ll(struct sk_buff *skb, struct net_device *dev,\n \t\t\t/* Remote management is not implemented yet,\n \t\t\t * drop.\n \t\t\t */\n+\t\t\tkfree_skb(skb);\n \t\t\treturn NULL;\n \t\tcase DSA_CODE_ARP_MIRROR:\n \t\tcase DSA_CODE_POLICY_MIRROR:\n@@ -244,12 +245,14 @@ static struct sk_buff *dsa_rcv_ll(struct sk_buff *skb, struct net_device *dev,\n \t\t\t/* Reserved code, this could be anything. Drop\n \t\t\t * seems like the safest option.\n \t\t\t */\n+\t\t\tkfree_skb(skb);\n \t\t\treturn NULL;\n \t\t}\n \n \t\tbreak;\n \n \tdefault:\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \n@@ -271,8 +274,10 @@ static struct sk_buff *dsa_rcv_ll(struct sk_buff *skb, struct net_device *dev,\n \t\t\t\t\t\t source_port);\n \t}\n \n-\tif (!skb-\u003edev)\n+\tif (!skb-\u003edev) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* When using LAG offload, skb-\u003edev is not a DSA user interface,\n \t * so we cannot call dsa_default_offload_fwd_mark and we need to\n@@ -335,8 +340,10 @@ static struct sk_buff *dsa_xmit(struct sk_buff *skb, struct net_device *dev)\n \n static struct sk_buff *dsa_rcv(struct sk_buff *skb, struct net_device *dev)\n {\n-\tif (unlikely(!pskb_may_pull(skb, DSA_HLEN)))\n+\tif (unlikely(!pskb_may_pull(skb, DSA_HLEN))) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \treturn dsa_rcv_ll(skb, dev, 0);\n }\n@@ -375,8 +382,10 @@ static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev)\n \n static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev)\n {\n-\tif (unlikely(!pskb_may_pull(skb, EDSA_HLEN)))\n+\tif (unlikely(!pskb_may_pull(skb, EDSA_HLEN))) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tskb_pull_rcsum(skb, EDSA_HLEN - DSA_HLEN);\n \ndiff --git a/net/dsa/tag_gswip.c b/net/dsa/tag_gswip.c\nindex 5fa436121087b4..5c407d448c9fee 100644\n--- a/net/dsa/tag_gswip.c\n+++ b/net/dsa/tag_gswip.c\n@@ -80,16 +80,20 @@ static struct sk_buff *gswip_tag_rcv(struct sk_buff *skb,\n \tint port;\n \tu8 *gswip_tag;\n \n-\tif (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN)))\n+\tif (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN))) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tgswip_tag = skb-\u003edata - ETH_HLEN;\n \n \t/* Get source port information */\n \tport = (gswip_tag[7] \u0026 GSWIP_RX_SPPID_MASK) \u003e\u003e GSWIP_RX_SPPID_SHIFT;\n \tskb-\u003edev = dsa_conduit_find_user(dev, 0, port);\n-\tif (!skb-\u003edev)\n+\tif (!skb-\u003edev) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* remove GSWIP tag */\n \tskb_pull_rcsum(skb, GSWIP_RX_HEADER_LEN);\ndiff --git a/net/dsa/tag_hellcreek.c b/net/dsa/tag_hellcreek.c\nindex 544ab15685a2b8..dd9f328f318210 100644\n--- a/net/dsa/tag_hellcreek.c\n+++ b/net/dsa/tag_hellcreek.c\n@@ -27,8 +27,10 @@ static struct sk_buff *hellcreek_xmit(struct sk_buff *skb,\n \t * checksums after the switch strips the tag.\n \t */\n \tif (skb-\u003eip_summed == CHECKSUM_PARTIAL \u0026\u0026\n-\t skb_checksum_help(skb))\n+\t skb_checksum_help(skb)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* Tag encoding */\n \ttag = skb_put(skb, HELLCREEK_TAG_LEN);\n@@ -47,11 +49,14 @@ static struct sk_buff *hellcreek_rcv(struct sk_buff *skb,\n \tskb-\u003edev = dsa_conduit_find_user(dev, 0, port);\n \tif (!skb-\u003edev) {\n \t\tnetdev_warn_once(dev, \"Failed to get source port: %d\\n\", port);\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \n-\tif (pskb_trim_rcsum(skb, skb-\u003elen - HELLCREEK_TAG_LEN))\n+\tif (pskb_trim_rcsum(skb, skb-\u003elen - HELLCREEK_TAG_LEN)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tdsa_default_offload_fwd_mark(skb);\n \ndiff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c\nindex d2475c3bbb7d22..67fa89f102e070 100644\n--- a/net/dsa/tag_ksz.c\n+++ b/net/dsa/tag_ksz.c\n@@ -88,11 +88,15 @@ static struct sk_buff *ksz_common_rcv(struct sk_buff *skb,\n \t\t\t\t unsigned int port, unsigned int len)\n {\n \tskb-\u003edev = dsa_conduit_find_user(dev, 0, port);\n-\tif (!skb-\u003edev)\n+\tif (!skb-\u003edev) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n-\tif (pskb_trim_rcsum(skb, skb-\u003elen - len))\n+\tif (pskb_trim_rcsum(skb, skb-\u003elen - len)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tdsa_default_offload_fwd_mark(skb);\n \n@@ -123,8 +127,10 @@ static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device *dev)\n \tstruct ethhdr *hdr;\n \tu8 *tag;\n \n-\tif (skb-\u003eip_summed == CHECKSUM_PARTIAL \u0026\u0026 skb_checksum_help(skb))\n+\tif (skb-\u003eip_summed == CHECKSUM_PARTIAL \u0026\u0026 skb_checksum_help(skb)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* Tag encoding */\n \ttag = skb_put(skb, KSZ_INGRESS_TAG_LEN);\n@@ -141,8 +147,10 @@ static struct sk_buff *ksz8795_rcv(struct sk_buff *skb, struct net_device *dev)\n {\n \tu8 *tag;\n \n-\tif (skb_linearize(skb))\n+\tif (skb_linearize(skb)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \ttag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;\n \n@@ -255,22 +263,24 @@ static struct sk_buff *ksz_defer_xmit(struct dsa_port *dp, struct sk_buff *skb)\n \txmit_work_fn = tagger_data-\u003exmit_work_fn;\n \txmit_worker = priv-\u003exmit_worker;\n \n-\tif (!xmit_work_fn || !xmit_worker)\n+\tif (!xmit_work_fn || !xmit_worker) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \txmit_work = kzalloc_obj(*xmit_work, GFP_ATOMIC);\n-\tif (!xmit_work)\n+\tif (!xmit_work) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tkthread_init_work(\u0026xmit_work-\u003ework, xmit_work_fn);\n-\t/* Increase refcount so the kfree_skb in dsa_user_xmit\n-\t * won't really free the packet.\n-\t */\n \txmit_work-\u003edp = dp;\n \txmit_work-\u003eskb = skb_get(skb);\n \n \tkthread_queue_work(xmit_worker, \u0026xmit_work-\u003ework);\n \n+\tkfree_skb(skb);\n \treturn NULL;\n }\n \n@@ -284,8 +294,10 @@ static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,\n \t__be16 *tag;\n \tu16 val;\n \n-\tif (skb-\u003eip_summed == CHECKSUM_PARTIAL \u0026\u0026 skb_checksum_help(skb))\n+\tif (skb-\u003eip_summed == CHECKSUM_PARTIAL \u0026\u0026 skb_checksum_help(skb)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* Tag encoding */\n \tksz_xmit_timestamp(dp, skb);\n@@ -310,8 +322,10 @@ static struct sk_buff *ksz9477_rcv(struct sk_buff *skb, struct net_device *dev)\n \tunsigned int port;\n \tu8 *tag;\n \n-\tif (skb_linearize(skb))\n+\tif (skb_linearize(skb)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* Tag decoding */\n \ttag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;\n@@ -352,8 +366,10 @@ static struct sk_buff *ksz9893_xmit(struct sk_buff *skb,\n \tstruct ethhdr *hdr;\n \tu8 *tag;\n \n-\tif (skb-\u003eip_summed == CHECKSUM_PARTIAL \u0026\u0026 skb_checksum_help(skb))\n+\tif (skb-\u003eip_summed == CHECKSUM_PARTIAL \u0026\u0026 skb_checksum_help(skb)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* Tag encoding */\n \tksz_xmit_timestamp(dp, skb);\n@@ -418,8 +434,10 @@ static struct sk_buff *lan937x_xmit(struct sk_buff *skb,\n \t__be16 *tag;\n \tu16 val;\n \n-\tif (skb-\u003eip_summed == CHECKSUM_PARTIAL \u0026\u0026 skb_checksum_help(skb))\n+\tif (skb-\u003eip_summed == CHECKSUM_PARTIAL \u0026\u0026 skb_checksum_help(skb)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tksz_xmit_timestamp(dp, skb);\n \ndiff --git a/net/dsa/tag_lan9303.c b/net/dsa/tag_lan9303.c\nindex 258e5d7dc5ef84..d1194696499ab8 100644\n--- a/net/dsa/tag_lan9303.c\n+++ b/net/dsa/tag_lan9303.c\n@@ -85,6 +85,7 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev)\n \tif (unlikely(!pskb_may_pull(skb, LAN9303_TAG_LEN))) {\n \t\tdev_warn_ratelimited(\u0026dev-\u003edev,\n \t\t\t\t \"Dropping packet, cannot pull\\n\");\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \n@@ -102,6 +103,7 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev)\n \tskb-\u003edev = dsa_conduit_find_user(dev, 0, source_port);\n \tif (!skb-\u003edev) {\n \t\tdev_warn_ratelimited(\u0026dev-\u003edev, \"Dropping packet due to invalid source port\\n\");\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \ndiff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c\nindex dea3eecaf093df..c7dc7731675ec0 100644\n--- a/net/dsa/tag_mtk.c\n+++ b/net/dsa/tag_mtk.c\n@@ -72,8 +72,10 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev)\n \tint port;\n \t__be16 *phdr;\n \n-\tif (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN)))\n+\tif (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN))) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tphdr = dsa_etype_header_pos_rx(skb);\n \thdr = ntohs(*phdr);\n@@ -87,8 +89,10 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev)\n \tport = (hdr \u0026 MTK_HDR_RECV_SOURCE_PORT_MASK);\n \n \tskb-\u003edev = dsa_conduit_find_user(dev, 0, port);\n-\tif (!skb-\u003edev)\n+\tif (!skb-\u003edev) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tdsa_default_offload_fwd_mark(skb);\n \ndiff --git a/net/dsa/tag_mxl-gsw1xx.c b/net/dsa/tag_mxl-gsw1xx.c\nindex 60f7c445e65610..4b1b6ef9419634 100644\n--- a/net/dsa/tag_mxl-gsw1xx.c\n+++ b/net/dsa/tag_mxl-gsw1xx.c\n@@ -73,6 +73,7 @@ static struct sk_buff *gsw1xx_tag_rcv(struct sk_buff *skb,\n \n \tif (unlikely(!pskb_may_pull(skb, GSW1XX_HEADER_LEN))) {\n \t\tdev_warn_ratelimited(\u0026dev-\u003edev, \"Dropping packet, cannot pull SKB\\n\");\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \n@@ -81,6 +82,7 @@ static struct sk_buff *gsw1xx_tag_rcv(struct sk_buff *skb,\n \tif (unlikely(ntohs(gsw1xx_tag[0]) != ETH_P_MXLGSW)) {\n \t\tdev_warn_ratelimited(\u0026dev-\u003edev, \"Dropping packet due to invalid special tag\\n\");\n \t\tdev_warn_ratelimited(\u0026dev-\u003edev, \"Tag: %8ph\\n\", gsw1xx_tag);\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \n@@ -90,6 +92,7 @@ static struct sk_buff *gsw1xx_tag_rcv(struct sk_buff *skb,\n \tif (!skb-\u003edev) {\n \t\tdev_warn_ratelimited(\u0026dev-\u003edev, \"Dropping packet due to invalid source port\\n\");\n \t\tdev_warn_ratelimited(\u0026dev-\u003edev, \"Tag: %8ph\\n\", gsw1xx_tag);\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \ndiff --git a/net/dsa/tag_mxl862xx.c b/net/dsa/tag_mxl862xx.c\nindex 8daefeb8d49dfa..87b80ddf094632 100644\n--- a/net/dsa/tag_mxl862xx.c\n+++ b/net/dsa/tag_mxl862xx.c\n@@ -64,6 +64,7 @@ static struct sk_buff *mxl862_tag_rcv(struct sk_buff *skb,\n \n \tif (unlikely(!pskb_may_pull(skb, MXL862_HEADER_LEN))) {\n \t\tdev_warn_ratelimited(\u0026dev-\u003edev, \"Cannot pull SKB, packet dropped\\n\");\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \n@@ -73,6 +74,7 @@ static struct sk_buff *mxl862_tag_rcv(struct sk_buff *skb,\n \t\tdev_warn_ratelimited(\u0026dev-\u003edev,\n \t\t\t\t \"Invalid special tag marker, packet dropped, tag: %8ph\\n\",\n \t\t\t\t mxl862_tag);\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \n@@ -83,6 +85,7 @@ static struct sk_buff *mxl862_tag_rcv(struct sk_buff *skb,\n \t\tdev_warn_ratelimited(\u0026dev-\u003edev,\n \t\t\t\t \"Invalid source port, packet dropped, tag: %8ph\\n\",\n \t\t\t\t mxl862_tag);\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \ndiff --git a/net/dsa/tag_netc.c b/net/dsa/tag_netc.c\nindex ccedfe3a80b64d..df72a61796ad5f 100644\n--- a/net/dsa/tag_netc.c\n+++ b/net/dsa/tag_netc.c\n@@ -131,14 +131,13 @@ static struct sk_buff *netc_rcv(struct sk_buff *skb,\n \tint type, subtype;\n \n \tif (unlikely(!pskb_may_pull(skb, NETC_TAG_MAX_LEN)))\n-\t\treturn NULL;\n+\t\tgoto err_free_skb;\n \n \ttag_cmn = dsa_etype_header_pos_rx(skb);\n \tif (ntohs(tag_cmn-\u003etpid) != ETH_P_NXP_NETC) {\n \t\tdev_warn_ratelimited(\u0026ndev-\u003edev, \"Unknown TPID 0x%04x\\n\",\n \t\t\t\t ntohs(tag_cmn-\u003etpid));\n-\n-\t\treturn NULL;\n+\t\tgoto err_free_skb;\n \t}\n \n \tif (tag_cmn-\u003eqos \u0026 NETC_TAG_QV)\n@@ -149,14 +148,13 @@ static struct sk_buff *netc_rcv(struct sk_buff *skb,\n \tif (!sw_id) {\n \t\tdev_warn_ratelimited(\u0026ndev-\u003edev,\n \t\t\t\t \"VEPA switch ID is not supported yet\\n\");\n-\n-\t\treturn NULL;\n+\t\tgoto err_free_skb;\n \t}\n \n \tport = FIELD_GET(NETC_TAG_PORT, tag_cmn-\u003eswitch_port);\n \tskb-\u003edev = dsa_conduit_find_user(ndev, sw_id, port);\n \tif (!skb-\u003edev)\n-\t\treturn NULL;\n+\t\tgoto err_free_skb;\n \n \ttype = FIELD_GET(NETC_TAG_TYPE, tag_cmn-\u003etype);\n \tsubtype = FIELD_GET(NETC_TAG_SUBTYPE, tag_cmn-\u003etype);\n@@ -165,11 +163,11 @@ static struct sk_buff *netc_rcv(struct sk_buff *skb,\n \t} else if (type == NETC_TAG_TO_HOST) {\n \t\t/* Currently only subtype0 supported */\n \t\tif (subtype != NETC_TAG_TH_SUBTYPE0)\n-\t\t\treturn NULL;\n+\t\t\tgoto err_free_skb;\n \t} else {\n \t\tdev_warn_ratelimited(\u0026ndev-\u003edev,\n \t\t\t\t \"Unexpected tag type %d\\n\", type);\n-\t\treturn NULL;\n+\t\tgoto err_free_skb;\n \t}\n \n \t/* Remove Switch tag from the frame */\n@@ -178,6 +176,10 @@ static struct sk_buff *netc_rcv(struct sk_buff *skb,\n \tdsa_strip_etype_header(skb, tag_len);\n \n \treturn skb;\n+\n+err_free_skb:\n+\tkfree_skb(skb);\n+\treturn NULL;\n }\n \n static void netc_flow_dissect(const struct sk_buff *skb, __be16 *proto,\ndiff --git a/net/dsa/tag_ocelot.c b/net/dsa/tag_ocelot.c\nindex 3405def79c2def..d208c7322cd626 100644\n--- a/net/dsa/tag_ocelot.c\n+++ b/net/dsa/tag_ocelot.c\n@@ -107,14 +107,16 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,\n \tocelot_xfh_get_rew_val(extraction, \u0026rew_val);\n \n \tskb-\u003edev = dsa_conduit_find_user(netdev, 0, src_port);\n-\tif (!skb-\u003edev)\n+\tif (!skb-\u003edev) {\n \t\t/* The switch will reflect back some frames sent through\n \t\t * sockets opened on the bare DSA conduit. These will come back\n \t\t * with src_port equal to the index of the CPU port, for which\n \t\t * there is no user registered. So don't print any error\n \t\t * message here (ignore and drop those frames).\n \t\t */\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tdsa_default_offload_fwd_mark(skb);\n \tskb-\u003epriority = qos_class;\ndiff --git a/net/dsa/tag_ocelot_8021q.c b/net/dsa/tag_ocelot_8021q.c\nindex e89d9254e90a3a..f50f1cd83f161c 100644\n--- a/net/dsa/tag_ocelot_8021q.c\n+++ b/net/dsa/tag_ocelot_8021q.c\n@@ -33,30 +33,34 @@ static struct sk_buff *ocelot_defer_xmit(struct dsa_port *dp,\n \txmit_work_fn = data-\u003exmit_work_fn;\n \txmit_worker = priv-\u003exmit_worker;\n \n-\tif (!xmit_work_fn || !xmit_worker)\n+\tif (!xmit_work_fn || !xmit_worker) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* PTP over IP packets need UDP checksumming. We may have inherited\n \t * NETIF_F_HW_CSUM from the DSA conduit, but these packets are not sent\n \t * through the DSA conduit, so calculate the checksum here.\n \t */\n-\tif (skb-\u003eip_summed == CHECKSUM_PARTIAL \u0026\u0026 skb_checksum_help(skb))\n+\tif (skb-\u003eip_summed == CHECKSUM_PARTIAL \u0026\u0026 skb_checksum_help(skb)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \txmit_work = kzalloc_obj(*xmit_work, GFP_ATOMIC);\n-\tif (!xmit_work)\n+\tif (!xmit_work) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* Calls felix_port_deferred_xmit in felix.c */\n \tkthread_init_work(\u0026xmit_work-\u003ework, xmit_work_fn);\n-\t/* Increase refcount so the kfree_skb in dsa_user_xmit\n-\t * won't really free the packet.\n-\t */\n \txmit_work-\u003edp = dp;\n \txmit_work-\u003eskb = skb_get(skb);\n \n \tkthread_queue_work(xmit_worker, \u0026xmit_work-\u003ework);\n \n+\tkfree_skb(skb);\n \treturn NULL;\n }\n \n@@ -84,8 +88,10 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,\n \tdsa_8021q_rcv(skb, \u0026src_port, \u0026switch_id, NULL, NULL);\n \n \tskb-\u003edev = dsa_conduit_find_user(netdev, switch_id, src_port);\n-\tif (!skb-\u003edev)\n+\tif (!skb-\u003edev) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tdsa_default_offload_fwd_mark(skb);\n \ndiff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c\nindex 9e3b429e8b3625..510792fbfa92dd 100644\n--- a/net/dsa/tag_qca.c\n+++ b/net/dsa/tag_qca.c\n@@ -46,16 +46,20 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev)\n \n \ttagger_data = ds-\u003etagger_data;\n \n-\tif (unlikely(!pskb_may_pull(skb, QCA_HDR_LEN)))\n+\tif (unlikely(!pskb_may_pull(skb, QCA_HDR_LEN))) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tphdr = dsa_etype_header_pos_rx(skb);\n \thdr = ntohs(*phdr);\n \n \t/* Make sure the version is correct */\n \tver = FIELD_GET(QCA_HDR_RECV_VERSION, hdr);\n-\tif (unlikely(ver != QCA_HDR_VERSION))\n+\tif (unlikely(ver != QCA_HDR_VERSION)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* Get pk type */\n \tpk_type = FIELD_GET(QCA_HDR_RECV_TYPE, hdr);\n@@ -64,6 +68,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev)\n \tif (pk_type == QCA_HDR_RECV_TYPE_RW_REG_ACK) {\n \t\tif (likely(tagger_data-\u003erw_reg_ack_handler))\n \t\t\ttagger_data-\u003erw_reg_ack_handler(ds, skb);\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \n@@ -71,6 +76,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev)\n \tif (pk_type == QCA_HDR_RECV_TYPE_MIB) {\n \t\tif (likely(tagger_data-\u003emib_autocast_handler))\n \t\t\ttagger_data-\u003emib_autocast_handler(ds, skb);\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \n@@ -78,8 +84,10 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev)\n \tport = FIELD_GET(QCA_HDR_RECV_SOURCE_PORT, hdr);\n \n \tskb-\u003edev = dsa_conduit_find_user(dev, 0, port);\n-\tif (!skb-\u003edev)\n+\tif (!skb-\u003edev) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* Remove QCA tag and recalculate checksum */\n \tskb_pull_rcsum(skb, QCA_HDR_LEN);\ndiff --git a/net/dsa/tag_rtl4_a.c b/net/dsa/tag_rtl4_a.c\nindex 3cc63eacfa0352..590ea3b921c9d9 100644\n--- a/net/dsa/tag_rtl4_a.c\n+++ b/net/dsa/tag_rtl4_a.c\n@@ -41,7 +41,7 @@ static struct sk_buff *rtl4a_tag_xmit(struct sk_buff *skb,\n \tu16 out;\n \n \t/* Pad out to at least 60 bytes */\n-\tif (unlikely(__skb_put_padto(skb, ETH_ZLEN, false)))\n+\tif (unlikely(eth_skb_pad(skb)))\n \t\treturn NULL;\n \n \tnetdev_dbg(dev, \"add realtek tag to package to port %d\\n\",\n@@ -75,8 +75,10 @@ static struct sk_buff *rtl4a_tag_rcv(struct sk_buff *skb,\n \tu8 prot;\n \tu8 port;\n \n-\tif (unlikely(!pskb_may_pull(skb, RTL4_A_HDR_LEN)))\n+\tif (unlikely(!pskb_may_pull(skb, RTL4_A_HDR_LEN))) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \ttag = dsa_etype_header_pos_rx(skb);\n \tp = (__be16 *)tag;\n@@ -92,6 +94,7 @@ static struct sk_buff *rtl4a_tag_rcv(struct sk_buff *skb,\n \tprot = (protport \u003e\u003e RTL4_A_PROTOCOL_SHIFT) \u0026 0x0f;\n \tif (prot != RTL4_A_PROTOCOL_RTL8366RB) {\n \t\tnetdev_err(dev, \"unknown realtek protocol 0x%01x\\n\", prot);\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \tport = protport \u0026 0xff;\n@@ -99,6 +102,7 @@ static struct sk_buff *rtl4a_tag_rcv(struct sk_buff *skb,\n \tskb-\u003edev = dsa_conduit_find_user(dev, 0, port);\n \tif (!skb-\u003edev) {\n \t\tnetdev_dbg(dev, \"could not find user for port %d\\n\", port);\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \ndiff --git a/net/dsa/tag_rtl8_4.c b/net/dsa/tag_rtl8_4.c\nindex 852c6b88079a13..4da3beebef75e2 100644\n--- a/net/dsa/tag_rtl8_4.c\n+++ b/net/dsa/tag_rtl8_4.c\n@@ -143,8 +143,10 @@ static struct sk_buff *rtl8_4t_tag_xmit(struct sk_buff *skb,\n \t/* Calculate the checksum here if not done yet as trailing tags will\n \t * break either software or hardware based checksum\n \t */\n-\tif (skb-\u003eip_summed == CHECKSUM_PARTIAL \u0026\u0026 skb_checksum_help(skb))\n+\tif (skb-\u003eip_summed == CHECKSUM_PARTIAL \u0026\u0026 skb_checksum_help(skb)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \trtl8_4_write_tag(skb, dev, skb_put(skb, RTL8_4_TAG_LEN));\n \n@@ -201,11 +203,15 @@ static int rtl8_4_read_tag(struct sk_buff *skb, struct net_device *dev,\n static struct sk_buff *rtl8_4_tag_rcv(struct sk_buff *skb,\n \t\t\t\t struct net_device *dev)\n {\n-\tif (unlikely(!pskb_may_pull(skb, RTL8_4_TAG_LEN)))\n+\tif (unlikely(!pskb_may_pull(skb, RTL8_4_TAG_LEN))) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n-\tif (unlikely(rtl8_4_read_tag(skb, dev, dsa_etype_header_pos_rx(skb))))\n+\tif (unlikely(rtl8_4_read_tag(skb, dev, dsa_etype_header_pos_rx(skb)))) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* Remove tag and recalculate checksum */\n \tskb_pull_rcsum(skb, RTL8_4_TAG_LEN);\n@@ -218,14 +224,20 @@ static struct sk_buff *rtl8_4_tag_rcv(struct sk_buff *skb,\n static struct sk_buff *rtl8_4t_tag_rcv(struct sk_buff *skb,\n \t\t\t\t struct net_device *dev)\n {\n-\tif (skb_linearize(skb))\n+\tif (skb_linearize(skb)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n-\tif (unlikely(rtl8_4_read_tag(skb, dev, skb_tail_pointer(skb) - RTL8_4_TAG_LEN)))\n+\tif (unlikely(rtl8_4_read_tag(skb, dev, skb_tail_pointer(skb) - RTL8_4_TAG_LEN))) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n-\tif (pskb_trim_rcsum(skb, skb-\u003elen - RTL8_4_TAG_LEN))\n+\tif (pskb_trim_rcsum(skb, skb-\u003elen - RTL8_4_TAG_LEN)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \treturn skb;\n }\ndiff --git a/net/dsa/tag_rzn1_a5psw.c b/net/dsa/tag_rzn1_a5psw.c\nindex 10994b3470f67a..734910156dc333 100644\n--- a/net/dsa/tag_rzn1_a5psw.c\n+++ b/net/dsa/tag_rzn1_a5psw.c\n@@ -48,7 +48,7 @@ static struct sk_buff *a5psw_tag_xmit(struct sk_buff *skb, struct net_device *de\n \t * least 60 bytes otherwise they will be discarded when they enter the\n \t * switch port logic.\n \t */\n-\tif (__skb_put_padto(skb, ETH_ZLEN, false))\n+\tif (eth_skb_pad(skb))\n \t\treturn NULL;\n \n \t/* provide 'A5PSW_TAG_LEN' bytes additional space */\n@@ -77,6 +77,7 @@ static struct sk_buff *a5psw_tag_rcv(struct sk_buff *skb,\n \tif (unlikely(!pskb_may_pull(skb, A5PSW_TAG_LEN))) {\n \t\tdev_warn_ratelimited(\u0026dev-\u003edev,\n \t\t\t\t \"Dropping packet, cannot pull\\n\");\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \n@@ -84,14 +85,17 @@ static struct sk_buff *a5psw_tag_rcv(struct sk_buff *skb,\n \n \tif (tag-\u003ectrl_tag != htons(ETH_P_DSA_A5PSW)) {\n \t\tdev_warn_ratelimited(\u0026dev-\u003edev, \"Dropping packet due to invalid TAG marker\\n\");\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \n \tport = FIELD_GET(A5PSW_CTRL_DATA_PORT, ntohs(tag-\u003ectrl_data));\n \n \tskb-\u003edev = dsa_conduit_find_user(dev, 0, port);\n-\tif (!skb-\u003edev)\n+\tif (!skb-\u003edev) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tskb_pull_rcsum(skb, A5PSW_TAG_LEN);\n \tdsa_strip_etype_header(skb, A5PSW_TAG_LEN);\ndiff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c\nindex de6d4ce8668be1..bfe1f746f55be5 100644\n--- a/net/dsa/tag_sja1105.c\n+++ b/net/dsa/tag_sja1105.c\n@@ -149,19 +149,20 @@ static struct sk_buff *sja1105_defer_xmit(struct dsa_port *dp,\n \txmit_work_fn = tagger_data-\u003exmit_work_fn;\n \txmit_worker = priv-\u003exmit_worker;\n \n-\tif (!xmit_work_fn || !xmit_worker)\n+\tif (!xmit_work_fn || !xmit_worker) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \txmit_work = kzalloc_obj(*xmit_work, GFP_ATOMIC);\n-\tif (!xmit_work)\n+\tif (!xmit_work) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tkthread_init_work(\u0026xmit_work-\u003ework, xmit_work_fn);\n-\t/* Increase refcount so the kfree_skb in dsa_user_xmit\n-\t * won't really free the packet.\n-\t */\n \txmit_work-\u003edp = dp;\n-\txmit_work-\u003eskb = skb_get(skb);\n+\txmit_work-\u003eskb = skb;\n \n \tkthread_queue_work(xmit_worker, \u0026xmit_work-\u003ework);\n \n@@ -401,10 +402,7 @@ static struct sk_buff\n \t\t\tkfree_skb(priv-\u003estampable_skb);\n \t\t}\n \n-\t\t/* Hold a reference to avoid dsa_switch_rcv\n-\t\t * from freeing the skb.\n-\t\t */\n-\t\tpriv-\u003estampable_skb = skb_get(skb);\n+\t\tpriv-\u003estampable_skb = skb;\n \t\tspin_unlock(\u0026priv-\u003emeta_lock);\n \n \t\t/* Tell DSA we got nothing */\n@@ -436,6 +434,7 @@ static struct sk_buff\n \t\t\tdev_err_ratelimited(ds-\u003edev,\n \t\t\t\t\t \"Unexpected meta frame\\n\");\n \t\t\tspin_unlock(\u0026priv-\u003emeta_lock);\n+\t\t\tkfree_skb(skb);\n \t\t\treturn NULL;\n \t\t}\n \n@@ -443,6 +442,7 @@ static struct sk_buff\n \t\t\tdev_err_ratelimited(ds-\u003edev,\n \t\t\t\t\t \"Meta frame on wrong port\\n\");\n \t\t\tspin_unlock(\u0026priv-\u003emeta_lock);\n+\t\t\tkfree_skb(skb);\n \t\t\treturn NULL;\n \t\t}\n \n@@ -501,18 +501,21 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb,\n \t/* Normal data plane traffic and link-local frames are tagged with\n \t * a tag_8021q VLAN which we have to strip\n \t */\n-\tif (sja1105_skb_has_tag_8021q(skb))\n+\tif (sja1105_skb_has_tag_8021q(skb)) {\n \t\tdsa_8021q_rcv(skb, \u0026source_port, \u0026switch_id, \u0026vbid, \u0026vid);\n-\telse if (source_port == -1 \u0026\u0026 switch_id == -1)\n+\t} else if (source_port == -1 \u0026\u0026 switch_id == -1) {\n \t\t/* Packets with no source information have no chance of\n \t\t * getting accepted, drop them straight away.\n \t\t */\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tskb-\u003edev = dsa_tag_8021q_find_user(netdev, source_port, switch_id,\n \t\t\t\t\t vid, vbid);\n \tif (!skb-\u003edev) {\n \t\tnetdev_warn(netdev, \"Couldn't decode source port\\n\");\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \n@@ -539,12 +542,15 @@ static struct sk_buff *sja1110_rcv_meta(struct sk_buff *skb, u16 rx_header)\n \tif (!ds) {\n \t\tnet_err_ratelimited(\"%s: cannot find switch id %d\\n\",\n \t\t\t\t conduit-\u003ename, switch_id);\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \n \ttagger_data = sja1105_tagger_data(ds);\n-\tif (!tagger_data-\u003emeta_tstamp_handler)\n+\tif (!tagger_data-\u003emeta_tstamp_handler) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tfor (i = 0; i \u003c= n_ts; i++) {\n \t\tu8 ts_id, source_port, dir;\n@@ -562,6 +568,7 @@ static struct sk_buff *sja1110_rcv_meta(struct sk_buff *skb, u16 rx_header)\n \t}\n \n \t/* Discard the meta frame, we've consumed the timestamps it contained */\n+\tkfree_skb(skb);\n \treturn NULL;\n }\n \n@@ -572,8 +579,10 @@ static struct sk_buff *sja1110_rcv_inband_control_extension(struct sk_buff *skb,\n {\n \tu16 rx_header;\n \n-\tif (unlikely(!pskb_may_pull(skb, SJA1110_HEADER_LEN)))\n+\tif (unlikely(!pskb_may_pull(skb, SJA1110_HEADER_LEN))) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* skb-\u003edata points to skb_mac_header(skb) + ETH_HLEN, which is exactly\n \t * what we need because the caller has checked the EtherType (which is\n@@ -609,8 +618,10 @@ static struct sk_buff *sja1110_rcv_inband_control_extension(struct sk_buff *skb,\n \t\t * padding and trailer we need to account for the fact that\n \t\t * skb-\u003edata points to skb_mac_header(skb) + ETH_HLEN.\n \t\t */\n-\t\tif (pskb_trim_rcsum(skb, start_of_padding - ETH_HLEN))\n+\t\tif (pskb_trim_rcsum(skb, start_of_padding - ETH_HLEN)) {\n+\t\t\tkfree_skb(skb);\n \t\t\treturn NULL;\n+\t\t}\n \t/* Trap-to-host frame, no timestamp trailer */\n \t} else {\n \t\t*source_port = SJA1110_RX_HEADER_SRC_PORT(rx_header);\n@@ -653,6 +664,7 @@ static struct sk_buff *sja1110_rcv(struct sk_buff *skb,\n \n \tif (!skb-\u003edev) {\n \t\tnetdev_warn(netdev, \"Couldn't decode source port\\n\");\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \ndiff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c\nindex 4dce24cfe6a716..49c802c10ca63a 100644\n--- a/net/dsa/tag_trailer.c\n+++ b/net/dsa/tag_trailer.c\n@@ -30,22 +30,30 @@ static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev)\n \tu8 *trailer;\n \tint source_port;\n \n-\tif (skb_linearize(skb))\n+\tif (skb_linearize(skb)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \ttrailer = skb_tail_pointer(skb) - 4;\n \tif (trailer[0] != 0x80 || (trailer[1] \u0026 0xf8) != 0x00 ||\n-\t (trailer[2] \u0026 0xef) != 0x00 || trailer[3] != 0x00)\n+\t (trailer[2] \u0026 0xef) != 0x00 || trailer[3] != 0x00) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tsource_port = trailer[1] \u0026 7;\n \n \tskb-\u003edev = dsa_conduit_find_user(dev, 0, source_port);\n-\tif (!skb-\u003edev)\n+\tif (!skb-\u003edev) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n-\tif (pskb_trim_rcsum(skb, skb-\u003elen - 4))\n+\tif (pskb_trim_rcsum(skb, skb-\u003elen - 4)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \treturn skb;\n }\ndiff --git a/net/dsa/tag_vsc73xx_8021q.c b/net/dsa/tag_vsc73xx_8021q.c\nindex af121a9aff7fbd..f4736a1a7a0f0f 100644\n--- a/net/dsa/tag_vsc73xx_8021q.c\n+++ b/net/dsa/tag_vsc73xx_8021q.c\n@@ -44,6 +44,7 @@ vsc73xx_rcv(struct sk_buff *skb, struct net_device *netdev)\n \tif (!skb-\u003edev) {\n \t\tdev_warn_ratelimited(\u0026netdev-\u003edev,\n \t\t\t\t \"Couldn't decode source port\\n\");\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \ndiff --git a/net/dsa/tag_xrs700x.c b/net/dsa/tag_xrs700x.c\nindex a05219f702c65a..bb268020ee865e 100644\n--- a/net/dsa/tag_xrs700x.c\n+++ b/net/dsa/tag_xrs700x.c\n@@ -30,15 +30,21 @@ static struct sk_buff *xrs700x_rcv(struct sk_buff *skb, struct net_device *dev)\n \n \tsource_port = ffs((int)trailer[0]) - 1;\n \n-\tif (source_port \u003c 0)\n+\tif (source_port \u003c 0) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \tskb-\u003edev = dsa_conduit_find_user(dev, 0, source_port);\n-\tif (!skb-\u003edev)\n+\tif (!skb-\u003edev) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n-\tif (pskb_trim_rcsum(skb, skb-\u003elen - 1))\n+\tif (pskb_trim_rcsum(skb, skb-\u003elen - 1)) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \t/* Frame is forwarded by hardware, don't forward in software. */\n \tdsa_default_offload_fwd_mark(skb);\ndiff --git a/net/dsa/tag_yt921x.c b/net/dsa/tag_yt921x.c\nindex f3ced99b1c852e..294784ab6694b6 100644\n--- a/net/dsa/tag_yt921x.c\n+++ b/net/dsa/tag_yt921x.c\n@@ -87,8 +87,10 @@ yt921x_tag_rcv(struct sk_buff *skb, struct net_device *netdev)\n \t__be16 *tag;\n \tu16 rx;\n \n-\tif (unlikely(!pskb_may_pull(skb, YT921X_TAG_LEN)))\n+\tif (unlikely(!pskb_may_pull(skb, YT921X_TAG_LEN))) {\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n+\t}\n \n \ttag = dsa_etype_header_pos_rx(skb);\n \n@@ -96,6 +98,7 @@ yt921x_tag_rcv(struct sk_buff *skb, struct net_device *netdev)\n \t\tdev_warn_ratelimited(\u0026netdev-\u003edev,\n \t\t\t\t \"Unexpected EtherType 0x%04x\\n\",\n \t\t\t\t ntohs(tag[0]));\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \n@@ -104,6 +107,7 @@ yt921x_tag_rcv(struct sk_buff *skb, struct net_device *netdev)\n \tif (unlikely((rx \u0026 YT921X_TAG_PORT_EN) == 0)) {\n \t\tdev_warn_ratelimited(\u0026netdev-\u003edev,\n \t\t\t\t \"Unexpected rx tag 0x%04x\\n\", rx);\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \n@@ -112,6 +116,7 @@ yt921x_tag_rcv(struct sk_buff *skb, struct net_device *netdev)\n \tif (unlikely(!skb-\u003edev)) {\n \t\tdev_warn_ratelimited(\u0026netdev-\u003edev,\n \t\t\t\t \"Couldn't decode source port %u\\n\", port);\n+\t\tkfree_skb(skb);\n \t\treturn NULL;\n \t}\n \ndiff --git a/net/dsa/user.c b/net/dsa/user.c\nindex 8704c1a3a5b741..072fa76972cc65 100644\n--- a/net/dsa/user.c\n+++ b/net/dsa/user.c\n@@ -935,13 +935,12 @@ static netdev_tx_t dsa_user_xmit(struct sk_buff *skb, struct net_device *dev)\n \t\teth_skb_pad(skb);\n \n \t/* Transmit function may have to reallocate the original SKB,\n-\t * in which case it must have freed it. Only free it here on error.\n+\t * in which case it must have freed it. Taggers will drop the\n+\t * passed skb on error.\n \t */\n \tnskb = p-\u003exmit(skb, dev);\n-\tif (!nskb) {\n-\t\tkfree_skb(skb);\n+\tif (!nskb)\n \t\treturn NETDEV_TX_OK;\n-\t}\n \n \treturn dsa_enqueue_skb(nskb, dev);\n }\n"
} |
| 2/1 | 2026/06/25 08:29 | agent | patch-evaluator |
1mModel:gemini-3.1-pro-preview Args: null Results: {
"EnableConfigs": [
"NET_DSA",
"NET_DSA_LOOP",
"NET_DSA_TAG_AR9331",
"NET_DSA_TAG_BRCM",
"NET_DSA_TAG_BRCM_LEGACY",
"NET_DSA_TAG_BRCM_PREPEND",
"NET_DSA_TAG_HELLCREEK",
"NET_DSA_TAG_GSWIP",
"NET_DSA_TAG_DSA",
"NET_DSA_TAG_EDSA",
"NET_DSA_TAG_MTK",
"NET_DSA_TAG_MXL_862XX",
"NET_DSA_TAG_MXL_GSW1XX",
"NET_DSA_TAG_KSZ",
"NET_DSA_TAG_NETC",
"NET_DSA_TAG_OCELOT",
"NET_DSA_TAG_OCELOT_8021Q",
"NET_DSA_TAG_QCA",
"NET_DSA_TAG_RTL4_A",
"NET_DSA_TAG_RTL8_4",
"NET_DSA_TAG_RZN1_A5PSW",
"NET_DSA_TAG_LAN9303",
"NET_DSA_TAG_SJA1105",
"NET_DSA_TAG_TRAILER",
"NET_DSA_TAG_VSC73XX_8021Q",
"NET_DSA_TAG_XRS700X",
"NET_DSA_TAG_YT921X"
],
"FocusSymbols": [
"dsa_switch_rcv",
"dsa_user_xmit",
"ar9331_tag_rcv",
"brcm_tag_xmit_ll",
"brcm_tag_rcv_ll",
"dsa_rcv_ll",
"edsa_rcv",
"ksz_common_rcv",
"ocelot_rcv",
"qca_tag_rcv",
"sja1105_rcv",
"trailer_rcv"
],
"Reasoning": "The patch refactors skb memory management in the DSA (Distributed Switch Architecture) subsystem. It shifts the responsibility of freeing the skb on error paths from the core DSA functions (dsa_user_xmit, dsa_switch_rcv) to the individual tagger drivers. This is a functional change that could introduce memory leaks or double frees if any error path in a tagger driver is missed or mishandled. The code is reachable in a virtualized environment by using the dsa_loop mock-up switch driver and dynamically changing the tagging protocol via sysfs.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Do not list too generic configs (we already have them enabled). Only list those that specifically cover the modified code. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 674e8998377cc6f17cb29ffc6655f92fc39a19f7
Author: syz-cluster <triage@syzkaller.com>
Date: Thu Jun 25 08:29:04 2026 +0000
syz-cluster: applied patch under review
diff --git a/net/dsa/tag.c b/net/dsa/tag.c
index 79ad105902d978..991732d6eae2c3 100644
--- a/net/dsa/tag.c
+++ b/net/dsa/tag.c
@@ -79,15 +79,16 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
if (likely(skb->dev)) {
dsa_default_offload_fwd_mark(skb);
nskb = skb;
+ } else {
+ /* Just drop the skb if we can't find the user */
+ kfree_skb(skb);
}
} else {
nskb = cpu_dp->rcv(skb, dev);
}
- if (!nskb) {
- kfree_skb(skb);
+ if (!nskb)
return 0;
- }
skb = nskb;
skb_push(skb, ETH_HLEN);
@@ -107,11 +108,10 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
if (unlikely(cpu_dp->ds->untag_bridge_pvid ||
cpu_dp->ds->untag_vlan_aware_bridge_pvid)) {
+ /* dsa_software_vlan_untag() drops skb on failure */
nskb = dsa_software_vlan_untag(skb);
- if (!nskb) {
- kfree_skb(skb);
+ if (!nskb)
return 0;
- }
skb = nskb;
}
diff --git a/net/dsa/tag_ar9331.c b/net/dsa/tag_ar9331.c
index cbb588ca73aaf5..2e2388143b0251 100644
--- a/net/dsa/tag_ar9331.c
+++ b/net/dsa/tag_ar9331.c
@@ -51,8 +51,10 @@ static struct sk_buff *ar9331_tag_rcv(struct sk_buff *skb,
u8 ver, port;
u16 hdr;
- if (unlikely(!pskb_may_pull(skb, AR9331_HDR_LEN)))
+ if (unlikely(!pskb_may_pull(skb, AR9331_HDR_LEN))) {
+ kfree_skb(skb);
return NULL;
+ }
hdr = le16_to_cpu(*(__le16 *)skb_mac_header(skb));
@@ -60,12 +62,14 @@ static struct sk_buff *ar9331_tag_rcv(struct sk_buff *skb,
if (unlikely(ver != AR9331_HDR_VERSION)) {
netdev_warn_once(ndev, "%s:%i wrong header version 0x%2x\n",
__func__, __LINE__, hdr);
+ kfree_skb(skb);
return NULL;
}
if (unlikely(hdr & AR9331_HDR_FROM_CPU)) {
netdev_warn_once(ndev, "%s:%i packet should not be from cpu 0x%2x\n",
__func__, __LINE__, hdr);
+ kfree_skb(skb);
return NULL;
}
@@ -75,8 +79,10 @@ static struct sk_buff *ar9331_tag_rcv(struct sk_buff *skb,
port = FIELD_GET(AR9331_HDR_PORT_NUM_MASK, hdr);
skb->dev = dsa_conduit_find_user(ndev, 0, port);
- if (!skb->dev)
+ if (!skb->dev) {
+ kfree_skb(skb);
return NULL;
+ }
return skb;
}
diff --git a/net/dsa/tag_brcm.c b/net/dsa/tag_brcm.c
index cf94204390543f..411e3b57d16af5 100644
--- a/net/dsa/tag_brcm.c
+++ b/net/dsa/tag_brcm.c
@@ -102,9 +102,9 @@ static struct sk_buff *brcm_tag_xmit_ll(struct sk_buff *skb,
* (including FCS and tag) because the length verification is done after
* the Broadcom tag is stripped off the ingress packet.
*
- * Let dsa_user_xmit() free the SKB
+ * Free the SKB on error.
*/
- if (__skb_put_padto(skb, ETH_ZLEN + BRCM_TAG_LEN, false))
+ if (skb_put_padto(skb, ETH_ZLEN + BRCM_TAG_LEN))
return NULL;
skb_push(skb, BRCM_TAG_LEN);
@@ -151,27 +151,35 @@ static struct sk_buff *brcm_tag_rcv_ll(struct sk_buff *skb,
int source_port;
u8 *brcm_tag;
- if (unlikely(!pskb_may_pull(skb, BRCM_TAG_LEN)))
+ if (unlikely(!pskb_may_pull(skb, BRCM_TAG_LEN))) {
+ kfree_skb(skb);
return NULL;
+ }
brcm_tag = skb->data - offset;
/* The opcode should never be different than 0b000 */
- if (unlikely((brcm_tag[0] >> BRCM_OPCODE_SHIFT) & BRCM_OPCODE_MASK))
+ if (unlikely((brcm_tag[0] >> BRCM_OPCODE_SHIFT) & BRCM_OPCODE_MASK)) {
+ kfree_skb(skb);
return NULL;
+ }
/* We should never see a reserved reason code without knowing how to
* handle it
*/
- if (unlikely(brcm_tag[2] & BRCM_EG_RC_RSVD))
+ if (unlikely(brcm_tag[2] & BRCM_EG_RC_RSVD)) {
+ kfree_skb(skb);
return NULL;
+ }
/* Locate which port this is coming from */
source_port = brcm_tag[3] & BRCM_EG_PID_MASK;
skb->dev = dsa_conduit_find_user(dev, 0, source_port);
- if (!skb->dev)
+ if (!skb->dev) {
+ kfree_skb(skb);
return NULL;
+ }
/* Remove Broadcom tag and update checksum */
skb_pull_rcsum(skb, BRCM_TAG_LEN);
@@ -228,8 +236,10 @@ static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
__be16 *proto;
u8 *brcm_tag;
- if (unlikely(!pskb_may_pull(skb, BRCM_LEG_TAG_LEN + VLAN_HLEN)))
+ if (unlikely(!pskb_may_pull(skb, BRCM_LEG_TAG_LEN + VLAN_HLEN))) {
+ kfree_skb(skb);
return NULL;
+ }
brcm_tag = dsa_etype_header_pos_rx(skb);
proto = (__be16 *)(brcm_tag + BRCM_LEG_TAG_LEN);
@@ -237,8 +247,10 @@ static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
source_port = brcm_tag[5] & BRCM_LEG_PORT_ID;
skb->dev = dsa_conduit_find_user(dev, 0, source_port);
- if (!skb->dev)
+ if (!skb->dev) {
+ kfree_skb(skb);
return NULL;
+ }
/* The internal switch in BCM63XX SoCs always tags on egress on the CPU
* port. We use VID 0 internally for untagged traffic, so strip the tag
@@ -273,10 +285,8 @@ static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb,
* need to make sure that packets are at least 70 bytes
* (including FCS and tag) because the length verification is done after
* the Broadcom tag is stripped off the ingress packet.
- *
- * Let dsa_user_xmit() free the SKB
*/
- if (__skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN, false))
+ if (skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN))
return NULL;
skb_push(skb, BRCM_LEG_TAG_LEN);
@@ -325,10 +335,8 @@ static struct sk_buff *brcm_leg_fcs_tag_xmit(struct sk_buff *skb,
* need to make sure that packets are at least 70 bytes (including FCS
* and tag) because the length verification is done after the Broadcom
* tag is stripped off the ingress packet.
- *
- * Let dsa_user_xmit() free the SKB.
*/
- if (__skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN, false))
+ if (skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN))
return NULL;
fcs_len = skb->len;
@@ -351,8 +359,9 @@ static struct sk_buff *brcm_leg_fcs_tag_xmit(struct sk_buff *skb,
brcm_tag[5] = dp->index & BRCM_LEG_PORT_ID;
/* Original FCS value */
- if (__skb_pad(skb, ETH_FCS_LEN, false))
+ if (skb_pad(skb, ETH_FCS_LEN))
return NULL;
+
skb_put_data(skb, &fcs_val, ETH_FCS_LEN);
return skb;
diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c
index 2a2c4fb61a65c6..d5ffee35fbb53b 100644
--- a/net/dsa/tag_dsa.c
+++ b/net/dsa/tag_dsa.c
@@ -224,6 +224,7 @@ static struct sk_buff *dsa_rcv_ll(struct sk_buff *skb, struct net_device *dev,
/* Remote management is not implemented yet,
* drop.
*/
+ kfree_skb(skb);
return NULL;
case DSA_CODE_ARP_MIRROR:
case DSA_CODE_POLICY_MIRROR:
@@ -244,12 +245,14 @@ static struct sk_buff *dsa_rcv_ll(struct sk_buff *skb, struct net_device *dev,
/* Reserved code, this could be anything. Drop
* seems like the safest option.
*/
+ kfree_skb(skb);
return NULL;
}
break;
default:
+ kfree_skb(skb);
return NULL;
}
@@ -271,8 +274,10 @@ static struct sk_buff *dsa_rcv_ll(struct sk_buff *skb, struct net_device *dev,
source_port);
}
- if (!skb->dev)
+ if (!skb->dev) {
+ kfree_skb(skb);
return NULL;
+ }
/* When using LAG offload, skb->dev is not a DSA user interface,
* so we cannot call dsa_default_offload_fwd_mark and we need to
@@ -335,8 +340,10 @@ static struct sk_buff *dsa_xmit(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff *dsa_rcv(struct sk_buff *skb, struct net_device *dev)
{
- if (unlikely(!pskb_may_pull(skb, DSA_HLEN)))
+ if (unlikely(!pskb_may_pull(skb, DSA_HLEN))) {
+ kfree_skb(skb);
return NULL;
+ }
return dsa_rcv_ll(skb, dev, 0);
}
@@ -375,8 +382,10 @@ static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev)
{
- if (unlikely(!pskb_may_pull(skb, EDSA_HLEN)))
+ if (unlikely(!pskb_may_pull(skb, EDSA_HLEN))) {
+ kfree_skb(skb);
return NULL;
+ }
skb_pull_rcsum(skb, EDSA_HLEN - DSA_HLEN);
diff --git a/net/dsa/tag_gswip.c b/net/dsa/tag_gswip.c
index 5fa436121087b4..5c407d448c9fee 100644
--- a/net/dsa/tag_gswip.c
+++ b/net/dsa/tag_gswip.c
@@ -80,16 +80,20 @@ static struct sk_buff *gswip_tag_rcv(struct sk_buff *skb,
int port;
u8 *gswip_tag;
- if (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN)))
+ if (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN))) {
+ kfree_skb(skb);
return NULL;
+ }
gswip_tag = skb->data - ETH_HLEN;
/* Get source port information */
port = (gswip_tag[7] & GSWIP_RX_SPPID_MASK) >> GSWIP_RX_SPPID_SHIFT;
skb->dev = dsa_conduit_find_user(dev, 0, port);
- if (!skb->dev)
+ if (!skb->dev) {
+ kfree_skb(skb);
return NULL;
+ }
/* remove GSWIP tag */
skb_pull_rcsum(skb, GSWIP_RX_HEADER_LEN);
diff --git a/net/dsa/tag_hellcreek.c b/net/dsa/tag_hellcreek.c
index 544ab15685a2b8..dd9f328f318210 100644
--- a/net/dsa/tag_hellcreek.c
+++ b/net/dsa/tag_hellcreek.c
@@ -27,8 +27,10 @@ static struct sk_buff *hellcreek_xmit(struct sk_buff *skb,
* checksums after the switch strips the tag.
*/
if (skb->ip_summed == CHECKSUM_PARTIAL &&
- skb_checksum_help(skb))
+ skb_checksum_help(skb)) {
+ kfree_skb(skb);
return NULL;
+ }
/* Tag encoding */
tag = skb_put(skb, HELLCREEK_TAG_LEN);
@@ -47,11 +49,14 @@ static struct sk_buff *hellcreek_rcv(struct sk_buff *skb,
skb->dev = dsa_conduit_find_user(dev, 0, port);
if (!skb->dev) {
netdev_warn_once(dev, "Failed to get source port: %d\n", port);
+ kfree_skb(skb);
return NULL;
}
- if (pskb_trim_rcsum(skb, skb->len - HELLCREEK_TAG_LEN))
+ if (pskb_trim_rcsum(skb, skb->len - HELLCREEK_TAG_LEN)) {
+ kfree_skb(skb);
return NULL;
+ }
dsa_default_offload_fwd_mark(skb);
diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
index d2475c3bbb7d22..67fa89f102e070 100644
--- a/net/dsa/tag_ksz.c
+++ b/net/dsa/tag_ksz.c
@@ -88,11 +88,15 @@ static struct sk_buff *ksz_common_rcv(struct sk_buff *skb,
unsigned int port, unsigned int len)
{
skb->dev = dsa_conduit_find_user(dev, 0, port);
- if (!skb->dev)
+ if (!skb->dev) {
+ kfree_skb(skb);
return NULL;
+ }
- if (pskb_trim_rcsum(skb, skb->len - len))
+ if (pskb_trim_rcsum(skb, skb->len - len)) {
+ kfree_skb(skb);
return NULL;
+ }
dsa_default_offload_fwd_mark(skb);
@@ -123,8 +127,10 @@ static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device *dev)
struct ethhdr *hdr;
u8 *tag;
- if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+ if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) {
+ kfree_skb(skb);
return NULL;
+ }
/* Tag encoding */
tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
@@ -141,8 +147,10 @@ static struct sk_buff *ksz8795_rcv(struct sk_buff *skb, struct net_device *dev)
{
u8 *tag;
- if (skb_linearize(skb))
+ if (skb_linearize(skb)) {
+ kfree_skb(skb);
return NULL;
+ }
tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
@@ -255,22 +263,24 @@ static struct sk_buff *ksz_defer_xmit(struct dsa_port *dp, struct sk_buff *skb)
xmit_work_fn = tagger_data->xmit_work_fn;
xmit_worker = priv->xmit_worker;
- if (!xmit_work_fn || !xmit_worker)
+ if (!xmit_work_fn || !xmit_worker) {
+ kfree_skb(skb);
return NULL;
+ }
xmit_work = kzalloc_obj(*xmit_work, GFP_ATOMIC);
- if (!xmit_work)
+ if (!xmit_work) {
+ kfree_skb(skb);
return NULL;
+ }
kthread_init_work(&xmit_work->work, xmit_work_fn);
- /* Increase refcount so the kfree_skb in dsa_user_xmit
- * won't really free the packet.
- */
xmit_work->dp = dp;
xmit_work->skb = skb_get(skb);
kthread_queue_work(xmit_worker, &xmit_work->work);
+ kfree_skb(skb);
return NULL;
}
@@ -284,8 +294,10 @@ static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,
__be16 *tag;
u16 val;
- if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+ if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) {
+ kfree_skb(skb);
return NULL;
+ }
/* Tag encoding */
ksz_xmit_timestamp(dp, skb);
@@ -310,8 +322,10 @@ static struct sk_buff *ksz9477_rcv(struct sk_buff *skb, struct net_device *dev)
unsigned int port;
u8 *tag;
- if (skb_linearize(skb))
+ if (skb_linearize(skb)) {
+ kfree_skb(skb);
return NULL;
+ }
/* Tag decoding */
tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
@@ -352,8 +366,10 @@ static struct sk_buff *ksz9893_xmit(struct sk_buff *skb,
struct ethhdr *hdr;
u8 *tag;
- if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+ if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) {
+ kfree_skb(skb);
return NULL;
+ }
/* Tag encoding */
ksz_xmit_timestamp(dp, skb);
@@ -418,8 +434,10 @@ static struct sk_buff *lan937x_xmit(struct sk_buff *skb,
__be16 *tag;
u16 val;
- if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+ if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) {
+ kfree_skb(skb);
return NULL;
+ }
ksz_xmit_timestamp(dp, skb);
diff --git a/net/dsa/tag_lan9303.c b/net/dsa/tag_lan9303.c
index 258e5d7dc5ef84..d1194696499ab8 100644
--- a/net/dsa/tag_lan9303.c
+++ b/net/dsa/tag_lan9303.c
@@ -85,6 +85,7 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev)
if (unlikely(!pskb_may_pull(skb, LAN9303_TAG_LEN))) {
dev_warn_ratelimited(&dev->dev,
"Dropping packet, cannot pull\n");
+ kfree_skb(skb);
return NULL;
}
@@ -102,6 +103,7 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev)
skb->dev = dsa_conduit_find_user(dev, 0, source_port);
if (!skb->dev) {
dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid source port\n");
+ kfree_skb(skb);
return NULL;
}
diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
index dea3eecaf093df..c7dc7731675ec0 100644
--- a/net/dsa/tag_mtk.c
+++ b/net/dsa/tag_mtk.c
@@ -72,8 +72,10 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev)
int port;
__be16 *phdr;
- if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN)))
+ if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN))) {
+ kfree_skb(skb);
return NULL;
+ }
phdr = dsa_etype_header_pos_rx(skb);
hdr = ntohs(*phdr);
@@ -87,8 +89,10 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev)
port = (hdr & MTK_HDR_RECV_SOURCE_PORT_MASK);
skb->dev = dsa_conduit_find_user(dev, 0, port);
- if (!skb->dev)
+ if (!skb->dev) {
+ kfree_skb(skb);
return NULL;
+ }
dsa_default_offload_fwd_mark(skb);
diff --git a/net/dsa/tag_mxl-gsw1xx.c b/net/dsa/tag_mxl-gsw1xx.c
index 60f7c445e65610..4b1b6ef9419634 100644
--- a/net/dsa/tag_mxl-gsw1xx.c
+++ b/net/dsa/tag_mxl-gsw1xx.c
@@ -73,6 +73,7 @@ static struct sk_buff *gsw1xx_tag_rcv(struct sk_buff *skb,
if (unlikely(!pskb_may_pull(skb, GSW1XX_HEADER_LEN))) {
dev_warn_ratelimited(&dev->dev, "Dropping packet, cannot pull SKB\n");
+ kfree_skb(skb);
return NULL;
}
@@ -81,6 +82,7 @@ static struct sk_buff *gsw1xx_tag_rcv(struct sk_buff *skb,
if (unlikely(ntohs(gsw1xx_tag[0]) != ETH_P_MXLGSW)) {
dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid special tag\n");
dev_warn_ratelimited(&dev->dev, "Tag: %8ph\n", gsw1xx_tag);
+ kfree_skb(skb);
return NULL;
}
@@ -90,6 +92,7 @@ static struct sk_buff *gsw1xx_tag_rcv(struct sk_buff *skb,
if (!skb->dev) {
dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid source port\n");
dev_warn_ratelimited(&dev->dev, "Tag: %8ph\n", gsw1xx_tag);
+ kfree_skb(skb);
return NULL;
}
diff --git a/net/dsa/tag_mxl862xx.c b/net/dsa/tag_mxl862xx.c
index 8daefeb8d49dfa..87b80ddf094632 100644
--- a/net/dsa/tag_mxl862xx.c
+++ b/net/dsa/tag_mxl862xx.c
@@ -64,6 +64,7 @@ static struct sk_buff *mxl862_tag_rcv(struct sk_buff *skb,
if (unlikely(!pskb_may_pull(skb, MXL862_HEADER_LEN))) {
dev_warn_ratelimited(&dev->dev, "Cannot pull SKB, packet dropped\n");
+ kfree_skb(skb);
return NULL;
}
@@ -73,6 +74,7 @@ static struct sk_buff *mxl862_tag_rcv(struct sk_buff *skb,
dev_warn_ratelimited(&dev->dev,
"Invalid special tag marker, packet dropped, tag: %8ph\n",
mxl862_tag);
+ kfree_skb(skb);
return NULL;
}
@@ -83,6 +85,7 @@ static struct sk_buff *mxl862_tag_rcv(struct sk_buff *skb,
dev_warn_ratelimited(&dev->dev,
"Invalid source port, packet dropped, tag: %8ph\n",
mxl862_tag);
+ kfree_skb(skb);
return NULL;
}
diff --git a/net/dsa/tag_netc.c b/net/dsa/tag_netc.c
index ccedfe3a80b64d..df72a61796ad5f 100644
--- a/net/dsa/tag_netc.c
+++ b/net/dsa/tag_netc.c
@@ -131,14 +131,13 @@ static struct sk_buff *netc_rcv(struct sk_buff *skb,
int type, subtype;
if (unlikely(!pskb_may_pull(skb, NETC_TAG_MAX_LEN)))
- return NULL;
+ goto err_free_skb;
tag_cmn = dsa_etype_header_pos_rx(skb);
if (ntohs(tag_cmn->tpid) != ETH_P_NXP_NETC) {
dev_warn_ratelimited(&ndev->dev, "Unknown TPID 0x%04x\n",
ntohs(tag_cmn->tpid));
-
- return NULL;
+ goto err_free_skb;
}
if (tag_cmn->qos & NETC_TAG_QV)
@@ -149,14 +148,13 @@ static struct sk_buff *netc_rcv(struct sk_buff *skb,
if (!sw_id) {
dev_warn_ratelimited(&ndev->dev,
"VEPA switch ID is not supported yet\n");
-
- return NULL;
+ goto err_free_skb;
}
port = FIELD_GET(NETC_TAG_PORT, tag_cmn->switch_port);
skb->dev = dsa_conduit_find_user(ndev, sw_id, port);
if (!skb->dev)
- return NULL;
+ goto err_free_skb;
type = FIELD_GET(NETC_TAG_TYPE, tag_cmn->type);
subtype = FIELD_GET(NETC_TAG_SUBTYPE, tag_cmn->type);
@@ -165,11 +163,11 @@ static struct sk_buff *netc_rcv(struct sk_buff *skb,
} else if (type == NETC_TAG_TO_HOST) {
/* Currently only subtype0 supported */
if (subtype != NETC_TAG_TH_SUBTYPE0)
- return NULL;
+ goto err_free_skb;
} else {
dev_warn_ratelimited(&ndev->dev,
"Unexpected tag type %d\n", type);
- return NULL;
+ goto err_free_skb;
}
/* Remove Switch tag from the frame */
@@ -178,6 +176,10 @@ static struct sk_buff *netc_rcv(struct sk_buff *skb,
dsa_strip_etype_header(skb, tag_len);
return skb;
+
+err_free_skb:
+ kfree_skb(skb);
+ return NULL;
}
static void netc_flow_dissect(const struct sk_buff *skb, __be16 *proto,
diff --git a/net/dsa/tag_ocelot.c b/net/dsa/tag_ocelot.c
index 3405def79c2def..d208c7322cd626 100644
--- a/net/dsa/tag_ocelot.c
+++ b/net/dsa/tag_ocelot.c
@@ -107,14 +107,16 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
ocelot_xfh_get_rew_val(extraction, &rew_val);
skb->dev = dsa_conduit_find_user(netdev, 0, src_port);
- if (!skb->dev)
+ if (!skb->dev) {
/* The switch will reflect back some frames sent through
* sockets opened on the bare DSA conduit. These will come back
* with src_port equal to the index of the CPU port, for which
* there is no user registered. So don't print any error
* message here (ignore and drop those frames).
*/
+ kfree_skb(skb);
return NULL;
+ }
dsa_default_offload_fwd_mark(skb);
skb->priority = qos_class;
diff --git a/net/dsa/tag_ocelot_8021q.c b/net/dsa/tag_ocelot_8021q.c
index e89d9254e90a3a..f50f1cd83f161c 100644
--- a/net/dsa/tag_ocelot_8021q.c
+++ b/net/dsa/tag_ocelot_8021q.c
@@ -33,30 +33,34 @@ static struct sk_buff *ocelot_defer_xmit(struct dsa_port *dp,
xmit_work_fn = data->xmit_work_fn;
xmit_worker = priv->xmit_worker;
- if (!xmit_work_fn || !xmit_worker)
+ if (!xmit_work_fn || !xmit_worker) {
+ kfree_skb(skb);
return NULL;
+ }
/* PTP over IP packets need UDP checksumming. We may have inherited
* NETIF_F_HW_CSUM from the DSA conduit, but these packets are not sent
* through the DSA conduit, so calculate the checksum here.
*/
- if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+ if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) {
+ kfree_skb(skb);
return NULL;
+ }
xmit_work = kzalloc_obj(*xmit_work, GFP_ATOMIC);
- if (!xmit_work)
+ if (!xmit_work) {
+ kfree_skb(skb);
return NULL;
+ }
/* Calls felix_port_deferred_xmit in felix.c */
kthread_init_work(&xmit_work->work, xmit_work_fn);
- /* Increase refcount so the kfree_skb in dsa_user_xmit
- * won't really free the packet.
- */
xmit_work->dp = dp;
xmit_work->skb = skb_get(skb);
kthread_queue_work(xmit_worker, &xmit_work->work);
+ kfree_skb(skb);
return NULL;
}
@@ -84,8 +88,10 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
dsa_8021q_rcv(skb, &src_port, &switch_id, NULL, NULL);
skb->dev = dsa_conduit_find_user(netdev, switch_id, src_port);
- if (!skb->dev)
+ if (!skb->dev) {
+ kfree_skb(skb);
return NULL;
+ }
dsa_default_offload_fwd_mark(skb);
diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c
index 9e3b429e8b3625..510792fbfa92dd 100644
--- a/net/dsa/tag_qca.c
+++ b/net/dsa/tag_qca.c
@@ -46,16 +46,20 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev)
tagger_data = ds->tagger_data;
- if (unlikely(!pskb_may_pull(skb, QCA_HDR_LEN)))
+ if (unlikely(!pskb_may_pull(skb, QCA_HDR_LEN))) {
+ kfree_skb(skb);
return NULL;
+ }
phdr = dsa_etype_header_pos_rx(skb);
hdr = ntohs(*phdr);
/* Make sure the version is correct */
ver = FIELD_GET(QCA_HDR_RECV_VERSION, hdr);
- if (unlikely(ver != QCA_HDR_VERSION))
+ if (unlikely(ver != QCA_HDR_VERSION)) {
+ kfree_skb(skb);
return NULL;
+ }
/* Get pk type */
pk_type = FIELD_GET(QCA_HDR_RECV_TYPE, hdr);
@@ -64,6 +68,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev)
if (pk_type == QCA_HDR_RECV_TYPE_RW_REG_ACK) {
if (likely(tagger_data->rw_reg_ack_handler))
tagger_data->rw_reg_ack_handler(ds, skb);
+ kfree_skb(skb);
return NULL;
}
@@ -71,6 +76,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev)
if (pk_type == QCA_HDR_RECV_TYPE_MIB) {
if (likely(tagger_data->mib_autocast_handler))
tagger_data->mib_autocast_handler(ds, skb);
+ kfree_skb(skb);
return NULL;
}
@@ -78,8 +84,10 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev)
port = FIELD_GET(QCA_HDR_RECV_SOURCE_PORT, hdr);
skb->dev = dsa_conduit_find_user(dev, 0, port);
- if (!skb->dev)
+ if (!skb->dev) {
+ kfree_skb(skb);
return NULL;
+ }
/* Remove QCA tag and recalculate checksum */
skb_pull_rcsum(skb, QCA_HDR_LEN);
diff --git a/net/dsa/tag_rtl4_a.c b/net/dsa/tag_rtl4_a.c
index 3cc63eacfa0352..590ea3b921c9d9 100644
--- a/net/dsa/tag_rtl4_a.c
+++ b/net/dsa/tag_rtl4_a.c
@@ -41,7 +41,7 @@ static struct sk_buff *rtl4a_tag_xmit(struct sk_buff *skb,
u16 out;
/* Pad out to at least 60 bytes */
- if (unlikely(__skb_put_padto(skb, ETH_ZLEN, false)))
+ if (unlikely(eth_skb_pad(skb)))
return NULL;
netdev_dbg(dev, "add realtek tag to package to port %d\n",
@@ -75,8 +75,10 @@ static struct sk_buff *rtl4a_tag_rcv(struct sk_buff *skb,
u8 prot;
u8 port;
- if (unlikely(!pskb_may_pull(skb, RTL4_A_HDR_LEN)))
+ if (unlikely(!pskb_may_pull(skb, RTL4_A_HDR_LEN))) {
+ kfree_skb(skb);
return NULL;
+ }
tag = dsa_etype_header_pos_rx(skb);
p = (__be16 *)tag;
@@ -92,6 +94,7 @@ static struct sk_buff *rtl4a_tag_rcv(struct sk_buff *skb,
prot = (protport >> RTL4_A_PROTOCOL_SHIFT) & 0x0f;
if (prot != RTL4_A_PROTOCOL_RTL8366RB) {
netdev_err(dev, "unknown realtek protocol 0x%01x\n", prot);
+ kfree_skb(skb);
return NULL;
}
port = protport & 0xff;
@@ -99,6 +102,7 @@ static struct sk_buff *rtl4a_tag_rcv(struct sk_buff *skb,
skb->dev = dsa_conduit_find_user(dev, 0, port);
if (!skb->dev) {
netdev_dbg(dev, "could not find user for port %d\n", port);
+ kfree_skb(skb);
return NULL;
}
diff --git a/net/dsa/tag_rtl8_4.c b/net/dsa/tag_rtl8_4.c
index 852c6b88079a13..4da3beebef75e2 100644
--- a/net/dsa/tag_rtl8_4.c
+++ b/net/dsa/tag_rtl8_4.c
@@ -143,8 +143,10 @@ static struct sk_buff *rtl8_4t_tag_xmit(struct sk_buff *skb,
/* Calculate the checksum here if not done yet as trailing tags will
* break either software or hardware based checksum
*/
- if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+ if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) {
+ kfree_skb(skb);
return NULL;
+ }
rtl8_4_write_tag(skb, dev, skb_put(skb, RTL8_4_TAG_LEN));
@@ -201,11 +203,15 @@ static int rtl8_4_read_tag(struct sk_buff *skb, struct net_device *dev,
static struct sk_buff *rtl8_4_tag_rcv(struct sk_buff *skb,
struct net_device *dev)
{
- if (unlikely(!pskb_may_pull(skb, RTL8_4_TAG_LEN)))
+ if (unlikely(!pskb_may_pull(skb, RTL8_4_TAG_LEN))) {
+ kfree_skb(skb);
return NULL;
+ }
- if (unlikely(rtl8_4_read_tag(skb, dev, dsa_etype_header_pos_rx(skb))))
+ if (unlikely(rtl8_4_read_tag(skb, dev, dsa_etype_header_pos_rx(skb)))) {
+ kfree_skb(skb);
return NULL;
+ }
/* Remove tag and recalculate checksum */
skb_pull_rcsum(skb, RTL8_4_TAG_LEN);
@@ -218,14 +224,20 @@ static struct sk_buff *rtl8_4_tag_rcv(struct sk_buff *skb,
static struct sk_buff *rtl8_4t_tag_rcv(struct sk_buff *skb,
struct net_device *dev)
{
- if (skb_linearize(skb))
+ if (skb_linearize(skb)) {
+ kfree_skb(skb);
return NULL;
+ }
- if (unlikely(rtl8_4_read_tag(skb, dev, skb_tail_pointer(skb) - RTL8_4_TAG_LEN)))
+ if (unlikely(rtl8_4_read_tag(skb, dev, skb_tail_pointer(skb) - RTL8_4_TAG_LEN))) {
+ kfree_skb(skb);
return NULL;
+ }
- if (pskb_trim_rcsum(skb, skb->len - RTL8_4_TAG_LEN))
+ if (pskb_trim_rcsum(skb, skb->len - RTL8_4_TAG_LEN)) {
+ kfree_skb(skb);
return NULL;
+ }
return skb;
}
diff --git a/net/dsa/tag_rzn1_a5psw.c b/net/dsa/tag_rzn1_a5psw.c
index 10994b3470f67a..734910156dc333 100644
--- a/net/dsa/tag_rzn1_a5psw.c
+++ b/net/dsa/tag_rzn1_a5psw.c
@@ -48,7 +48,7 @@ static struct sk_buff *a5psw_tag_xmit(struct sk_buff *skb, struct net_device *de
* least 60 bytes otherwise they will be discarded when they enter the
* switch port logic.
*/
- if (__skb_put_padto(skb, ETH_ZLEN, false))
+ if (eth_skb_pad(skb))
return NULL;
/* provide 'A5PSW_TAG_LEN' bytes additional space */
@@ -77,6 +77,7 @@ static struct sk_buff *a5psw_tag_rcv(struct sk_buff *skb,
if (unlikely(!pskb_may_pull(skb, A5PSW_TAG_LEN))) {
dev_warn_ratelimited(&dev->dev,
"Dropping packet, cannot pull\n");
+ kfree_skb(skb);
return NULL;
}
@@ -84,14 +85,17 @@ static struct sk_buff *a5psw_tag_rcv(struct sk_buff *skb,
if (tag->ctrl_tag != htons(ETH_P_DSA_A5PSW)) {
dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid TAG marker\n");
+ kfree_skb(skb);
return NULL;
}
port = FIELD_GET(A5PSW_CTRL_DATA_PORT, ntohs(tag->ctrl_data));
skb->dev = dsa_conduit_find_user(dev, 0, port);
- if (!skb->dev)
+ if (!skb->dev) {
+ kfree_skb(skb);
return NULL;
+ }
skb_pull_rcsum(skb, A5PSW_TAG_LEN);
dsa_strip_etype_header(skb, A5PSW_TAG_LEN);
diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c
index de6d4ce8668be1..bfe1f746f55be5 100644
--- a/net/dsa/tag_sja1105.c
+++ b/net/dsa/tag_sja1105.c
@@ -149,19 +149,20 @@ static struct sk_buff *sja1105_defer_xmit(struct dsa_port *dp,
xmit_work_fn = tagger_data->xmit_work_fn;
xmit_worker = priv->xmit_worker;
- if (!xmit_work_fn || !xmit_worker)
+ if (!xmit_work_fn || !xmit_worker) {
+ kfree_skb(skb);
return NULL;
+ }
xmit_work = kzalloc_obj(*xmit_work, GFP_ATOMIC);
- if (!xmit_work)
+ if (!xmit_work) {
+ kfree_skb(skb);
return NULL;
+ }
kthread_init_work(&xmit_work->work, xmit_work_fn);
- /* Increase refcount so the kfree_skb in dsa_user_xmit
- * won't really free the packet.
- */
xmit_work->dp = dp;
- xmit_work->skb = skb_get(skb);
+ xmit_work->skb = skb;
kthread_queue_work(xmit_worker, &xmit_work->work);
@@ -401,10 +402,7 @@ static struct sk_buff
kfree_skb(priv->stampable_skb);
}
- /* Hold a reference to avoid dsa_switch_rcv
- * from freeing the skb.
- */
- priv->stampable_skb = skb_get(skb);
+ priv->stampable_skb = skb;
spin_unlock(&priv->meta_lock);
/* Tell DSA we got nothing */
@@ -436,6 +434,7 @@ static struct sk_buff
dev_err_ratelimited(ds->dev,
"Unexpected meta frame\n");
spin_unlock(&priv->meta_lock);
+ kfree_skb(skb);
return NULL;
}
@@ -443,6 +442,7 @@ static struct sk_buff
dev_err_ratelimited(ds->dev,
"Meta frame on wrong port\n");
spin_unlock(&priv->meta_lock);
+ kfree_skb(skb);
return NULL;
}
@@ -501,18 +501,21 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb,
/* Normal data plane traffic and link-local frames are tagged with
* a tag_8021q VLAN which we have to strip
*/
- if (sja1105_skb_has_tag_8021q(skb))
+ if (sja1105_skb_has_tag_8021q(skb)) {
dsa_8021q_rcv(skb, &source_port, &switch_id, &vbid, &vid);
- else if (source_port == -1 && switch_id == -1)
+ } else if (source_port == -1 && switch_id == -1) {
/* Packets with no source information have no chance of
* getting accepted, drop them straight away.
*/
+ kfree_skb(skb);
return NULL;
+ }
skb->dev = dsa_tag_8021q_find_user(netdev, source_port, switch_id,
vid, vbid);
if (!skb->dev) {
netdev_warn(netdev, "Couldn't decode source port\n");
+ kfree_skb(skb);
return NULL;
}
@@ -539,12 +542,15 @@ static struct sk_buff *sja1110_rcv_meta(struct sk_buff *skb, u16 rx_header)
if (!ds) {
net_err_ratelimited("%s: cannot find switch id %d\n",
conduit->name, switch_id);
+ kfree_skb(skb);
return NULL;
}
tagger_data = sja1105_tagger_data(ds);
- if (!tagger_data->meta_tstamp_handler)
+ if (!tagger_data->meta_tstamp_handler) {
+ kfree_skb(skb);
return NULL;
+ }
for (i = 0; i <= n_ts; i++) {
u8 ts_id, source_port, dir;
@@ -562,6 +568,7 @@ static struct sk_buff *sja1110_rcv_meta(struct sk_buff *skb, u16 rx_header)
}
/* Discard the meta frame, we've consumed the timestamps it contained */
+ kfree_skb(skb);
return NULL;
}
@@ -572,8 +579,10 @@ static struct sk_buff *sja1110_rcv_inband_control_extension(struct sk_buff *skb,
{
u16 rx_header;
- if (unlikely(!pskb_may_pull(skb, SJA1110_HEADER_LEN)))
+ if (unlikely(!pskb_may_pull(skb, SJA1110_HEADER_LEN))) {
+ kfree_skb(skb);
return NULL;
+ }
/* skb->data points to skb_mac_header(skb) + ETH_HLEN, which is exactly
* what we need because the caller has checked the EtherType (which is
@@ -609,8 +618,10 @@ static struct sk_buff *sja1110_rcv_inband_control_extension(struct sk_buff *skb,
* padding and trailer we need to account for the fact that
* skb->data points to skb_mac_header(skb) + ETH_HLEN.
*/
- if (pskb_trim_rcsum(skb, start_of_padding - ETH_HLEN))
+ if (pskb_trim_rcsum(skb, start_of_padding - ETH_HLEN)) {
+ kfree_skb(skb);
return NULL;
+ }
/* Trap-to-host frame, no timestamp trailer */
} else {
*source_port = SJA1110_RX_HEADER_SRC_PORT(rx_header);
@@ -653,6 +664,7 @@ static struct sk_buff *sja1110_rcv(struct sk_buff *skb,
if (!skb->dev) {
netdev_warn(netdev, "Couldn't decode source port\n");
+ kfree_skb(skb);
return NULL;
}
diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c
index 4dce24cfe6a716..49c802c10ca63a 100644
--- a/net/dsa/tag_trailer.c
+++ b/net/dsa/tag_trailer.c
@@ -30,22 +30,30 @@ static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev)
u8 *trailer;
int source_port;
- if (skb_linearize(skb))
+ if (skb_linearize(skb)) {
+ kfree_skb(skb);
return NULL;
+ }
trailer = skb_tail_pointer(skb) - 4;
if (trailer[0] != 0x80 || (trailer[1] & 0xf8) != 0x00 ||
- (trailer[2] & 0xef) != 0x00 || trailer[3] != 0x00)
+ (trailer[2] & 0xef) != 0x00 || trailer[3] != 0x00) {
+ kfree_skb(skb);
return NULL;
+ }
source_port = trailer[1] & 7;
skb->dev = dsa_conduit_find_user(dev, 0, source_port);
- if (!skb->dev)
+ if (!skb->dev) {
+ kfree_skb(skb);
return NULL;
+ }
- if (pskb_trim_rcsum(skb, skb->len - 4))
+ if (pskb_trim_rcsum(skb, skb->len - 4)) {
+ kfree_skb(skb);
return NULL;
+ }
return skb;
}
diff --git a/net/dsa/tag_vsc73xx_8021q.c b/net/dsa/tag_vsc73xx_8021q.c
index af121a9aff7fbd..f4736a1a7a0f0f 100644
--- a/net/dsa/tag_vsc73xx_8021q.c
+++ b/net/dsa/tag_vsc73xx_8021q.c
@@ -44,6 +44,7 @@ vsc73xx_rcv(struct sk_buff *skb, struct net_device *netdev)
if (!skb->dev) {
dev_warn_ratelimited(&netdev->dev,
"Couldn't decode source port\n");
+ kfree_skb(skb);
return NULL;
}
diff --git a/net/dsa/tag_xrs700x.c b/net/dsa/tag_xrs700x.c
index a05219f702c65a..bb268020ee865e 100644
--- a/net/dsa/tag_xrs700x.c
+++ b/net/dsa/tag_xrs700x.c
@@ -30,15 +30,21 @@ static struct sk_buff *xrs700x_rcv(struct sk_buff *skb, struct net_device *dev)
source_port = ffs((int)trailer[0]) - 1;
- if (source_port < 0)
+ if (source_port < 0) {
+ kfree_skb(skb);
return NULL;
+ }
skb->dev = dsa_conduit_find_user(dev, 0, source_port);
- if (!skb->dev)
+ if (!skb->dev) {
+ kfree_skb(skb);
return NULL;
+ }
- if (pskb_trim_rcsum(skb, skb->len - 1))
+ if (pskb_trim_rcsum(skb, skb->len - 1)) {
+ kfree_skb(skb);
return NULL;
+ }
/* Frame is forwarded by hardware, don't forward in software. */
dsa_default_offload_fwd_mark(skb);
diff --git a/net/dsa/tag_yt921x.c b/net/dsa/tag_yt921x.c
index f3ced99b1c852e..294784ab6694b6 100644
--- a/net/dsa/tag_yt921x.c
+++ b/net/dsa/tag_yt921x.c
@@ -87,8 +87,10 @@ yt921x_tag_rcv(struct sk_buff *skb, struct net_device *netdev)
__be16 *tag;
u16 rx;
- if (unlikely(!pskb_may_pull(skb, YT921X_TAG_LEN)))
+ if (unlikely(!pskb_may_pull(skb, YT921X_TAG_LEN))) {
+ kfree_skb(skb);
return NULL;
+ }
tag = dsa_etype_header_pos_rx(skb);
@@ -96,6 +98,7 @@ yt921x_tag_rcv(struct sk_buff *skb, struct net_device *netdev)
dev_warn_ratelimited(&netdev->dev,
"Unexpected EtherType 0x%04x\n",
ntohs(tag[0]));
+ kfree_skb(skb);
return NULL;
}
@@ -104,6 +107,7 @@ yt921x_tag_rcv(struct sk_buff *skb, struct net_device *netdev)
if (unlikely((rx & YT921X_TAG_PORT_EN) == 0)) {
dev_warn_ratelimited(&netdev->dev,
"Unexpected rx tag 0x%04x\n", rx);
+ kfree_skb(skb);
return NULL;
}
@@ -112,6 +116,7 @@ yt921x_tag_rcv(struct sk_buff *skb, struct net_device *netdev)
if (unlikely(!skb->dev)) {
dev_warn_ratelimited(&netdev->dev,
"Couldn't decode source port %u\n", port);
+ kfree_skb(skb);
return NULL;
}
diff --git a/net/dsa/user.c b/net/dsa/user.c
index 8704c1a3a5b741..072fa76972cc65 100644
--- a/net/dsa/user.c
+++ b/net/dsa/user.c
@@ -935,13 +935,12 @@ static netdev_tx_t dsa_user_xmit(struct sk_buff *skb, struct net_device *dev)
eth_skb_pad(skb);
/* Transmit function may have to reallocate the original SKB,
- * in which case it must have freed it. Only free it here on error.
+ * in which case it must have freed it. Taggers will drop the
+ * passed skb on error.
*/
nskb = p->xmit(skb, dev);
- if (!nskb) {
- kfree_skb(skb);
+ if (!nskb)
return NETDEV_TX_OK;
- }
return dsa_enqueue_skb(nskb, dev);
}
|
| 3/2 | 2026/06/25 08:29 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 18681 output: 21 thoughts: 417 Thoughts: **Analyzing the DSA SKB Memory Management Changes**
Okay, so I'm looking at this patch series touching `net/dsa/tag_*.c`, `net/dsa/user.c`, and `net/dsa/tag.c`. My initial read is that this is about SKB (Socket Buffer) memory management in the DSA (Distributed Switch Architecture) tagger functions. Specifically, it's about explicitly freeing the `skb` within the tagger functions themselves, instead of relying on the calling functions (`dsa_user_xmit`, `dsa_switch_rcv`) to handle it when a `NULL` is returned.
Let me just double-check that `dsa_user_xmit` code snippet to be sure:
```c
nskb = p->xmit(skb, dev);
- if (!nskb) {
- kfree_skb(skb);
+ if (!nskb)
return NETDEV_TX_OK;
- }
```
Yup, and similarly for `dsa_switch_rcv`...
```c
- if (!nskb) {
- kfree_skb(skb);
+ if (!nskb)
return 0;
- }
```
So the taggers are now calling `kfree_skb(skb)` *before* returning `NULL`. It's definitely a functional change, shifting where the memory is managed, though the intended functionality remains consistent. This is essentially a memory management refactoring in the DSA tagger code.
But here's the key question, does this *actually* change the execution flow? Yes, it does change where `kfree_skb` is called. That's the core of the change. Is this a code path that's even exercised in a virtualized environment or by fuzzers? DSA is a subsystem for Ethernet switches, so I need to think about if this is reachable. We need to consider how accessible this code is, particularly for security auditing.
Can we hit this in something like syzkaller? Syzkaller has some DSA support, or at least the ability to create dummy DSA interfaces using the `dsa_loop` driver. It's time to check if `CONFIG_NET_DSA` is enabled and how we can reach this code. I'll need to search for `dsa_loop` and `dsa_user_xmit` in relevant build configurations to confirm.
|
| 4/2 | 2026/06/25 08:29 | tool | grepper |
0mArgs:{
"Expression": "dsa_user_xmit"
}Results: {
"Output": "Documentation/networking/dsa/dsa.rst=317=LAG slave). Therefore, the RX data path of the LAG DSA conduit is not used.\nDocumentation/networking/dsa/dsa.rst:318:On the other hand, TX takes place linearly: ``dsa_user_xmit`` calls\nDocumentation/networking/dsa/dsa.rst-319-``dsa_enqueue_skb``, which calls ``dev_queue_xmit`` towards the LAG DSA conduit.\n--\nnet/dsa/user.c=911=EXPORT_SYMBOL_GPL(dsa_enqueue_skb);\nnet/dsa/user.c-912-\nnet/dsa/user.c:913:static netdev_tx_t dsa_user_xmit(struct sk_buff *skb, struct net_device *dev)\nnet/dsa/user.c-914-{\n--\nnet/dsa/user.c=2586=static const struct net_device_ops dsa_user_netdev_ops = {\n--\nnet/dsa/user.c-2588-\t.ndo_stop\t\t= dsa_user_close,\nnet/dsa/user.c:2589:\t.ndo_start_xmit\t\t= dsa_user_xmit,\nnet/dsa/user.c-2590-\t.ndo_change_rx_flags\t= dsa_user_change_rx_flags,\n"
} |
| 5/2 | 2026/06/25 08:29 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 20029 output: 18 thoughts: 121 Thoughts: **Fuzzing the DSA Tagging Code** Okay, let's take a look at this. My gut tells me this is ripe for fuzzing. The patch is touching `net/dsa/tag.c` and a few of the `net/dsa/tag_*.c` files, so it's all about DSA tagging. From a quick glance, the changes are centered around memory management – specifically, freeing `skb` in error paths. That instantly screams "potential memory leak or double free" to me. It’s definitely worth the effort to throw some fuzzing at it. Now, what's the appropriate setup? I'll need to enable `CONFIG_NET_DSA`, and probably some of the tagger-specific configurations too. Let me double-check the `net/dsa/Kconfig` file to be certain I have the right configuration. Time to make sure this code is robust. |
| 6/2 | 2026/06/25 08:29 | tool | grepper |
0mArgs:{
"Expression": "config NET_DSA"
}Results: {
"Output": "drivers/net/dsa/Kconfig=5=source \"drivers/net/dsa/b53/Kconfig\"\ndrivers/net/dsa/Kconfig-6-\ndrivers/net/dsa/Kconfig:7:config NET_DSA_BCM_SF2\ndrivers/net/dsa/Kconfig-8-\ttristate \"Broadcom Starfighter 2 Ethernet switch support\"\n--\ndrivers/net/dsa/Kconfig-18-\ndrivers/net/dsa/Kconfig:19:config NET_DSA_LOOP\ndrivers/net/dsa/Kconfig-20-\ttristate \"DSA mock-up Ethernet switch chip support\"\n--\ndrivers/net/dsa/Kconfig=29=source \"drivers/net/dsa/lantiq/Kconfig\"\ndrivers/net/dsa/Kconfig-30-\ndrivers/net/dsa/Kconfig:31:config NET_DSA_MT7530\ndrivers/net/dsa/Kconfig-32-\ttristate \"MediaTek MT7530 and MT7531 Ethernet switch support\"\n--\ndrivers/net/dsa/Kconfig-42-\ndrivers/net/dsa/Kconfig:43:config NET_DSA_MT7530_MDIO\ndrivers/net/dsa/Kconfig-44-\ttristate \"MediaTek MT7530 MDIO interface driver\"\n--\ndrivers/net/dsa/Kconfig-53-\ndrivers/net/dsa/Kconfig:54:config NET_DSA_MT7530_MMIO\ndrivers/net/dsa/Kconfig-55-\ttristate \"MediaTek MT7530 MMIO interface driver\"\n--\ndrivers/net/dsa/Kconfig-65-\ndrivers/net/dsa/Kconfig:66:config NET_DSA_MV88E6060\ndrivers/net/dsa/Kconfig-67-\ttristate \"Marvell 88E6060 ethernet switch chip support\"\n--\ndrivers/net/dsa/Kconfig=89=source \"drivers/net/dsa/realtek/Kconfig\"\ndrivers/net/dsa/Kconfig-90-\ndrivers/net/dsa/Kconfig:91:config NET_DSA_RZN1_A5PSW\ndrivers/net/dsa/Kconfig-92-\ttristate \"Renesas RZ/N1 A5PSW Ethernet switch support\"\n--\ndrivers/net/dsa/Kconfig-99-\ndrivers/net/dsa/Kconfig:100:config NET_DSA_KS8995\ndrivers/net/dsa/Kconfig-101-\ttristate \"Micrel KS8995 family 5-ports 10/100 Ethernet switches\"\n--\ndrivers/net/dsa/Kconfig-107-\ndrivers/net/dsa/Kconfig:108:config NET_DSA_SMSC_LAN9303\ndrivers/net/dsa/Kconfig-109-\ttristate\n--\ndrivers/net/dsa/Kconfig-116-\ndrivers/net/dsa/Kconfig:117:config NET_DSA_SMSC_LAN9303_I2C\ndrivers/net/dsa/Kconfig-118-\ttristate \"SMSC/Microchip LAN9303 3-ports 10/100 ethernet switch in I2C managed mode\"\n--\ndrivers/net/dsa/Kconfig-126-\ndrivers/net/dsa/Kconfig:127:config NET_DSA_SMSC_LAN9303_MDIO\ndrivers/net/dsa/Kconfig-128-\ttristate \"Microchip LAN9303/LAN9354 3-ports 10/100 ethernet switch in MDIO managed mode\"\n--\ndrivers/net/dsa/Kconfig-134-\ndrivers/net/dsa/Kconfig:135:config NET_DSA_VITESSE_VSC73XX\ndrivers/net/dsa/Kconfig-136-\ttristate\n--\ndrivers/net/dsa/Kconfig-144-\ndrivers/net/dsa/Kconfig:145:config NET_DSA_VITESSE_VSC73XX_SPI\ndrivers/net/dsa/Kconfig-146-\ttristate \"Vitesse VSC7385/7388/7395/7398 SPI mode support\"\n--\ndrivers/net/dsa/Kconfig-152-\ndrivers/net/dsa/Kconfig:153:config NET_DSA_VITESSE_VSC73XX_PLATFORM\ndrivers/net/dsa/Kconfig-154-\ttristate \"Vitesse VSC7385/7388/7395/7398 Platform mode support\"\n--\ndrivers/net/dsa/Kconfig-161-\ndrivers/net/dsa/Kconfig:162:config NET_DSA_YT921X\ndrivers/net/dsa/Kconfig-163-\ttristate \"Motorcomm YT9215 ethernet switch chip support\"\n--\ndrivers/net/dsa/hirschmann/Kconfig-1-# SPDX-License-Identifier: GPL-2.0\ndrivers/net/dsa/hirschmann/Kconfig:2:config NET_DSA_HIRSCHMANN_HELLCREEK\ndrivers/net/dsa/hirschmann/Kconfig-3-\ttristate \"Hirschmann Hellcreek TSN Switch support\"\n--\ndrivers/net/dsa/lantiq/Kconfig:1:config NET_DSA_LANTIQ_COMMON\ndrivers/net/dsa/lantiq/Kconfig-2-\ttristate\n--\ndrivers/net/dsa/lantiq/Kconfig-4-\ndrivers/net/dsa/lantiq/Kconfig:5:config NET_DSA_LANTIQ_GSWIP\ndrivers/net/dsa/lantiq/Kconfig-6-\ttristate \"Lantiq / Intel GSWIP\"\n--\ndrivers/net/dsa/lantiq/Kconfig-13-\ndrivers/net/dsa/lantiq/Kconfig:14:config NET_DSA_MXL_GSW1XX\ndrivers/net/dsa/lantiq/Kconfig-15-\ttristate \"MaxLinear GSW1xx Ethernet switch support\"\n--\ndrivers/net/dsa/microchip/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\ndrivers/net/dsa/microchip/Kconfig:2:menuconfig NET_DSA_MICROCHIP_KSZ_COMMON\ndrivers/net/dsa/microchip/Kconfig-3-\ttristate \"Microchip KSZ8XXX/KSZ9XXX/LAN937X series switch support\"\n--\ndrivers/net/dsa/microchip/Kconfig-16-\ndrivers/net/dsa/microchip/Kconfig:17:config NET_DSA_MICROCHIP_KSZ9477_I2C\ndrivers/net/dsa/microchip/Kconfig-18-\ttristate \"KSZ series I2C connected switch driver\"\n--\ndrivers/net/dsa/microchip/Kconfig-23-\ndrivers/net/dsa/microchip/Kconfig:24:config NET_DSA_MICROCHIP_KSZ_SPI\ndrivers/net/dsa/microchip/Kconfig-25-\ttristate \"KSZ series SPI connected switch driver\"\n--\ndrivers/net/dsa/microchip/Kconfig-30-\ndrivers/net/dsa/microchip/Kconfig:31:config NET_DSA_MICROCHIP_KSZ_PTP\ndrivers/net/dsa/microchip/Kconfig-32-\tbool \"Support for the PTP clock on the KSZ9563/LAN937x Ethernet Switch\"\n--\ndrivers/net/dsa/microchip/Kconfig-40-\ndrivers/net/dsa/microchip/Kconfig:41:config NET_DSA_MICROCHIP_KSZ8863_SMI\ndrivers/net/dsa/microchip/Kconfig-42-\ttristate \"KSZ series SMI connected switch driver\"\n--\ndrivers/net/dsa/mv88e6xxx/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\ndrivers/net/dsa/mv88e6xxx/Kconfig:2:config NET_DSA_MV88E6XXX\ndrivers/net/dsa/mv88e6xxx/Kconfig-3-\ttristate \"Marvell 88E6xxx Ethernet switch fabric support\"\n--\ndrivers/net/dsa/mv88e6xxx/Kconfig-11-\ndrivers/net/dsa/mv88e6xxx/Kconfig:12:config NET_DSA_MV88E6XXX_PTP\ndrivers/net/dsa/mv88e6xxx/Kconfig-13-\tbool \"PTP support for Marvell 88E6xxx\"\n--\ndrivers/net/dsa/mv88e6xxx/Kconfig-20-\ndrivers/net/dsa/mv88e6xxx/Kconfig:21:config NET_DSA_MV88E6XXX_LEDS\ndrivers/net/dsa/mv88e6xxx/Kconfig-22-\tbool \"LED support for Marvell 88E6xxx\"\n--\ndrivers/net/dsa/mxl862xx/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\ndrivers/net/dsa/mxl862xx/Kconfig:2:config NET_DSA_MXL862\ndrivers/net/dsa/mxl862xx/Kconfig-3-\ttristate \"MaxLinear MxL862xx\"\n--\ndrivers/net/dsa/netc/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\ndrivers/net/dsa/netc/Kconfig:2:config NET_DSA_NETC_SWITCH\ndrivers/net/dsa/netc/Kconfig-3-\ttristate \"NXP NETC Ethernet switch support\"\n--\ndrivers/net/dsa/ocelot/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\ndrivers/net/dsa/ocelot/Kconfig:2:config NET_DSA_MSCC_FELIX_DSA_LIB\ndrivers/net/dsa/ocelot/Kconfig-3-\ttristate\n--\ndrivers/net/dsa/ocelot/Kconfig-10-\ndrivers/net/dsa/ocelot/Kconfig:11:config NET_DSA_MSCC_OCELOT_EXT\ndrivers/net/dsa/ocelot/Kconfig-12-\ttristate \"Ocelot External Ethernet switch support\"\n--\ndrivers/net/dsa/ocelot/Kconfig-31-\ndrivers/net/dsa/ocelot/Kconfig:32:config NET_DSA_MSCC_FELIX\ndrivers/net/dsa/ocelot/Kconfig-33-\ttristate \"Ocelot / Felix Ethernet switch support\"\n--\ndrivers/net/dsa/ocelot/Kconfig-49-\ndrivers/net/dsa/ocelot/Kconfig:50:config NET_DSA_MSCC_SEVILLE\ndrivers/net/dsa/ocelot/Kconfig-51-\ttristate \"Ocelot / Seville Ethernet switch support\"\n--\ndrivers/net/dsa/qca/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\ndrivers/net/dsa/qca/Kconfig:2:config NET_DSA_AR9331\ndrivers/net/dsa/qca/Kconfig-3-\ttristate \"Qualcomm Atheros AR9331 Ethernet switch support\"\n--\ndrivers/net/dsa/qca/Kconfig-10-\ndrivers/net/dsa/qca/Kconfig:11:config NET_DSA_QCA8K\ndrivers/net/dsa/qca/Kconfig-12-\ttristate \"Qualcomm Atheros QCA8K Ethernet switch family support\"\n--\ndrivers/net/dsa/qca/Kconfig-18-\ndrivers/net/dsa/qca/Kconfig:19:config NET_DSA_QCA8K_LEDS_SUPPORT\ndrivers/net/dsa/qca/Kconfig-20-\tbool \"Qualcomm Atheros QCA8K Ethernet switch family LEDs support\"\n--\ndrivers/net/dsa/realtek/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\ndrivers/net/dsa/realtek/Kconfig:2:menuconfig NET_DSA_REALTEK\ndrivers/net/dsa/realtek/Kconfig-3-\ttristate \"Realtek Ethernet switch family support\"\n--\ndrivers/net/dsa/realtek/Kconfig=16=if NET_DSA_REALTEK\ndrivers/net/dsa/realtek/Kconfig-17-\ndrivers/net/dsa/realtek/Kconfig:18:config NET_DSA_REALTEK_MDIO\ndrivers/net/dsa/realtek/Kconfig-19-\tbool \"Realtek MDIO interface support\"\n--\ndrivers/net/dsa/realtek/Kconfig-24-\ndrivers/net/dsa/realtek/Kconfig:25:config NET_DSA_REALTEK_SMI\ndrivers/net/dsa/realtek/Kconfig-26-\tbool \"Realtek SMI interface support\"\n--\ndrivers/net/dsa/realtek/Kconfig-31-\ndrivers/net/dsa/realtek/Kconfig:32:config NET_DSA_REALTEK_RTL8365MB\ndrivers/net/dsa/realtek/Kconfig-33-\ttristate \"Realtek RTL8365MB switch driver\"\n--\ndrivers/net/dsa/realtek/Kconfig-38-\ndrivers/net/dsa/realtek/Kconfig:39:config NET_DSA_REALTEK_RTL8366RB\ndrivers/net/dsa/realtek/Kconfig-40-\ttristate \"Realtek RTL8366RB switch driver\"\n--\ndrivers/net/dsa/realtek/Kconfig-45-\ndrivers/net/dsa/realtek/Kconfig:46:config NET_DSA_REALTEK_RTL8366RB_LEDS\ndrivers/net/dsa/realtek/Kconfig-47-\tbool\n--\ndrivers/net/dsa/sja1105/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\ndrivers/net/dsa/sja1105/Kconfig:2:config NET_DSA_SJA1105\ndrivers/net/dsa/sja1105/Kconfig-3-tristate \"NXP SJA1105 Ethernet switch family support\"\n--\ndrivers/net/dsa/sja1105/Kconfig-25-\ndrivers/net/dsa/sja1105/Kconfig:26:config NET_DSA_SJA1105_PTP\ndrivers/net/dsa/sja1105/Kconfig-27-\tbool \"Support for the PTP clock on the NXP SJA1105 Ethernet switch\"\n--\ndrivers/net/dsa/sja1105/Kconfig-33-\ndrivers/net/dsa/sja1105/Kconfig:34:config NET_DSA_SJA1105_TAS\ndrivers/net/dsa/sja1105/Kconfig-35-\tbool \"Support for the Time-Aware Scheduler on NXP SJA1105\"\n--\ndrivers/net/dsa/sja1105/Kconfig-43-\ndrivers/net/dsa/sja1105/Kconfig:44:config NET_DSA_SJA1105_VL\ndrivers/net/dsa/sja1105/Kconfig-45-\tbool \"Support for Virtual Links on NXP SJA1105\"\n--\ndrivers/net/dsa/xrs700x/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\ndrivers/net/dsa/xrs700x/Kconfig:2:config NET_DSA_XRS700X\ndrivers/net/dsa/xrs700x/Kconfig-3-\ttristate\n--\ndrivers/net/dsa/xrs700x/Kconfig-10-\ndrivers/net/dsa/xrs700x/Kconfig:11:config NET_DSA_XRS700X_I2C\ndrivers/net/dsa/xrs700x/Kconfig-12-\ttristate \"Arrow XRS7000X series switch in I2C mode\"\n--\ndrivers/net/dsa/xrs700x/Kconfig-19-\ndrivers/net/dsa/xrs700x/Kconfig:20:config NET_DSA_XRS700X_MDIO\ndrivers/net/dsa/xrs700x/Kconfig-21-\ttristate \"Arrow XRS7000X series switch in MDIO mode\"\n--\nnet/dsa/Kconfig-2-\nnet/dsa/Kconfig:3:menuconfig NET_DSA\nnet/dsa/Kconfig-4-\ttristate \"Distributed Switch Architecture\"\n--\nnet/dsa/Kconfig=17=if NET_DSA\n--\nnet/dsa/Kconfig-20-\nnet/dsa/Kconfig:21:config NET_DSA_TAG_NONE\nnet/dsa/Kconfig-22-\ttristate \"No-op tag driver\"\n--\nnet/dsa/Kconfig-26-\nnet/dsa/Kconfig:27:config NET_DSA_TAG_AR9331\nnet/dsa/Kconfig-28-\ttristate \"Tag driver for Atheros AR9331 SoC with built-in switch\"\n--\nnet/dsa/Kconfig-32-\nnet/dsa/Kconfig:33:config NET_DSA_TAG_BRCM_COMMON\nnet/dsa/Kconfig-34-\ttristate\n--\nnet/dsa/Kconfig-36-\nnet/dsa/Kconfig:37:config NET_DSA_TAG_BRCM\nnet/dsa/Kconfig-38-\ttristate \"Tag driver for Broadcom switches using in-frame headers\"\n--\nnet/dsa/Kconfig-43-\nnet/dsa/Kconfig:44:config NET_DSA_TAG_BRCM_LEGACY\nnet/dsa/Kconfig-45-\ttristate \"Tag driver for BCM63xx legacy switches using in-frame headers\"\n--\nnet/dsa/Kconfig-53-\nnet/dsa/Kconfig:54:config NET_DSA_TAG_BRCM_LEGACY_FCS\nnet/dsa/Kconfig-55-\ttristate \"Tag driver for BCM53xx legacy switches using in-frame headers\"\n--\nnet/dsa/Kconfig-63-\nnet/dsa/Kconfig:64:config NET_DSA_TAG_BRCM_PREPEND\nnet/dsa/Kconfig-65-\ttristate \"Tag driver for Broadcom switches using prepended headers\"\n--\nnet/dsa/Kconfig-71-\nnet/dsa/Kconfig:72:config NET_DSA_TAG_HELLCREEK\nnet/dsa/Kconfig-73-\ttristate \"Tag driver for Hirschmann Hellcreek TSN switches\"\n--\nnet/dsa/Kconfig-77-\nnet/dsa/Kconfig:78:config NET_DSA_TAG_GSWIP\nnet/dsa/Kconfig-79-\ttristate \"Tag driver for Lantiq / Intel GSWIP switches\"\n--\nnet/dsa/Kconfig-83-\nnet/dsa/Kconfig:84:config NET_DSA_TAG_DSA_COMMON\nnet/dsa/Kconfig-85-\ttristate\nnet/dsa/Kconfig-86-\nnet/dsa/Kconfig:87:config NET_DSA_TAG_DSA\nnet/dsa/Kconfig-88-\ttristate \"Tag driver for Marvell switches using DSA headers\"\n--\nnet/dsa/Kconfig-93-\nnet/dsa/Kconfig:94:config NET_DSA_TAG_EDSA\nnet/dsa/Kconfig-95-\ttristate \"Tag driver for Marvell switches using EtherType DSA headers\"\n--\nnet/dsa/Kconfig-100-\nnet/dsa/Kconfig:101:config NET_DSA_TAG_MTK\nnet/dsa/Kconfig-102-\ttristate \"Tag driver for Mediatek switches\"\n--\nnet/dsa/Kconfig-106-\nnet/dsa/Kconfig:107:config NET_DSA_TAG_MXL_862XX\nnet/dsa/Kconfig-108-\ttristate \"Tag driver for MaxLinear MxL862xx switches\"\n--\nnet/dsa/Kconfig-113-\nnet/dsa/Kconfig:114:config NET_DSA_TAG_MXL_GSW1XX\nnet/dsa/Kconfig-115-\ttristate \"Tag driver for MaxLinear GSW1xx switches\"\n--\nnet/dsa/Kconfig-121-\nnet/dsa/Kconfig:122:config NET_DSA_TAG_KSZ\nnet/dsa/Kconfig-123-\ttristate \"Tag driver for Microchip 8795/937x/9477/9893 families of switches\"\n--\nnet/dsa/Kconfig-127-\nnet/dsa/Kconfig:128:config NET_DSA_TAG_NETC\nnet/dsa/Kconfig-129-\ttristate \"Tag driver for NXP NETC switches\"\n--\nnet/dsa/Kconfig-137-\nnet/dsa/Kconfig:138:config NET_DSA_TAG_OCELOT\nnet/dsa/Kconfig-139-\ttristate \"Tag driver for Ocelot family of switches, using NPI port\"\n--\nnet/dsa/Kconfig-148-\nnet/dsa/Kconfig:149:config NET_DSA_TAG_OCELOT_8021Q\nnet/dsa/Kconfig-150-\ttristate \"Tag driver for Ocelot family of switches, using VLAN\"\n--\nnet/dsa/Kconfig-158-\nnet/dsa/Kconfig:159:config NET_DSA_TAG_QCA\nnet/dsa/Kconfig-160-\ttristate \"Tag driver for Qualcomm Atheros QCA8K switches\"\n--\nnet/dsa/Kconfig-164-\nnet/dsa/Kconfig:165:config NET_DSA_TAG_RTL4_A\nnet/dsa/Kconfig-166-\ttristate \"Tag driver for Realtek 4 byte protocol A tags\"\n--\nnet/dsa/Kconfig-171-\nnet/dsa/Kconfig:172:config NET_DSA_TAG_RTL8_4\nnet/dsa/Kconfig-173-\ttristate \"Tag driver for Realtek 8 byte protocol 4 tags\"\n--\nnet/dsa/Kconfig-177-\nnet/dsa/Kconfig:178:config NET_DSA_TAG_RZN1_A5PSW\nnet/dsa/Kconfig-179-\ttristate \"Tag driver for Renesas RZ/N1 A5PSW switch\"\n--\nnet/dsa/Kconfig-184-\nnet/dsa/Kconfig:185:config NET_DSA_TAG_LAN9303\nnet/dsa/Kconfig-186-\ttristate \"Tag driver for SMSC/Microchip LAN9303 family of switches\"\n--\nnet/dsa/Kconfig-190-\nnet/dsa/Kconfig:191:config NET_DSA_TAG_SJA1105\nnet/dsa/Kconfig-192-\ttristate \"Tag driver for NXP SJA1105 switches\"\n--\nnet/dsa/Kconfig-199-\nnet/dsa/Kconfig:200:config NET_DSA_TAG_TRAILER\nnet/dsa/Kconfig-201-\ttristate \"Tag driver for switches using a trailer tag\"\n--\nnet/dsa/Kconfig-205-\nnet/dsa/Kconfig:206:config NET_DSA_TAG_VSC73XX_8021Q\nnet/dsa/Kconfig-207-\ttristate \"Tag driver for Microchip/Vitesse VSC73xx family of switches, using VLAN\"\n--\nnet/dsa/Kconfig-211-\nnet/dsa/Kconfig:212:config NET_DSA_TAG_XRS700X\nnet/dsa/Kconfig-213-\ttristate \"Tag driver for XRS700x switches\"\n--\nnet/dsa/Kconfig-217-\nnet/dsa/Kconfig:218:config NET_DSA_TAG_YT921X\nnet/dsa/Kconfig-219-\ttristate \"Tag driver for Motorcomm YT921x switches\"\n"
} |
| 7/2 | 2026/06/25 08:29 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 26689 output: 20 thoughts: 57 Thoughts: **Enabling DSA for Fuzzing** Okay, so we're looking to expand our fuzzing capabilities within the networking stack. My initial thought is we need to enable `NET_DSA` and also some of those taggers. But hold on, I remember `NET_DSA_LOOP` – that's the mock-up switch chip support, isn't it? Bingo! That's a perfect candidate for deeper DSA fuzzing. The simulated environment it provides seems ideal. Now, before we dive in, I need to confirm the dependencies for `NET_DSA_LOOP`. Let me quickly check those… gotta make sure everything is in place to minimize any setup headaches. |
| 8/2 | 2026/06/25 08:29 | tool | grepper |
0mArgs:{
"Expression": "config NET_DSA_LOOP"
}Results: {
"Output": "drivers/net/dsa/Kconfig=7=config NET_DSA_BCM_SF2\n--\ndrivers/net/dsa/Kconfig-18-\ndrivers/net/dsa/Kconfig:19:config NET_DSA_LOOP\ndrivers/net/dsa/Kconfig-20-\ttristate \"DSA mock-up Ethernet switch chip support\"\n"
} |
| 9/2 | 2026/06/25 08:29 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 27007 output: 36 thoughts: 24 Thoughts: Here's my thought process, summarized as you requested: **Navigating the Codebase: NET_DSA_LOOP Configuration** Okay, so I need to understand the configuration related to the `NET_DSA_LOOP` functionality within the network DSA subsystem. Where would the relevant settings be defined? My initial instinct is to go straight to the configuration files. Given the nature of this feature, I'm expecting to find it within the `drivers/net/dsa` directory, which is the standard location for DSA (Distributed Switch Architecture) related drivers. More specifically, I should be able to dig around in `Kconfig` files for configuration options. Therefore, I will check the `drivers/net/dsa/Kconfig` file. That's the most logical starting point for understanding how this feature is enabled, disabled, and configured. I'm expecting to find a conditional statement or definition associated with `NET_DSA_LOOP` in there. Let's see what's in `drivers/net/dsa/Kconfig`. |
| 10/2 | 2026/06/25 08:29 | tool | read-file |
0mArgs:{
"File": "drivers/net/dsa/Kconfig",
"FirstLine": 15,
"LineCount": 20
}Results: {
"Contents": " 15:\t\thelp\n 16:\t\t This enables support for the Broadcom Starfighter 2 Ethernet\n 17:\t\t switch chips.\n 18:\t\n 19:\tconfig NET_DSA_LOOP\n 20:\t\ttristate \"DSA mock-up Ethernet switch chip support\"\n 21:\t\tselect NET_DSA_TAG_NONE\n 22:\t\tselect FIXED_PHY\n 23:\t\thelp\n 24:\t\t This enables support for a fake mock-up switch chip which\n 25:\t\t exercises the DSA APIs.\n 26:\t\n 27:\tsource \"drivers/net/dsa/hirschmann/Kconfig\"\n 28:\t\n 29:\tsource \"drivers/net/dsa/lantiq/Kconfig\"\n 30:\t\n 31:\tconfig NET_DSA_MT7530\n 32:\t\ttristate \"MediaTek MT7530 and MT7531 Ethernet switch support\"\n 33:\t\tselect NET_DSA_TAG_MTK\n 34:\t\tselect REGMAP_IRQ\n"
} |
| 11/2 | 2026/06/25 08:29 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 27565 output: 18 thoughts: 82 Thoughts: **Investigating the DSA Loop and Tagging Options** Okay, so `NET_DSA_LOOP` is configured to use `NET_DSA_TAG_NONE` by default. That's fine, but this patch seems to be touching all the other taggers. If we're serious about fuzzing these other taggers, then it's pretty clear we need to enable them. But the real question is, can we *actually* use any of these other taggers in conjunction with `dsa_loop`? I need to figure out if there's any kind of compatibility here. My first stop? Let's dive right into the code itself. I'm going to check `drivers/net/dsa/dsa_loop.c` and see if there are any hints or configuration options in there that would allow for different taggers to work. I'm expecting to find some indication of how the tagger is selected, or if there is a way to override this behaviour. |
| 12/2 | 2026/06/25 08:29 | tool | grepper |
0mArgs:{
"Expression": "dsa_loop"
}Results: {
"Output": "Documentation/networking/dsa/dsa.rst=159=all attached switch ports must be down while doing this).\nDocumentation/networking/dsa/dsa.rst-160-\nDocumentation/networking/dsa/dsa.rst:161:It is desirable that all tagging protocols are testable with the ``dsa_loop``\nDocumentation/networking/dsa/dsa.rst-162-mockup driver, which can be attached to any network interface. The goal is that\n--\ndrivers/net/dsa/Makefile=3=bcm-sf2-objs\t\t\t:= bcm_sf2.o bcm_sf2_cfp.o\ndrivers/net/dsa/Makefile:4:obj-$(CONFIG_NET_DSA_LOOP)\t+= dsa_loop.o\ndrivers/net/dsa/Makefile-5-obj-$(CONFIG_NET_DSA_KS8995) \t+= ks8995.o\n--\ndrivers/net/dsa/dsa_loop.c-24-\ndrivers/net/dsa/dsa_loop.c:25:struct dsa_loop_vlan {\ndrivers/net/dsa/dsa_loop.c-26-\tu16 members;\n--\ndrivers/net/dsa/dsa_loop.c-29-\ndrivers/net/dsa/dsa_loop.c:30:struct dsa_loop_mib_entry {\ndrivers/net/dsa/dsa_loop.c-31-\tchar name[ETH_GSTRING_LEN];\n--\ndrivers/net/dsa/dsa_loop.c-34-\ndrivers/net/dsa/dsa_loop.c:35:enum dsa_loop_mib_counters {\ndrivers/net/dsa/dsa_loop.c-36-\tDSA_LOOP_PHY_READ_OK,\n--\ndrivers/net/dsa/dsa_loop.c-42-\ndrivers/net/dsa/dsa_loop.c:43:struct dsa_loop_port {\ndrivers/net/dsa/dsa_loop.c:44:\tstruct dsa_loop_mib_entry mib[__DSA_LOOP_CNT_MAX];\ndrivers/net/dsa/dsa_loop.c-45-\tu16 pvid;\n--\ndrivers/net/dsa/dsa_loop.c-48-\ndrivers/net/dsa/dsa_loop.c:49:struct dsa_loop_priv {\ndrivers/net/dsa/dsa_loop.c-50-\tstruct mii_bus\t*bus;\ndrivers/net/dsa/dsa_loop.c-51-\tunsigned int\tport_base;\ndrivers/net/dsa/dsa_loop.c:52:\tstruct dsa_loop_vlan vlans[VLAN_N_VID];\ndrivers/net/dsa/dsa_loop.c-53-\tstruct net_device *netdev;\ndrivers/net/dsa/dsa_loop.c:54:\tstruct dsa_loop_port ports[DSA_MAX_PORTS];\ndrivers/net/dsa/dsa_loop.c-55-};\ndrivers/net/dsa/dsa_loop.c-56-\ndrivers/net/dsa/dsa_loop.c:57:struct dsa_loop_pdata {\ndrivers/net/dsa/dsa_loop.c-58-\t/* Must be first, such that dsa_register_switch() can access this\n--\ndrivers/net/dsa/dsa_loop.c-66-\ndrivers/net/dsa/dsa_loop.c:67:static struct dsa_loop_mib_entry dsa_loop_mibs[] = {\ndrivers/net/dsa/dsa_loop.c-68-\t[DSA_LOOP_PHY_READ_OK]\t= { \"phy_read_ok\", },\n--\ndrivers/net/dsa/dsa_loop.c=75=static struct mdio_device *switch_mdiodev;\ndrivers/net/dsa/dsa_loop.c-76-\ndrivers/net/dsa/dsa_loop.c:77:enum dsa_loop_devlink_resource_id {\ndrivers/net/dsa/dsa_loop.c-78-\tDSA_LOOP_DEVLINK_PARAM_ID_NONE, /* DEVLINK_RESOURCE_ID_PARENT_TOP */\n--\ndrivers/net/dsa/dsa_loop.c-81-\ndrivers/net/dsa/dsa_loop.c:82:static u64 dsa_loop_devlink_vtu_get(void *priv)\ndrivers/net/dsa/dsa_loop.c-83-{\ndrivers/net/dsa/dsa_loop.c:84:\tstruct dsa_loop_priv *ps = priv;\ndrivers/net/dsa/dsa_loop.c-85-\tunsigned int i, count = 0;\ndrivers/net/dsa/dsa_loop.c:86:\tstruct dsa_loop_vlan *vl;\ndrivers/net/dsa/dsa_loop.c-87-\n--\ndrivers/net/dsa/dsa_loop.c-96-\ndrivers/net/dsa/dsa_loop.c:97:static int dsa_loop_setup_devlink_resources(struct dsa_switch *ds)\ndrivers/net/dsa/dsa_loop.c-98-{\ndrivers/net/dsa/dsa_loop.c-99-\tstruct devlink_resource_size_params size_params;\ndrivers/net/dsa/dsa_loop.c:100:\tstruct dsa_loop_priv *ps = ds-\u003epriv;\ndrivers/net/dsa/dsa_loop.c-101-\tint err;\n--\ndrivers/net/dsa/dsa_loop.c-115-\t\t\t\t\t DSA_LOOP_DEVLINK_PARAM_ID_VTU,\ndrivers/net/dsa/dsa_loop.c:116:\t\t\t\t\t dsa_loop_devlink_vtu_get, ps);\ndrivers/net/dsa/dsa_loop.c-117-\n--\ndrivers/net/dsa/dsa_loop.c-124-\ndrivers/net/dsa/dsa_loop.c:125:static enum dsa_tag_protocol dsa_loop_get_protocol(struct dsa_switch *ds,\ndrivers/net/dsa/dsa_loop.c-126-\t\t\t\t\t\t int port,\n--\ndrivers/net/dsa/dsa_loop.c-133-\ndrivers/net/dsa/dsa_loop.c:134:static int dsa_loop_setup(struct dsa_switch *ds)\ndrivers/net/dsa/dsa_loop.c-135-{\ndrivers/net/dsa/dsa_loop.c:136:\tstruct dsa_loop_priv *ps = ds-\u003epriv;\ndrivers/net/dsa/dsa_loop.c-137-\tunsigned int i;\n--\ndrivers/net/dsa/dsa_loop.c-139-\tfor (i = 0; i \u003c ds-\u003enum_ports; i++)\ndrivers/net/dsa/dsa_loop.c:140:\t\tmemcpy(ps-\u003eports[i].mib, dsa_loop_mibs,\ndrivers/net/dsa/dsa_loop.c:141:\t\t sizeof(dsa_loop_mibs));\ndrivers/net/dsa/dsa_loop.c-142-\n--\ndrivers/net/dsa/dsa_loop.c-144-\ndrivers/net/dsa/dsa_loop.c:145:\treturn dsa_loop_setup_devlink_resources(ds);\ndrivers/net/dsa/dsa_loop.c-146-}\ndrivers/net/dsa/dsa_loop.c-147-\ndrivers/net/dsa/dsa_loop.c:148:static void dsa_loop_teardown(struct dsa_switch *ds)\ndrivers/net/dsa/dsa_loop.c-149-{\n--\ndrivers/net/dsa/dsa_loop.c-152-\ndrivers/net/dsa/dsa_loop.c:153:static int dsa_loop_get_sset_count(struct dsa_switch *ds, int port, int sset)\ndrivers/net/dsa/dsa_loop.c-154-{\n--\ndrivers/net/dsa/dsa_loop.c-160-\ndrivers/net/dsa/dsa_loop.c:161:static void dsa_loop_get_strings(struct dsa_switch *ds, int port,\ndrivers/net/dsa/dsa_loop.c-162-\t\t\t\t u32 stringset, uint8_t *data)\ndrivers/net/dsa/dsa_loop.c-163-{\ndrivers/net/dsa/dsa_loop.c:164:\tstruct dsa_loop_priv *ps = ds-\u003epriv;\ndrivers/net/dsa/dsa_loop.c-165-\tunsigned int i;\n--\ndrivers/net/dsa/dsa_loop.c-173-\ndrivers/net/dsa/dsa_loop.c:174:static void dsa_loop_get_ethtool_stats(struct dsa_switch *ds, int port,\ndrivers/net/dsa/dsa_loop.c-175-\t\t\t\t uint64_t *data)\ndrivers/net/dsa/dsa_loop.c-176-{\ndrivers/net/dsa/dsa_loop.c:177:\tstruct dsa_loop_priv *ps = ds-\u003epriv;\ndrivers/net/dsa/dsa_loop.c-178-\tunsigned int i;\n--\ndrivers/net/dsa/dsa_loop.c-183-\ndrivers/net/dsa/dsa_loop.c:184:static int dsa_loop_phy_read(struct dsa_switch *ds, int port, int regnum)\ndrivers/net/dsa/dsa_loop.c-185-{\ndrivers/net/dsa/dsa_loop.c:186:\tstruct dsa_loop_priv *ps = ds-\u003epriv;\ndrivers/net/dsa/dsa_loop.c-187-\tstruct mii_bus *bus = ps-\u003ebus;\n--\ndrivers/net/dsa/dsa_loop.c-198-\ndrivers/net/dsa/dsa_loop.c:199:static int dsa_loop_phy_write(struct dsa_switch *ds, int port,\ndrivers/net/dsa/dsa_loop.c-200-\t\t\t int regnum, u16 value)\ndrivers/net/dsa/dsa_loop.c-201-{\ndrivers/net/dsa/dsa_loop.c:202:\tstruct dsa_loop_priv *ps = ds-\u003epriv;\ndrivers/net/dsa/dsa_loop.c-203-\tstruct mii_bus *bus = ps-\u003ebus;\n--\ndrivers/net/dsa/dsa_loop.c-214-\ndrivers/net/dsa/dsa_loop.c:215:static int dsa_loop_port_bridge_join(struct dsa_switch *ds, int port,\ndrivers/net/dsa/dsa_loop.c-216-\t\t\t\t struct dsa_bridge bridge,\n--\ndrivers/net/dsa/dsa_loop.c-225-\ndrivers/net/dsa/dsa_loop.c:226:static void dsa_loop_port_bridge_leave(struct dsa_switch *ds, int port,\ndrivers/net/dsa/dsa_loop.c-227-\t\t\t\t struct dsa_bridge bridge)\n--\ndrivers/net/dsa/dsa_loop.c-232-\ndrivers/net/dsa/dsa_loop.c:233:static void dsa_loop_port_stp_state_set(struct dsa_switch *ds, int port,\ndrivers/net/dsa/dsa_loop.c-234-\t\t\t\t\tu8 state)\n--\ndrivers/net/dsa/dsa_loop.c-239-\ndrivers/net/dsa/dsa_loop.c:240:static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port,\ndrivers/net/dsa/dsa_loop.c-241-\t\t\t\t\tbool vlan_filtering,\n--\ndrivers/net/dsa/dsa_loop.c-249-\ndrivers/net/dsa/dsa_loop.c:250:static int dsa_loop_port_vlan_add(struct dsa_switch *ds, int port,\ndrivers/net/dsa/dsa_loop.c-251-\t\t\t\t const struct switchdev_obj_port_vlan *vlan,\n--\ndrivers/net/dsa/dsa_loop.c-255-\tbool pvid = vlan-\u003eflags \u0026 BRIDGE_VLAN_INFO_PVID;\ndrivers/net/dsa/dsa_loop.c:256:\tstruct dsa_loop_priv *ps = ds-\u003epriv;\ndrivers/net/dsa/dsa_loop.c-257-\tstruct mii_bus *bus = ps-\u003ebus;\ndrivers/net/dsa/dsa_loop.c:258:\tstruct dsa_loop_vlan *vl;\ndrivers/net/dsa/dsa_loop.c-259-\n--\ndrivers/net/dsa/dsa_loop.c-282-\ndrivers/net/dsa/dsa_loop.c:283:static int dsa_loop_port_vlan_del(struct dsa_switch *ds, int port,\ndrivers/net/dsa/dsa_loop.c-284-\t\t\t\t const struct switchdev_obj_port_vlan *vlan)\n--\ndrivers/net/dsa/dsa_loop.c-286-\tbool untagged = vlan-\u003eflags \u0026 BRIDGE_VLAN_INFO_UNTAGGED;\ndrivers/net/dsa/dsa_loop.c:287:\tstruct dsa_loop_priv *ps = ds-\u003epriv;\ndrivers/net/dsa/dsa_loop.c-288-\tu16 pvid = ps-\u003eports[port].pvid;\ndrivers/net/dsa/dsa_loop.c-289-\tstruct mii_bus *bus = ps-\u003ebus;\ndrivers/net/dsa/dsa_loop.c:290:\tstruct dsa_loop_vlan *vl;\ndrivers/net/dsa/dsa_loop.c-291-\n--\ndrivers/net/dsa/dsa_loop.c-310-\ndrivers/net/dsa/dsa_loop.c:311:static int dsa_loop_port_change_mtu(struct dsa_switch *ds, int port,\ndrivers/net/dsa/dsa_loop.c-312-\t\t\t\t int new_mtu)\ndrivers/net/dsa/dsa_loop.c-313-{\ndrivers/net/dsa/dsa_loop.c:314:\tstruct dsa_loop_priv *priv = ds-\u003epriv;\ndrivers/net/dsa/dsa_loop.c-315-\n--\ndrivers/net/dsa/dsa_loop.c-320-\ndrivers/net/dsa/dsa_loop.c:321:static int dsa_loop_port_max_mtu(struct dsa_switch *ds, int port)\ndrivers/net/dsa/dsa_loop.c-322-{\n--\ndrivers/net/dsa/dsa_loop.c-325-\ndrivers/net/dsa/dsa_loop.c:326:static void dsa_loop_phylink_get_caps(struct dsa_switch *dsa, int port,\ndrivers/net/dsa/dsa_loop.c-327-\t\t\t\t struct phylink_config *config)\n--\ndrivers/net/dsa/dsa_loop.c-333-\ndrivers/net/dsa/dsa_loop.c:334:static const struct dsa_switch_ops dsa_loop_driver = {\ndrivers/net/dsa/dsa_loop.c:335:\t.get_tag_protocol\t= dsa_loop_get_protocol,\ndrivers/net/dsa/dsa_loop.c:336:\t.setup\t\t\t= dsa_loop_setup,\ndrivers/net/dsa/dsa_loop.c:337:\t.teardown\t\t= dsa_loop_teardown,\ndrivers/net/dsa/dsa_loop.c:338:\t.get_strings\t\t= dsa_loop_get_strings,\ndrivers/net/dsa/dsa_loop.c:339:\t.get_ethtool_stats\t= dsa_loop_get_ethtool_stats,\ndrivers/net/dsa/dsa_loop.c:340:\t.get_sset_count\t\t= dsa_loop_get_sset_count,\ndrivers/net/dsa/dsa_loop.c:341:\t.get_ethtool_phy_stats\t= dsa_loop_get_ethtool_stats,\ndrivers/net/dsa/dsa_loop.c:342:\t.phy_read\t\t= dsa_loop_phy_read,\ndrivers/net/dsa/dsa_loop.c:343:\t.phy_write\t\t= dsa_loop_phy_write,\ndrivers/net/dsa/dsa_loop.c:344:\t.port_bridge_join\t= dsa_loop_port_bridge_join,\ndrivers/net/dsa/dsa_loop.c:345:\t.port_bridge_leave\t= dsa_loop_port_bridge_leave,\ndrivers/net/dsa/dsa_loop.c:346:\t.port_stp_state_set\t= dsa_loop_port_stp_state_set,\ndrivers/net/dsa/dsa_loop.c:347:\t.port_vlan_filtering\t= dsa_loop_port_vlan_filtering,\ndrivers/net/dsa/dsa_loop.c:348:\t.port_vlan_add\t\t= dsa_loop_port_vlan_add,\ndrivers/net/dsa/dsa_loop.c:349:\t.port_vlan_del\t\t= dsa_loop_port_vlan_del,\ndrivers/net/dsa/dsa_loop.c:350:\t.port_change_mtu\t= dsa_loop_port_change_mtu,\ndrivers/net/dsa/dsa_loop.c:351:\t.port_max_mtu\t\t= dsa_loop_port_max_mtu,\ndrivers/net/dsa/dsa_loop.c:352:\t.phylink_get_caps\t= dsa_loop_phylink_get_caps,\ndrivers/net/dsa/dsa_loop.c-353-};\ndrivers/net/dsa/dsa_loop.c-354-\ndrivers/net/dsa/dsa_loop.c:355:static int dsa_loop_drv_probe(struct mdio_device *mdiodev)\ndrivers/net/dsa/dsa_loop.c-356-{\ndrivers/net/dsa/dsa_loop.c:357:\tstruct dsa_loop_pdata *pdata = mdiodev-\u003edev.platform_data;\ndrivers/net/dsa/dsa_loop.c:358:\tstruct dsa_loop_priv *ps;\ndrivers/net/dsa/dsa_loop.c-359-\tstruct dsa_switch *ds;\n--\ndrivers/net/dsa/dsa_loop.c-382-\tds-\u003edev = \u0026mdiodev-\u003edev;\ndrivers/net/dsa/dsa_loop.c:383:\tds-\u003eops = \u0026dsa_loop_driver;\ndrivers/net/dsa/dsa_loop.c-384-\tds-\u003epriv = ps;\n--\ndrivers/net/dsa/dsa_loop.c-396-\ndrivers/net/dsa/dsa_loop.c:397:static void dsa_loop_drv_remove(struct mdio_device *mdiodev)\ndrivers/net/dsa/dsa_loop.c-398-{\ndrivers/net/dsa/dsa_loop.c-399-\tstruct dsa_switch *ds = dev_get_drvdata(\u0026mdiodev-\u003edev);\ndrivers/net/dsa/dsa_loop.c:400:\tstruct dsa_loop_priv *ps;\ndrivers/net/dsa/dsa_loop.c-401-\n--\ndrivers/net/dsa/dsa_loop.c-410-\ndrivers/net/dsa/dsa_loop.c:411:static void dsa_loop_drv_shutdown(struct mdio_device *mdiodev)\ndrivers/net/dsa/dsa_loop.c-412-{\n--\ndrivers/net/dsa/dsa_loop.c-422-\ndrivers/net/dsa/dsa_loop.c:423:static struct mdio_driver dsa_loop_drv = {\ndrivers/net/dsa/dsa_loop.c-424-\t.mdiodrv.driver\t= {\n--\ndrivers/net/dsa/dsa_loop.c-426-\t},\ndrivers/net/dsa/dsa_loop.c:427:\t.probe\t= dsa_loop_drv_probe,\ndrivers/net/dsa/dsa_loop.c:428:\t.remove\t= dsa_loop_drv_remove,\ndrivers/net/dsa/dsa_loop.c:429:\t.shutdown = dsa_loop_drv_shutdown,\ndrivers/net/dsa/dsa_loop.c-430-};\ndrivers/net/dsa/dsa_loop.c-431-\ndrivers/net/dsa/dsa_loop.c:432:static int dsa_loop_bus_match(struct device *dev,\ndrivers/net/dsa/dsa_loop.c-433-\t\t\t const struct device_driver *drv)\ndrivers/net/dsa/dsa_loop.c-434-{\ndrivers/net/dsa/dsa_loop.c:435:\treturn drv == \u0026dsa_loop_drv.mdiodrv.driver;\ndrivers/net/dsa/dsa_loop.c-436-}\ndrivers/net/dsa/dsa_loop.c-437-\ndrivers/net/dsa/dsa_loop.c:438:static void dsa_loop_phydevs_unregister(void)\ndrivers/net/dsa/dsa_loop.c-439-{\n--\ndrivers/net/dsa/dsa_loop.c-445-\ndrivers/net/dsa/dsa_loop.c:446:static int __init dsa_loop_create_switch_mdiodev(void)\ndrivers/net/dsa/dsa_loop.c-447-{\ndrivers/net/dsa/dsa_loop.c:448:\tstatic struct dsa_loop_pdata dsa_loop_pdata = {\ndrivers/net/dsa/dsa_loop.c-449-\t\t.cd = {\n--\ndrivers/net/dsa/dsa_loop.c-470-\ndrivers/net/dsa/dsa_loop.c:471:\tswitch_mdiodev-\u003ebus_match = dsa_loop_bus_match;\ndrivers/net/dsa/dsa_loop.c:472:\tswitch_mdiodev-\u003edev.platform_data = \u0026dsa_loop_pdata;\ndrivers/net/dsa/dsa_loop.c-473-\n--\ndrivers/net/dsa/dsa_loop.c-481-\ndrivers/net/dsa/dsa_loop.c:482:static int __init dsa_loop_init(void)\ndrivers/net/dsa/dsa_loop.c-483-{\n--\ndrivers/net/dsa/dsa_loop.c-486-\ndrivers/net/dsa/dsa_loop.c:487:\tret = dsa_loop_create_switch_mdiodev();\ndrivers/net/dsa/dsa_loop.c-488-\tif (ret)\n--\ndrivers/net/dsa/dsa_loop.c-493-\ndrivers/net/dsa/dsa_loop.c:494:\tret = mdio_driver_register(\u0026dsa_loop_drv);\ndrivers/net/dsa/dsa_loop.c-495-\tif (ret) {\ndrivers/net/dsa/dsa_loop.c:496:\t\tdsa_loop_phydevs_unregister();\ndrivers/net/dsa/dsa_loop.c-497-\t\tmdio_device_remove(switch_mdiodev);\n--\ndrivers/net/dsa/dsa_loop.c-502-}\ndrivers/net/dsa/dsa_loop.c:503:module_init(dsa_loop_init);\ndrivers/net/dsa/dsa_loop.c-504-\ndrivers/net/dsa/dsa_loop.c:505:static void __exit dsa_loop_exit(void)\ndrivers/net/dsa/dsa_loop.c-506-{\ndrivers/net/dsa/dsa_loop.c:507:\tmdio_driver_unregister(\u0026dsa_loop_drv);\ndrivers/net/dsa/dsa_loop.c:508:\tdsa_loop_phydevs_unregister();\ndrivers/net/dsa/dsa_loop.c-509-\tmdio_device_remove(switch_mdiodev);\n--\ndrivers/net/dsa/dsa_loop.c-511-}\ndrivers/net/dsa/dsa_loop.c:512:module_exit(dsa_loop_exit);\ndrivers/net/dsa/dsa_loop.c-513-\n"
} |
| 13/2 | 2026/06/25 08:29 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 34532 output: 27 thoughts: 278 Thoughts: **DSA Switch Instantiation and Fuzzing Strategy** Okay, so `dsa_loop` uses `NET_DSA_TAG_NONE`. And `dsa_loop_get_protocol` returns `DSA_TAG_PROTO_NONE`. That's the baseline. Can we leverage this to fuzz other taggers, maybe? The key is going to be figuring out how to get traffic routed *through* the DSA infrastructure. Syzkaller is great with packet injection through `tun`/`tap`, `mac80211_hwsim`, and even `dummy` interfaces. The immediate question is, if we *enable* `NET_DSA` and some of these taggers, can syzkaller actually *reach* them? Now, remember how `dsa_switch_rcv` gets called? It's from `netif_receive_skb_core` *if* `skb->dev->dsa_ptr` is set. Right, and to have `skb->dev->dsa_ptr` set, you need a DSA switch attached to a `net_device`. So the real question is: can syzkaller *create* a DSA switch? It has `syz_genetlink_get_family` and other netlink bits, which might be helpful. But DSA switches are typically set up through device tree, platform data, or even I2C/MDIO devices. That seems difficult to emulate. Wait a second, syzkaller does have clever virtualization tricks for other subsystems. It has `vhci` for USB, `mac80211_hwsim` for wifi. So the question becomes, does it have a way to instantiate DSA switches somehow? A virtual one, or perhaps a way to fake the data structures required? Okay, time to stop speculating. Let's see if there is any existing syzkaller description, a dedicated one, of DSA devices. That's the first place to look. Maybe someone has already figured out how to do this. |
| 14/2 | 2026/06/25 08:30 | tool | grepper |
0mArgs:{
"Expression": "dsa",
"PathPrefix": "net/dsa/"
}Results: {
"Output": "\nFull output is too long, showing 500 out of 8104 lines.\nUse more precise expression if possible.\n\nnet/dsa/Makefile=6=endif\n--\nnet/dsa/Makefile-8-# the core\nnet/dsa/Makefile:9:obj-$(CONFIG_NET_DSA) += dsa_core.o\nnet/dsa/Makefile:10:dsa_core-y += \\\nnet/dsa/Makefile-11-\tconduit.o \\\nnet/dsa/Makefile-12-\tdevlink.o \\\nnet/dsa/Makefile:13:\tdsa.o \\\nnet/dsa/Makefile-14-\tnetlink.o \\\n--\nnet/dsa/Makefile=24=obj-$(CONFIG_NET_DSA_TAG_BRCM_COMMON) += tag_brcm.o\nnet/dsa/Makefile:25:obj-$(CONFIG_NET_DSA_TAG_DSA_COMMON) += tag_dsa.o\nnet/dsa/Makefile-26-obj-$(CONFIG_NET_DSA_TAG_GSWIP) += tag_gswip.o\n--\nnet/dsa/conduit.c-11-#include \u003clinux/netlink.h\u003e\nnet/dsa/conduit.c:12:#include \u003cnet/dsa.h\u003e\nnet/dsa/conduit.c-13-#include \u003cnet/netdev_lock.h\u003e\n--\nnet/dsa/conduit.c-15-#include \"conduit.h\"\nnet/dsa/conduit.c:16:#include \"dsa.h\"\nnet/dsa/conduit.c-17-#include \"port.h\"\n--\nnet/dsa/conduit.c-19-\nnet/dsa/conduit.c:20:static int dsa_conduit_get_regs_len(struct net_device *dev)\nnet/dsa/conduit.c-21-{\nnet/dsa/conduit.c:22:\tstruct dsa_port *cpu_dp = dev-\u003edsa_ptr;\nnet/dsa/conduit.c-23-\tconst struct ethtool_ops *ops = cpu_dp-\u003eorig_ethtool_ops;\nnet/dsa/conduit.c:24:\tstruct dsa_switch *ds = cpu_dp-\u003eds;\nnet/dsa/conduit.c-25-\tint port = cpu_dp-\u003eindex;\n--\nnet/dsa/conduit.c-48-\nnet/dsa/conduit.c:49:static void dsa_conduit_get_regs(struct net_device *dev,\nnet/dsa/conduit.c-50-\t\t\t\t struct ethtool_regs *regs, void *data)\nnet/dsa/conduit.c-51-{\nnet/dsa/conduit.c:52:\tstruct dsa_port *cpu_dp = dev-\u003edsa_ptr;\nnet/dsa/conduit.c-53-\tconst struct ethtool_ops *ops = cpu_dp-\u003eorig_ethtool_ops;\nnet/dsa/conduit.c:54:\tstruct dsa_switch *ds = cpu_dp-\u003eds;\nnet/dsa/conduit.c-55-\tstruct ethtool_drvinfo *cpu_info;\n--\nnet/dsa/conduit.c-69-\tcpu_info = (struct ethtool_drvinfo *)data;\nnet/dsa/conduit.c:70:\tstrscpy(cpu_info-\u003edriver, \"dsa\", sizeof(cpu_info-\u003edriver));\nnet/dsa/conduit.c-71-\tdata += sizeof(*cpu_info);\n--\nnet/dsa/conduit.c-83-\nnet/dsa/conduit.c:84:static ssize_t dsa_conduit_append_port_stats(struct dsa_switch *ds, int port,\nnet/dsa/conduit.c-85-\t\t\t\t\t u64 *data, size_t start)\n--\nnet/dsa/conduit.c-101-\nnet/dsa/conduit.c:102:static void dsa_conduit_get_ethtool_stats(struct net_device *dev,\nnet/dsa/conduit.c-103-\t\t\t\t\t struct ethtool_stats *stats,\n--\nnet/dsa/conduit.c-105-{\nnet/dsa/conduit.c:106:\tstruct dsa_port *dp, *cpu_dp = dev-\u003edsa_ptr;\nnet/dsa/conduit.c-107-\tconst struct ethtool_ops *ops = cpu_dp-\u003eorig_ethtool_ops;\nnet/dsa/conduit.c:108:\tstruct dsa_switch_tree *dst = cpu_dp-\u003edst;\nnet/dsa/conduit.c-109-\tint count, mcount = 0;\n--\nnet/dsa/conduit.c-116-\tlist_for_each_entry(dp, \u0026dst-\u003eports, list) {\nnet/dsa/conduit.c:117:\t\tif (!dsa_port_is_dsa(dp) \u0026\u0026 !dsa_port_is_cpu(dp))\nnet/dsa/conduit.c-118-\t\t\tcontinue;\nnet/dsa/conduit.c-119-\nnet/dsa/conduit.c:120:\t\tcount = dsa_conduit_append_port_stats(dp-\u003eds, dp-\u003eindex,\nnet/dsa/conduit.c-121-\t\t\t\t\t\t data, mcount);\n--\nnet/dsa/conduit.c-128-\nnet/dsa/conduit.c:129:static void dsa_conduit_get_ethtool_phy_stats(struct net_device *dev,\nnet/dsa/conduit.c-130-\t\t\t\t\t struct ethtool_stats *stats,\n--\nnet/dsa/conduit.c-132-{\nnet/dsa/conduit.c:133:\tstruct dsa_port *cpu_dp = dev-\u003edsa_ptr;\nnet/dsa/conduit.c-134-\tconst struct ethtool_ops *ops = cpu_dp-\u003eorig_ethtool_ops;\nnet/dsa/conduit.c:135:\tstruct dsa_switch *ds = cpu_dp-\u003eds;\nnet/dsa/conduit.c-136-\tint port = cpu_dp-\u003eindex;\n--\nnet/dsa/conduit.c-154-\nnet/dsa/conduit.c:155:static void dsa_conduit_append_port_sset_count(struct dsa_switch *ds, int port,\nnet/dsa/conduit.c-156-\t\t\t\t\t int sset, int *count)\n--\nnet/dsa/conduit.c-161-\nnet/dsa/conduit.c:162:static int dsa_conduit_get_sset_count(struct net_device *dev, int sset)\nnet/dsa/conduit.c-163-{\nnet/dsa/conduit.c:164:\tstruct dsa_port *dp, *cpu_dp = dev-\u003edsa_ptr;\nnet/dsa/conduit.c-165-\tconst struct ethtool_ops *ops = cpu_dp-\u003eorig_ethtool_ops;\nnet/dsa/conduit.c:166:\tstruct dsa_switch_tree *dst = cpu_dp-\u003edst;\nnet/dsa/conduit.c-167-\tint count = 0;\n--\nnet/dsa/conduit.c-178-\tlist_for_each_entry(dp, \u0026dst-\u003eports, list) {\nnet/dsa/conduit.c:179:\t\tif (!dsa_port_is_dsa(dp) \u0026\u0026 !dsa_port_is_cpu(dp))\nnet/dsa/conduit.c-180-\t\t\tcontinue;\nnet/dsa/conduit.c-181-\nnet/dsa/conduit.c:182:\t\tdsa_conduit_append_port_sset_count(dp-\u003eds, dp-\u003eindex, sset,\nnet/dsa/conduit.c-183-\t\t\t\t\t\t \u0026count);\n--\nnet/dsa/conduit.c-188-\nnet/dsa/conduit.c:189:static ssize_t dsa_conduit_append_port_strings(struct dsa_switch *ds, int port,\nnet/dsa/conduit.c-190-\t\t\t\t\t u32 stringset, u8 *data,\n--\nnet/dsa/conduit.c-221-\nnet/dsa/conduit.c:222:static void dsa_conduit_get_strings(struct net_device *dev, u32 stringset,\nnet/dsa/conduit.c-223-\t\t\t\t u8 *data)\nnet/dsa/conduit.c-224-{\nnet/dsa/conduit.c:225:\tstruct dsa_port *dp, *cpu_dp = dev-\u003edsa_ptr;\nnet/dsa/conduit.c-226-\tconst struct ethtool_ops *ops = cpu_dp-\u003eorig_ethtool_ops;\nnet/dsa/conduit.c:227:\tstruct dsa_switch_tree *dst = cpu_dp-\u003edst;\nnet/dsa/conduit.c-228-\tint count, mcount = 0;\n--\nnet/dsa/conduit.c-244-\tlist_for_each_entry(dp, \u0026dst-\u003eports, list) {\nnet/dsa/conduit.c:245:\t\tif (!dsa_port_is_dsa(dp) \u0026\u0026 !dsa_port_is_cpu(dp))\nnet/dsa/conduit.c-246-\t\t\tcontinue;\nnet/dsa/conduit.c-247-\nnet/dsa/conduit.c:248:\t\tcount = dsa_conduit_append_port_strings(dp-\u003eds, dp-\u003eindex,\nnet/dsa/conduit.c-249-\t\t\t\t\t\t\tstringset, data,\n--\nnet/dsa/conduit.c-260- */\nnet/dsa/conduit.c:261:int __dsa_conduit_hwtstamp_validate(struct net_device *dev,\nnet/dsa/conduit.c-262-\t\t\t\t const struct kernel_hwtstamp_config *config,\n--\nnet/dsa/conduit.c-264-{\nnet/dsa/conduit.c:265:\tstruct dsa_port *cpu_dp = dev-\u003edsa_ptr;\nnet/dsa/conduit.c:266:\tstruct dsa_switch *ds = cpu_dp-\u003eds;\nnet/dsa/conduit.c:267:\tstruct dsa_switch_tree *dst;\nnet/dsa/conduit.c:268:\tstruct dsa_port *dp;\nnet/dsa/conduit.c-269-\n--\nnet/dsa/conduit.c-272-\tlist_for_each_entry(dp, \u0026dst-\u003eports, list) {\nnet/dsa/conduit.c:273:\t\tif (dsa_port_supports_hwtstamp(dp)) {\nnet/dsa/conduit.c-274-\t\t\tNL_SET_ERR_MSG(extack,\n--\nnet/dsa/conduit.c-282-\nnet/dsa/conduit.c:283:static int dsa_conduit_ethtool_setup(struct net_device *dev)\nnet/dsa/conduit.c-284-{\nnet/dsa/conduit.c:285:\tstruct dsa_port *cpu_dp = dev-\u003edsa_ptr;\nnet/dsa/conduit.c:286:\tstruct dsa_switch *ds = cpu_dp-\u003eds;\nnet/dsa/conduit.c-287-\tstruct ethtool_ops *ops;\n--\nnet/dsa/conduit.c-299-\nnet/dsa/conduit.c:300:\tops-\u003eget_regs_len = dsa_conduit_get_regs_len;\nnet/dsa/conduit.c:301:\tops-\u003eget_regs = dsa_conduit_get_regs;\nnet/dsa/conduit.c:302:\tops-\u003eget_sset_count = dsa_conduit_get_sset_count;\nnet/dsa/conduit.c:303:\tops-\u003eget_ethtool_stats = dsa_conduit_get_ethtool_stats;\nnet/dsa/conduit.c:304:\tops-\u003eget_strings = dsa_conduit_get_strings;\nnet/dsa/conduit.c:305:\tops-\u003eget_ethtool_phy_stats = dsa_conduit_get_ethtool_phy_stats;\nnet/dsa/conduit.c-306-\n--\nnet/dsa/conduit.c-311-\nnet/dsa/conduit.c:312:static void dsa_conduit_ethtool_teardown(struct net_device *dev)\nnet/dsa/conduit.c-313-{\nnet/dsa/conduit.c:314:\tstruct dsa_port *cpu_dp = dev-\u003edsa_ptr;\nnet/dsa/conduit.c-315-\n--\nnet/dsa/conduit.c-327- */\nnet/dsa/conduit.c:328:static void dsa_conduit_set_promiscuity(struct net_device *dev, int inc)\nnet/dsa/conduit.c-329-{\nnet/dsa/conduit.c:330:\tconst struct dsa_device_ops *ops = dev-\u003edsa_ptr-\u003etag_ops;\nnet/dsa/conduit.c-331-\n--\nnet/dsa/conduit.c=340=static ssize_t tagging_show(struct device *d, struct device_attribute *attr,\n--\nnet/dsa/conduit.c-343-\tstruct net_device *dev = to_net_dev(d);\nnet/dsa/conduit.c:344:\tstruct dsa_port *cpu_dp = dev-\u003edsa_ptr;\nnet/dsa/conduit.c-345-\nnet/dsa/conduit.c-346-\treturn sysfs_emit(buf, \"%s\\n\",\nnet/dsa/conduit.c:347:\t\t dsa_tag_protocol_to_str(cpu_dp-\u003etag_ops));\nnet/dsa/conduit.c-348-}\n--\nnet/dsa/conduit.c=350=static ssize_t tagging_store(struct device *d, struct device_attribute *attr,\n--\nnet/dsa/conduit.c-352-{\nnet/dsa/conduit.c:353:\tconst struct dsa_device_ops *new_tag_ops, *old_tag_ops;\nnet/dsa/conduit.c-354-\tconst char *end = strchrnul(buf, '\\n'), *name;\nnet/dsa/conduit.c-355-\tstruct net_device *dev = to_net_dev(d);\nnet/dsa/conduit.c:356:\tstruct dsa_port *cpu_dp = dev-\u003edsa_ptr;\nnet/dsa/conduit.c-357-\tsize_t len = end - buf;\n--\nnet/dsa/conduit.c-368-\told_tag_ops = cpu_dp-\u003etag_ops;\nnet/dsa/conduit.c:369:\tnew_tag_ops = dsa_tag_driver_get_by_name(name);\nnet/dsa/conduit.c-370-\tkfree(name);\n--\nnet/dsa/conduit.c-380-\nnet/dsa/conduit.c:381:\terr = dsa_tree_change_tag_proto(cpu_dp-\u003eds-\u003edst, new_tag_ops,\nnet/dsa/conduit.c-382-\t\t\t\t\told_tag_ops);\n--\nnet/dsa/conduit.c-386-\t\t */\nnet/dsa/conduit.c:387:\t\tdsa_tag_driver_put(new_tag_ops);\nnet/dsa/conduit.c-388-\t\treturn err;\n--\nnet/dsa/conduit.c-393-out:\nnet/dsa/conduit.c:394:\tdsa_tag_driver_put(old_tag_ops);\nnet/dsa/conduit.c-395-\treturn count;\n--\nnet/dsa/conduit.c=397=static DEVICE_ATTR_RW(tagging);\nnet/dsa/conduit.c-398-\nnet/dsa/conduit.c:399:static struct attribute *dsa_user_attrs[] = {\nnet/dsa/conduit.c-400-\t\u0026dev_attr_tagging.attr,\n--\nnet/dsa/conduit.c-403-\nnet/dsa/conduit.c:404:static const struct attribute_group dsa_group = {\nnet/dsa/conduit.c:405:\t.name\t= \"dsa\",\nnet/dsa/conduit.c:406:\t.attrs\t= dsa_user_attrs,\nnet/dsa/conduit.c-407-};\nnet/dsa/conduit.c-408-\nnet/dsa/conduit.c:409:static void dsa_conduit_reset_mtu(struct net_device *dev)\nnet/dsa/conduit.c-410-{\n--\nnet/dsa/conduit.c-418-\nnet/dsa/conduit.c:419:int dsa_conduit_setup(struct net_device *dev, struct dsa_port *cpu_dp)\nnet/dsa/conduit.c-420-{\nnet/dsa/conduit.c:421:\tconst struct dsa_device_ops *tag_ops = cpu_dp-\u003etag_ops;\nnet/dsa/conduit.c:422:\tstruct dsa_switch *ds = cpu_dp-\u003eds;\nnet/dsa/conduit.c-423-\tstruct device_link *consumer_link;\n--\nnet/dsa/conduit.c-425-\nnet/dsa/conduit.c:426:\tmtu = ETH_DATA_LEN + dsa_tag_protocol_overhead(tag_ops);\nnet/dsa/conduit.c-427-\n--\nnet/dsa/conduit.c-438-\t/* The switch driver may not implement -\u003eport_change_mtu(), case in\nnet/dsa/conduit.c:439:\t * which dsa_user_change_mtu() will not update the conduit MTU either,\nnet/dsa/conduit.c-440-\t * so we need to do that here.\n--\nnet/dsa/conduit.c-452-\nnet/dsa/conduit.c:453:\tdev-\u003edsa_ptr = cpu_dp;\nnet/dsa/conduit.c-454-\nnet/dsa/conduit.c:455:\tdsa_conduit_set_promiscuity(dev, 1);\nnet/dsa/conduit.c-456-\nnet/dsa/conduit.c:457:\tret = dsa_conduit_ethtool_setup(dev);\nnet/dsa/conduit.c-458-\tif (ret)\n--\nnet/dsa/conduit.c-460-\nnet/dsa/conduit.c:461:\tret = sysfs_create_group(\u0026dev-\u003edev.kobj, \u0026dsa_group);\nnet/dsa/conduit.c-462-\tif (ret)\n--\nnet/dsa/conduit.c-467-out_err_ethtool_teardown:\nnet/dsa/conduit.c:468:\tdsa_conduit_ethtool_teardown(dev);\nnet/dsa/conduit.c-469-out_err_reset_promisc:\nnet/dsa/conduit.c:470:\tdsa_conduit_set_promiscuity(dev, -1);\nnet/dsa/conduit.c-471-\treturn ret;\n--\nnet/dsa/conduit.c-473-\nnet/dsa/conduit.c:474:void dsa_conduit_teardown(struct net_device *dev)\nnet/dsa/conduit.c-475-{\nnet/dsa/conduit.c:476:\tsysfs_remove_group(\u0026dev-\u003edev.kobj, \u0026dsa_group);\nnet/dsa/conduit.c:477:\tdsa_conduit_ethtool_teardown(dev);\nnet/dsa/conduit.c:478:\tdsa_conduit_reset_mtu(dev);\nnet/dsa/conduit.c:479:\tdsa_conduit_set_promiscuity(dev, -1);\nnet/dsa/conduit.c-480-\nnet/dsa/conduit.c:481:\tdev-\u003edsa_ptr = NULL;\nnet/dsa/conduit.c-482-\n--\nnet/dsa/conduit.c-489-\nnet/dsa/conduit.c:490:int dsa_conduit_lag_setup(struct net_device *lag_dev, struct dsa_port *cpu_dp,\nnet/dsa/conduit.c-491-\t\t\t struct netdev_lag_upper_info *uinfo,\n--\nnet/dsa/conduit.c-496-\nnet/dsa/conduit.c:497:\tif (!netdev_uses_dsa(lag_dev)) {\nnet/dsa/conduit.c:498:\t\terr = dsa_conduit_setup(lag_dev, cpu_dp);\nnet/dsa/conduit.c-499-\t\tif (err)\n--\nnet/dsa/conduit.c-504-\nnet/dsa/conduit.c:505:\terr = dsa_port_lag_join(cpu_dp, lag_dev, uinfo, extack);\nnet/dsa/conduit.c-506-\tif (err) {\n--\nnet/dsa/conduit.c-514-\tif (conduit_setup)\nnet/dsa/conduit.c:515:\t\tdsa_conduit_teardown(lag_dev);\nnet/dsa/conduit.c-516-\treturn err;\n--\nnet/dsa/conduit.c-521- */\nnet/dsa/conduit.c:522:void dsa_conduit_lag_teardown(struct net_device *lag_dev,\nnet/dsa/conduit.c:523:\t\t\t struct dsa_port *cpu_dp)\nnet/dsa/conduit.c-524-{\n--\nnet/dsa/conduit.c-527-\nnet/dsa/conduit.c:528:\tdsa_port_lag_leave(cpu_dp, lag_dev);\nnet/dsa/conduit.c-529-\nnet/dsa/conduit.c-530-\tnetdev_for_each_upper_dev_rcu(lag_dev, upper, iter)\nnet/dsa/conduit.c:531:\t\tif (dsa_user_dev_check(upper))\nnet/dsa/conduit.c-532-\t\t\treturn;\nnet/dsa/conduit.c-533-\nnet/dsa/conduit.c:534:\tdsa_conduit_teardown(lag_dev);\nnet/dsa/conduit.c-535-}\n--\nnet/dsa/conduit.h-5-\nnet/dsa/conduit.h:6:struct dsa_port;\nnet/dsa/conduit.h-7-struct net_device;\n--\nnet/dsa/conduit.h=9=struct netlink_ext_ack;\nnet/dsa/conduit.h-10-\nnet/dsa/conduit.h:11:int dsa_conduit_setup(struct net_device *dev, struct dsa_port *cpu_dp);\nnet/dsa/conduit.h:12:void dsa_conduit_teardown(struct net_device *dev);\nnet/dsa/conduit.h:13:int dsa_conduit_lag_setup(struct net_device *lag_dev, struct dsa_port *cpu_dp,\nnet/dsa/conduit.h-14-\t\t\t struct netdev_lag_upper_info *uinfo,\nnet/dsa/conduit.h-15-\t\t\t struct netlink_ext_ack *extack);\nnet/dsa/conduit.h:16:void dsa_conduit_lag_teardown(struct net_device *lag_dev,\nnet/dsa/conduit.h:17:\t\t\t struct dsa_port *cpu_dp);\nnet/dsa/conduit.h:18:int __dsa_conduit_hwtstamp_validate(struct net_device *dev,\nnet/dsa/conduit.h-19-\t\t\t\t const struct kernel_hwtstamp_config *config,\n--\nnet/dsa/devlink.c-5-\nnet/dsa/devlink.c:6:#include \u003cnet/dsa.h\u003e\nnet/dsa/devlink.c-7-#include \u003cnet/devlink.h\u003e\n--\nnet/dsa/devlink.c-10-\nnet/dsa/devlink.c:11:static int dsa_devlink_info_get(struct devlink *dl,\nnet/dsa/devlink.c-12-\t\t\t\tstruct devlink_info_req *req,\n--\nnet/dsa/devlink.c-14-{\nnet/dsa/devlink.c:15:\tstruct dsa_switch *ds = dsa_devlink_to_ds(dl);\nnet/dsa/devlink.c-16-\n--\nnet/dsa/devlink.c-22-\nnet/dsa/devlink.c:23:static int dsa_devlink_sb_pool_get(struct devlink *dl,\nnet/dsa/devlink.c-24-\t\t\t\t unsigned int sb_index, u16 pool_index,\n--\nnet/dsa/devlink.c-26-{\nnet/dsa/devlink.c:27:\tstruct dsa_switch *ds = dsa_devlink_to_ds(dl);\nnet/dsa/devlink.c-28-\n--\nnet/dsa/devlink.c-35-\nnet/dsa/devlink.c:36:static int dsa_devlink_sb_pool_set(struct devlink *dl, unsigned int sb_index,\nnet/dsa/devlink.c-37-\t\t\t\t u16 pool_index, u32 size,\n--\nnet/dsa/devlink.c-40-{\nnet/dsa/devlink.c:41:\tstruct dsa_switch *ds = dsa_devlink_to_ds(dl);\nnet/dsa/devlink.c-42-\n--\nnet/dsa/devlink.c-49-\nnet/dsa/devlink.c:50:static int dsa_devlink_sb_port_pool_get(struct devlink_port *dlp,\nnet/dsa/devlink.c-51-\t\t\t\t\tunsigned int sb_index, u16 pool_index,\n--\nnet/dsa/devlink.c-53-{\nnet/dsa/devlink.c:54:\tstruct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);\nnet/dsa/devlink.c:55:\tint port = dsa_devlink_port_to_port(dlp);\nnet/dsa/devlink.c-56-\n--\nnet/dsa/devlink.c-63-\nnet/dsa/devlink.c:64:static int dsa_devlink_sb_port_pool_set(struct devlink_port *dlp,\nnet/dsa/devlink.c-65-\t\t\t\t\tunsigned int sb_index, u16 pool_index,\n--\nnet/dsa/devlink.c-68-{\nnet/dsa/devlink.c:69:\tstruct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);\nnet/dsa/devlink.c:70:\tint port = dsa_devlink_port_to_port(dlp);\nnet/dsa/devlink.c-71-\n--\nnet/dsa/devlink.c=79=static int\nnet/dsa/devlink.c:80:dsa_devlink_sb_tc_pool_bind_get(struct devlink_port *dlp,\nnet/dsa/devlink.c-81-\t\t\t\tunsigned int sb_index, u16 tc_index,\n--\nnet/dsa/devlink.c-84-{\nnet/dsa/devlink.c:85:\tstruct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);\nnet/dsa/devlink.c:86:\tint port = dsa_devlink_port_to_port(dlp);\nnet/dsa/devlink.c-87-\n--\nnet/dsa/devlink.c=96=static int\nnet/dsa/devlink.c:97:dsa_devlink_sb_tc_pool_bind_set(struct devlink_port *dlp,\nnet/dsa/devlink.c-98-\t\t\t\tunsigned int sb_index, u16 tc_index,\n--\nnet/dsa/devlink.c-102-{\nnet/dsa/devlink.c:103:\tstruct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);\nnet/dsa/devlink.c:104:\tint port = dsa_devlink_port_to_port(dlp);\nnet/dsa/devlink.c-105-\n--\nnet/dsa/devlink.c-114-\nnet/dsa/devlink.c:115:static int dsa_devlink_sb_occ_snapshot(struct devlink *dl,\nnet/dsa/devlink.c-116-\t\t\t\t unsigned int sb_index)\nnet/dsa/devlink.c-117-{\nnet/dsa/devlink.c:118:\tstruct dsa_switch *ds = dsa_devlink_to_ds(dl);\nnet/dsa/devlink.c-119-\n--\nnet/dsa/devlink.c-125-\nnet/dsa/devlink.c:126:static int dsa_devlink_sb_occ_max_clear(struct devlink *dl,\nnet/dsa/devlink.c-127-\t\t\t\t\tunsigned int sb_index)\nnet/dsa/devlink.c-128-{\nnet/dsa/devlink.c:129:\tstruct dsa_switch *ds = dsa_devlink_to_ds(dl);\nnet/dsa/devlink.c-130-\n--\nnet/dsa/devlink.c-136-\nnet/dsa/devlink.c:137:static int dsa_devlink_sb_occ_port_pool_get(struct devlink_port *dlp,\nnet/dsa/devlink.c-138-\t\t\t\t\t unsigned int sb_index,\n--\nnet/dsa/devlink.c-141-{\nnet/dsa/devlink.c:142:\tstruct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);\nnet/dsa/devlink.c:143:\tint port = dsa_devlink_port_to_port(dlp);\nnet/dsa/devlink.c-144-\n--\nnet/dsa/devlink.c=152=static int\nnet/dsa/devlink.c:153:dsa_devlink_sb_occ_tc_port_bind_get(struct devlink_port *dlp,\nnet/dsa/devlink.c-154-\t\t\t\t unsigned int sb_index, u16 tc_index,\n--\nnet/dsa/devlink.c-157-{\nnet/dsa/devlink.c:158:\tstruct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);\nnet/dsa/devlink.c:159:\tint port = dsa_devlink_port_to_port(dlp);\nnet/dsa/devlink.c-160-\n--\nnet/dsa/devlink.c-169-\nnet/dsa/devlink.c:170:static const struct devlink_ops dsa_devlink_ops = {\nnet/dsa/devlink.c:171:\t.info_get\t\t\t= dsa_devlink_info_get,\nnet/dsa/devlink.c:172:\t.sb_pool_get\t\t\t= dsa_devlink_sb_pool_get,\nnet/dsa/devlink.c:173:\t.sb_pool_set\t\t\t= dsa_devlink_sb_pool_set,\nnet/dsa/devlink.c:174:\t.sb_port_pool_get\t\t= dsa_devlink_sb_port_pool_get,\nnet/dsa/devlink.c:175:\t.sb_port_pool_set\t\t= dsa_devlink_sb_port_pool_set,\nnet/dsa/devlink.c:176:\t.sb_tc_pool_bind_get\t\t= dsa_devlink_sb_tc_pool_bind_get,\nnet/dsa/devlink.c:177:\t.sb_tc_pool_bind_set\t\t= dsa_devlink_sb_tc_pool_bind_set,\nnet/dsa/devlink.c:178:\t.sb_occ_snapshot\t\t= dsa_devlink_sb_occ_snapshot,\nnet/dsa/devlink.c:179:\t.sb_occ_max_clear\t\t= dsa_devlink_sb_occ_max_clear,\nnet/dsa/devlink.c:180:\t.sb_occ_port_pool_get\t\t= dsa_devlink_sb_occ_port_pool_get,\nnet/dsa/devlink.c:181:\t.sb_occ_tc_port_bind_get\t= dsa_devlink_sb_occ_tc_port_bind_get,\nnet/dsa/devlink.c-182-};\nnet/dsa/devlink.c-183-\nnet/dsa/devlink.c:184:int dsa_devlink_param_get(struct devlink *dl, u32 id,\nnet/dsa/devlink.c-185-\t\t\t struct devlink_param_gset_ctx *ctx,\n--\nnet/dsa/devlink.c-187-{\nnet/dsa/devlink.c:188:\tstruct dsa_switch *ds = dsa_devlink_to_ds(dl);\nnet/dsa/devlink.c-189-\n--\nnet/dsa/devlink.c-194-}\nnet/dsa/devlink.c:195:EXPORT_SYMBOL_GPL(dsa_devlink_param_get);\nnet/dsa/devlink.c-196-\nnet/dsa/devlink.c:197:int dsa_devlink_param_set(struct devlink *dl, u32 id,\nnet/dsa/devlink.c-198-\t\t\t struct devlink_param_gset_ctx *ctx,\n--\nnet/dsa/devlink.c-200-{\nnet/dsa/devlink.c:201:\tstruct dsa_switch *ds = dsa_devlink_to_ds(dl);\nnet/dsa/devlink.c-202-\n--\nnet/dsa/devlink.c-207-}\nnet/dsa/devlink.c:208:EXPORT_SYMBOL_GPL(dsa_devlink_param_set);\nnet/dsa/devlink.c-209-\nnet/dsa/devlink.c:210:int dsa_devlink_params_register(struct dsa_switch *ds,\nnet/dsa/devlink.c-211-\t\t\t\tconst struct devlink_param *params,\n--\nnet/dsa/devlink.c-215-}\nnet/dsa/devlink.c:216:EXPORT_SYMBOL_GPL(dsa_devlink_params_register);\nnet/dsa/devlink.c-217-\nnet/dsa/devlink.c:218:void dsa_devlink_params_unregister(struct dsa_switch *ds,\nnet/dsa/devlink.c-219-\t\t\t\t const struct devlink_param *params,\n--\nnet/dsa/devlink.c-223-}\nnet/dsa/devlink.c:224:EXPORT_SYMBOL_GPL(dsa_devlink_params_unregister);\nnet/dsa/devlink.c-225-\nnet/dsa/devlink.c:226:int dsa_devlink_resource_register(struct dsa_switch *ds,\nnet/dsa/devlink.c-227-\t\t\t\t const char *resource_name,\n--\nnet/dsa/devlink.c-242-}\nnet/dsa/devlink.c:243:EXPORT_SYMBOL_GPL(dsa_devlink_resource_register);\nnet/dsa/devlink.c-244-\nnet/dsa/devlink.c:245:void dsa_devlink_resources_unregister(struct dsa_switch *ds)\nnet/dsa/devlink.c-246-{\n--\nnet/dsa/devlink.c-248-}\nnet/dsa/devlink.c:249:EXPORT_SYMBOL_GPL(dsa_devlink_resources_unregister);\nnet/dsa/devlink.c-250-\nnet/dsa/devlink.c:251:void dsa_devlink_resource_occ_get_register(struct dsa_switch *ds,\nnet/dsa/devlink.c-252-\t\t\t\t\t u64 resource_id,\n--\nnet/dsa/devlink.c-260-}\nnet/dsa/devlink.c:261:EXPORT_SYMBOL_GPL(dsa_devlink_resource_occ_get_register);\nnet/dsa/devlink.c-262-\nnet/dsa/devlink.c:263:void dsa_devlink_resource_occ_get_unregister(struct dsa_switch *ds,\nnet/dsa/devlink.c-264-\t\t\t\t\t u64 resource_id)\n--\nnet/dsa/devlink.c-269-}\nnet/dsa/devlink.c:270:EXPORT_SYMBOL_GPL(dsa_devlink_resource_occ_get_unregister);\nnet/dsa/devlink.c-271-\nnet/dsa/devlink.c=272=struct devlink_region *\nnet/dsa/devlink.c:273:dsa_devlink_region_create(struct dsa_switch *ds,\nnet/dsa/devlink.c-274-\t\t\t const struct devlink_region_ops *ops,\n--\nnet/dsa/devlink.c-279-}\nnet/dsa/devlink.c:280:EXPORT_SYMBOL_GPL(dsa_devlink_region_create);\nnet/dsa/devlink.c-281-\nnet/dsa/devlink.c=282=struct devlink_region *\nnet/dsa/devlink.c:283:dsa_devlink_port_region_create(struct dsa_switch *ds,\nnet/dsa/devlink.c-284-\t\t\t int port,\n--\nnet/dsa/devlink.c-287-{\nnet/dsa/devlink.c:288:\tstruct dsa_port *dp = dsa_to_port(ds, port);\nnet/dsa/devlink.c-289-\n--\nnet/dsa/devlink.c-293-}\nnet/dsa/devlink.c:294:EXPORT_SYMBOL_GPL(dsa_devlink_port_region_create);\nnet/dsa/devlink.c-295-\nnet/dsa/devlink.c:296:void dsa_devlink_region_destroy(struct devlink_region *region)\nnet/dsa/devlink.c-297-{\n--\nnet/dsa/devlink.c-299-}\nnet/dsa/devlink.c:300:EXPORT_SYMBOL_GPL(dsa_devlink_region_destroy);\nnet/dsa/devlink.c-301-\nnet/dsa/devlink.c:302:int dsa_port_devlink_setup(struct dsa_port *dp)\nnet/dsa/devlink.c-303-{\nnet/dsa/devlink.c-304-\tstruct devlink_port *dlp = \u0026dp-\u003edevlink_port;\nnet/dsa/devlink.c:305:\tstruct dsa_switch_tree *dst = dp-\u003eds-\u003edst;\nnet/dsa/devlink.c-306-\tstruct devlink_port_attrs attrs = {};\nnet/dsa/devlink.c-307-\tstruct devlink *dl = dp-\u003eds-\u003edevlink;\nnet/dsa/devlink.c:308:\tstruct dsa_switch *ds = dp-\u003eds;\nnet/dsa/devlink.c-309-\tconst unsigned char *id;\n--\nnet/dsa/devlink.c-354-\nnet/dsa/devlink.c:355:void dsa_port_devlink_teardown(struct dsa_port *dp)\nnet/dsa/devlink.c-356-{\nnet/dsa/devlink.c-357-\tstruct devlink_port *dlp = \u0026dp-\u003edevlink_port;\n\n"
} |
| 15/2 | 2026/06/25 08:30 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 46146 output: 21 thoughts: 1108 Thoughts: **Fuzzing DSA Tagging Protocols with `dsa_loop`**
Okay, so I've been digging into the DSA (Distributed Switch Architecture) code, specifically looking for fuzzing opportunities. The `dsa_loop` driver seems like a great starting point – it's a mock-up driver, essentially a virtual switch instantiated via `mdio_driver_register` and `dsa_loop_create_switch_mdiodev()`. If `CONFIG_NET_DSA_LOOP` is enabled, this thing automatically sets up a switch and attaches it to a fixed PHY, which is convenient.
Now, `dsa_loop_create_switch_mdiodev()` creates either a platform device or an MDIO device, which is interesting in itself. The critical part is whether `dsa_loop` provides a path to the modified tagging code in `net/dsa/tag_*.c`, `net/dsa/user.c`, and `net/dsa/tag.c`. Initially, it looks like `dsa_loop` uses `NET_DSA_TAG_NONE`, which isn't going to get us anywhere with the different tagging protocols.
However, the key is the `dsa_conduit_set_promiscuity` and `tagging_store` functions in `net/dsa/conduit.c`. It looks like these offer a way to *dynamically* change the tag protocol via sysfs! Specifically, syzkaller can write to `/sys/class/net/<conduit>/dsa/tagging` to swap out the tag protocol to ANY of the registered tag drivers. The `tagging_store` function actually calls `dsa_tag_driver_get_by_name()` and then `dsa_tree_change_tag_proto()`. This is fantastic!
This means we can enable *all* the `NET_DSA_TAG_*` configs and use syzkaller to switch between them on the fly. This gives us complete dynamic control over what protocols we fuzz. We need to confirm that we can enable all these tags, which is the next step. I'll check `net/dsa/Kconfig` to be sure.
Regarding `dsa_loop` and the "conduit" device, it creates a switch, but which network device does it attach to? Looking at `dsa_loop_pdata`, it defines `.cd = { .netdev = "eth0", }`. Perfect! Syzkaller usually has `eth0` or `eth1` present. If `dsa_loop` attaches to `eth0`, it'll create DSA user interfaces like `lan1`, `lan2`, etc.
This means we can send packets through `lan1`, which will call `dsa_user_xmit`, which in turn calls the tagger's `xmit` function (`p->xmit`). Crucially, if we send packets *to* `eth0`, it calls `dsa_switch_rcv`, and calls the tagger's `rcv` function (`p->rcv`). We now have a clean fuzzing path for both transmit and receive paths!
So, the game plan is clear. We need to enable the following configs:
* `NET_DSA`
* `NET_DSA_LOOP`
* All the `NET_DSA_TAG_*` configs.
Specifically, I'll need to enable all of these:
* `NET_DSA_TAG_AR9331`
* `NET_DSA_TAG_BRCM`
* `NET_DSA_TAG_BRCM_LEGACY`
* `NET_DSA_TAG_BRCM_PREPEND`
* `NET_DSA_TAG_HELLCREEK`
* `NET_DSA_TAG_GSWIP`
* `NET_DSA_TAG_DSA`
* `NET_DSA_TAG_EDSA`
* `NET_DSA_TAG_MTK`
* `NET_DSA_TAG_MXL_862XX`
* `NET_DSA_TAG_MXL_GSW1XX`
* `NET_DSA_TAG_KSZ`
* `NET_DSA_TAG_NETC`
* `NET_DSA_TAG_OCELOT`
* `NET_DSA_TAG_OCELOT_8021Q`
* `NET_DSA_TAG_QCA`
* `NET_DSA_TAG_RTL4_A`
* `NET_DSA_TAG_RTL8_4`
* `NET_DSA_TAG_RZN1
|
| 16/2 | 2026/06/25 08:30 | tool | grepper |
0mArgs:{
"Expression": "config NET_DSA_TAG_"
}Results: {
"Output": "net/dsa/Kconfig=17=if NET_DSA\n--\nnet/dsa/Kconfig-20-\nnet/dsa/Kconfig:21:config NET_DSA_TAG_NONE\nnet/dsa/Kconfig-22-\ttristate \"No-op tag driver\"\n--\nnet/dsa/Kconfig-26-\nnet/dsa/Kconfig:27:config NET_DSA_TAG_AR9331\nnet/dsa/Kconfig-28-\ttristate \"Tag driver for Atheros AR9331 SoC with built-in switch\"\n--\nnet/dsa/Kconfig-32-\nnet/dsa/Kconfig:33:config NET_DSA_TAG_BRCM_COMMON\nnet/dsa/Kconfig-34-\ttristate\n--\nnet/dsa/Kconfig-36-\nnet/dsa/Kconfig:37:config NET_DSA_TAG_BRCM\nnet/dsa/Kconfig-38-\ttristate \"Tag driver for Broadcom switches using in-frame headers\"\n--\nnet/dsa/Kconfig-43-\nnet/dsa/Kconfig:44:config NET_DSA_TAG_BRCM_LEGACY\nnet/dsa/Kconfig-45-\ttristate \"Tag driver for BCM63xx legacy switches using in-frame headers\"\n--\nnet/dsa/Kconfig-53-\nnet/dsa/Kconfig:54:config NET_DSA_TAG_BRCM_LEGACY_FCS\nnet/dsa/Kconfig-55-\ttristate \"Tag driver for BCM53xx legacy switches using in-frame headers\"\n--\nnet/dsa/Kconfig-63-\nnet/dsa/Kconfig:64:config NET_DSA_TAG_BRCM_PREPEND\nnet/dsa/Kconfig-65-\ttristate \"Tag driver for Broadcom switches using prepended headers\"\n--\nnet/dsa/Kconfig-71-\nnet/dsa/Kconfig:72:config NET_DSA_TAG_HELLCREEK\nnet/dsa/Kconfig-73-\ttristate \"Tag driver for Hirschmann Hellcreek TSN switches\"\n--\nnet/dsa/Kconfig-77-\nnet/dsa/Kconfig:78:config NET_DSA_TAG_GSWIP\nnet/dsa/Kconfig-79-\ttristate \"Tag driver for Lantiq / Intel GSWIP switches\"\n--\nnet/dsa/Kconfig-83-\nnet/dsa/Kconfig:84:config NET_DSA_TAG_DSA_COMMON\nnet/dsa/Kconfig-85-\ttristate\nnet/dsa/Kconfig-86-\nnet/dsa/Kconfig:87:config NET_DSA_TAG_DSA\nnet/dsa/Kconfig-88-\ttristate \"Tag driver for Marvell switches using DSA headers\"\n--\nnet/dsa/Kconfig-93-\nnet/dsa/Kconfig:94:config NET_DSA_TAG_EDSA\nnet/dsa/Kconfig-95-\ttristate \"Tag driver for Marvell switches using EtherType DSA headers\"\n--\nnet/dsa/Kconfig-100-\nnet/dsa/Kconfig:101:config NET_DSA_TAG_MTK\nnet/dsa/Kconfig-102-\ttristate \"Tag driver for Mediatek switches\"\n--\nnet/dsa/Kconfig-106-\nnet/dsa/Kconfig:107:config NET_DSA_TAG_MXL_862XX\nnet/dsa/Kconfig-108-\ttristate \"Tag driver for MaxLinear MxL862xx switches\"\n--\nnet/dsa/Kconfig-113-\nnet/dsa/Kconfig:114:config NET_DSA_TAG_MXL_GSW1XX\nnet/dsa/Kconfig-115-\ttristate \"Tag driver for MaxLinear GSW1xx switches\"\n--\nnet/dsa/Kconfig-121-\nnet/dsa/Kconfig:122:config NET_DSA_TAG_KSZ\nnet/dsa/Kconfig-123-\ttristate \"Tag driver for Microchip 8795/937x/9477/9893 families of switches\"\n--\nnet/dsa/Kconfig-127-\nnet/dsa/Kconfig:128:config NET_DSA_TAG_NETC\nnet/dsa/Kconfig-129-\ttristate \"Tag driver for NXP NETC switches\"\n--\nnet/dsa/Kconfig-137-\nnet/dsa/Kconfig:138:config NET_DSA_TAG_OCELOT\nnet/dsa/Kconfig-139-\ttristate \"Tag driver for Ocelot family of switches, using NPI port\"\n--\nnet/dsa/Kconfig-148-\nnet/dsa/Kconfig:149:config NET_DSA_TAG_OCELOT_8021Q\nnet/dsa/Kconfig-150-\ttristate \"Tag driver for Ocelot family of switches, using VLAN\"\n--\nnet/dsa/Kconfig-158-\nnet/dsa/Kconfig:159:config NET_DSA_TAG_QCA\nnet/dsa/Kconfig-160-\ttristate \"Tag driver for Qualcomm Atheros QCA8K switches\"\n--\nnet/dsa/Kconfig-164-\nnet/dsa/Kconfig:165:config NET_DSA_TAG_RTL4_A\nnet/dsa/Kconfig-166-\ttristate \"Tag driver for Realtek 4 byte protocol A tags\"\n--\nnet/dsa/Kconfig-171-\nnet/dsa/Kconfig:172:config NET_DSA_TAG_RTL8_4\nnet/dsa/Kconfig-173-\ttristate \"Tag driver for Realtek 8 byte protocol 4 tags\"\n--\nnet/dsa/Kconfig-177-\nnet/dsa/Kconfig:178:config NET_DSA_TAG_RZN1_A5PSW\nnet/dsa/Kconfig-179-\ttristate \"Tag driver for Renesas RZ/N1 A5PSW switch\"\n--\nnet/dsa/Kconfig-184-\nnet/dsa/Kconfig:185:config NET_DSA_TAG_LAN9303\nnet/dsa/Kconfig-186-\ttristate \"Tag driver for SMSC/Microchip LAN9303 family of switches\"\n--\nnet/dsa/Kconfig-190-\nnet/dsa/Kconfig:191:config NET_DSA_TAG_SJA1105\nnet/dsa/Kconfig-192-\ttristate \"Tag driver for NXP SJA1105 switches\"\n--\nnet/dsa/Kconfig-199-\nnet/dsa/Kconfig:200:config NET_DSA_TAG_TRAILER\nnet/dsa/Kconfig-201-\ttristate \"Tag driver for switches using a trailer tag\"\n--\nnet/dsa/Kconfig-205-\nnet/dsa/Kconfig:206:config NET_DSA_TAG_VSC73XX_8021Q\nnet/dsa/Kconfig-207-\ttristate \"Tag driver for Microchip/Vitesse VSC73xx family of switches, using VLAN\"\n--\nnet/dsa/Kconfig-211-\nnet/dsa/Kconfig:212:config NET_DSA_TAG_XRS700X\nnet/dsa/Kconfig-213-\ttristate \"Tag driver for XRS700x switches\"\n--\nnet/dsa/Kconfig-217-\nnet/dsa/Kconfig:218:config NET_DSA_TAG_YT921X\nnet/dsa/Kconfig-219-\ttristate \"Tag driver for Motorcomm YT921x switches\"\n"
} |
| 17/2 | 2026/06/25 08:30 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 50310 output: 621 thoughts: 2875 Thoughts: **DSA Subsystem Analysis for Fuzzing** Alright, let's break this down systematically. First, I need to list the relevant kernel configurations. While `NET_DSA_TAG_BRCM_COMMON` and `NET_DSA_TAG_DSA_COMMON` are likely already enabled by others, it doesn't hurt to be explicit. The critical one here is `NET_DSA_LOOP`; that's essential for instantiating a virtual switch, which is the key to testing this. Then, of course, `CONFIG_NET_DSA` itself is required. Now, which functions are modified? The patch touches a lot of files within the `net/dsa` directory. I've got to consider all of the tagging functions, the ones that are likely to have a memory management change. Let me see what needs to be considered as the main focus: - `dsa_switch_rcv` in `net/dsa/tag.c` - `ar9331_tag_rcv` in `net/dsa/tag_ar9331.c` - `brcm_tag_xmit_ll` in `net/dsa/tag_brcm.c` - `brcm_tag_rcv_ll` in `net/dsa/tag_brcm.c` - `brcm_leg_tag_rcv` in `net/dsa/tag_brcm.c` - `brcm_leg_tag_xmit` in `net/dsa/tag_brcm.c` - `brcm_leg_fcs_tag_xmit` in `net/dsa/tag_brcm.c` - `dsa_rcv_ll` in `net/dsa/tag_dsa.c` - `dsa_rcv` in `net/dsa/tag_dsa.c` - `edsa_rcv` in `net/dsa/tag_dsa.c` - `gswip_tag_rcv` in `net/dsa/tag_gswip.c` - `hellcreek_xmit` in `net/dsa/tag_hellcreek.c` - `hellcreek_rcv` in `net/dsa/tag_hellcreek.c` - `ksz_common_rcv` in `net/dsa/tag_ksz.c` - `ksz8795_xmit` in `net/dsa/tag_ksz.c` - `ksz8795_rcv` in `net/dsa/tag_ksz.c` - `ksz_defer_xmit` in `net/dsa/tag_ksz.c` - `ksz9477_xmit` in `net/dsa/tag_ksz.c` - `ksz9477_rcv` in `net/dsa/tag_ksz.c` - `ksz9893_xmit` in `net/dsa/tag_ksz.c` - `lan937x_xmit` in `net/dsa/tag_ksz.c` - `lan9303_rcv` in `net/dsa/tag_lan9303.c` - `mtk_tag_rcv` in `net/dsa/tag_mtk.c` - `gsw1xx_tag_rcv` in `net/dsa/tag_mxl-gsw1xx.c` - `mxl862_tag_rcv` in `net/dsa/tag_mxl862xx.c` - `netc_rcv` in `net/dsa/tag_netc.c` - `ocelot_rcv` in `net/dsa/tag_ocelot.c` - `ocelot_defer_xmit` in `net/dsa/tag_ocelot_8021q.c` - `ocelot_rcv` in `net/dsa/tag_ocelot_8021q.c` - `qca_tag_rcv` in `net/dsa/tag_qca.c` - `rtl4a_tag_xmit` in `net/dsa/ |
| 18/2 | 2026/06/25 08:30 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"NET_DSA",
"NET_DSA_LOOP",
"NET_DSA_TAG_AR9331",
"NET_DSA_TAG_BRCM",
"NET_DSA_TAG_BRCM_LEGACY",
"NET_DSA_TAG_BRCM_PREPEND",
"NET_DSA_TAG_HELLCREEK",
"NET_DSA_TAG_GSWIP",
"NET_DSA_TAG_DSA",
"NET_DSA_TAG_EDSA",
"NET_DSA_TAG_MTK",
"NET_DSA_TAG_MXL_862XX",
"NET_DSA_TAG_MXL_GSW1XX",
"NET_DSA_TAG_KSZ",
"NET_DSA_TAG_NETC",
"NET_DSA_TAG_OCELOT",
"NET_DSA_TAG_OCELOT_8021Q",
"NET_DSA_TAG_QCA",
"NET_DSA_TAG_RTL4_A",
"NET_DSA_TAG_RTL8_4",
"NET_DSA_TAG_RZN1_A5PSW",
"NET_DSA_TAG_LAN9303",
"NET_DSA_TAG_SJA1105",
"NET_DSA_TAG_TRAILER",
"NET_DSA_TAG_VSC73XX_8021Q",
"NET_DSA_TAG_XRS700X",
"NET_DSA_TAG_YT921X"
],
"FocusSymbols": [
"dsa_switch_rcv",
"dsa_user_xmit",
"ar9331_tag_rcv",
"brcm_tag_xmit_ll",
"brcm_tag_rcv_ll",
"dsa_rcv_ll",
"edsa_rcv",
"ksz_common_rcv",
"ocelot_rcv",
"qca_tag_rcv",
"sja1105_rcv",
"trailer_rcv"
],
"Reasoning": "The patch refactors skb memory management in the DSA (Distributed Switch Architecture) subsystem. It shifts the responsibility of freeing the skb on error paths from the core DSA functions (dsa_user_xmit, dsa_switch_rcv) to the individual tagger drivers. This is a functional change that could introduce memory leaks or double frees if any error path in a tagger driver is missed or mishandled. The code is reachable in a virtualized environment by using the dsa_loop mock-up switch driver and dynamically changing the tagging protocol via sysfs.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"NET_DSA",
"NET_DSA_LOOP",
"NET_DSA_TAG_AR9331",
"NET_DSA_TAG_BRCM",
"NET_DSA_TAG_BRCM_LEGACY",
"NET_DSA_TAG_BRCM_PREPEND",
"NET_DSA_TAG_HELLCREEK",
"NET_DSA_TAG_GSWIP",
"NET_DSA_TAG_DSA",
"NET_DSA_TAG_EDSA",
"NET_DSA_TAG_MTK",
"NET_DSA_TAG_MXL_862XX",
"NET_DSA_TAG_MXL_GSW1XX",
"NET_DSA_TAG_KSZ",
"NET_DSA_TAG_NETC",
"NET_DSA_TAG_OCELOT",
"NET_DSA_TAG_OCELOT_8021Q",
"NET_DSA_TAG_QCA",
"NET_DSA_TAG_RTL4_A",
"NET_DSA_TAG_RTL8_4",
"NET_DSA_TAG_RZN1_A5PSW",
"NET_DSA_TAG_LAN9303",
"NET_DSA_TAG_SJA1105",
"NET_DSA_TAG_TRAILER",
"NET_DSA_TAG_VSC73XX_8021Q",
"NET_DSA_TAG_XRS700X",
"NET_DSA_TAG_YT921X"
],
"FocusSymbols": [
"dsa_switch_rcv",
"dsa_user_xmit",
"ar9331_tag_rcv",
"brcm_tag_xmit_ll",
"brcm_tag_rcv_ll",
"dsa_rcv_ll",
"edsa_rcv",
"ksz_common_rcv",
"ocelot_rcv",
"qca_tag_rcv",
"sja1105_rcv",
"trailer_rcv"
],
"Reasoning": "The patch refactors skb memory management in the DSA (Distributed Switch Architecture) subsystem. It shifts the responsibility of freeing the skb on error paths from the core DSA functions (dsa_user_xmit, dsa_switch_rcv) to the individual tagger drivers. This is a functional change that could introduce memory leaks or double frees if any error path in a tagger driver is missed or mishandled. The code is reachable in a virtualized environment by using the dsa_loop mock-up switch driver and dynamically changing the tagging protocol via sysfs.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|