From: sashiko-bot@kernel.org
To: "Birger Koblitz" <mail@birger-koblitz.de>
Cc: linux-usb@vger.kernel.org
Subject: Re: [PATCH net-next v21 07/13] ax88179_178a: Add VLAN offload support for AX88179A
Date: Sun, 15 Nov 2026 10:51:54 +0000 [thread overview]
Message-ID: <sashiko-outbox-215420@kernel.org> (raw)
In-Reply-To: <20261114-ax88179a-v21-7-c2d34410bcbe@birger-koblitz.de>
Thank you for your contribution! Sashiko AI review found 5 potential
issues to consider:
- [Medium] net: usb: ax88179: uninitialized stack read and short USB
read in VLAN ops
- [Medium] net: usb: ax88179: unchecked USB writes in
ax88179a_set_features() loop
- [Medium] net: usb: ax88179_178a: TX VLAN tag drop race in
ax88179a_tx_fixup()
- [Low] net: usb: ax88179_178a: partial feature state in
ax88179a_set_features()
- [Low] net: usb: ax88179_178a: duplicated VLAN filter update logic in
add/kill vid
--
commit a2245f1909a4b4c924abeed75400e9c875dcb39c
Author: Birger Koblitz <mail@birger-koblitz.de>
ax88179_178a: Add VLAN offload support for AX88179A
This commit adds hardware VLAN offload and filtering callbacks
(NETIF_F_HW_VLAN_CTAG_TX, NETIF_F_HW_VLAN_CTAG_RX, and
NETIF_F_HW_VLAN_CTAG_FILTER) for AX88179A-based USB network devices.
> diff --git a/drivers/net/usb/ax88179a_devices.c b/drivers/net/usb/ax88179a_devices.c
> index 272e923656832..4207d2cc2b865 100644
> --- a/drivers/net/usb/ax88179a_devices.c
> +++ b/drivers/net/usb/ax88179a_devices.c
> @@ -258,6 +258,88 @@ static const struct ethtool_ops ax88179a_ethtool_ops = {
> .get_ts_info = ethtool_op_get_ts_info,
> };
>
> +static int ax88179a_vlan_rx_kill_vid(struct net_device *net, __be16 proto, u16 vid)
> +{
> + struct usbnet *dev = netdev_priv(net);
> + u16 reg16 = 0;
> + u8 vlan_ctrl;
> + int ret = 0;
> + u8 reg8 = 0;
> +
> + ret = ax88179_read_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, ®8);
> + if (ret < 0)
> + return ret;
> + vlan_ctrl = reg8;
> +
> + /* Address */
> + reg8 = (vid / 16);
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_ADDRESS, 1, 1, ®8);
> + if (ret < 0)
> + return ret;
> +
> + /* Data */
> + reg8 = vlan_ctrl | AX_VLAN_CONTROL_RD;
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, ®8);
> + if (ret < 0)
> + return ret;
> +
> + ret = ax88179_read_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_DATA0, 2, 2, ®16);
> + if (ret < 0)
> + return ret;
> + reg16 &= ~(1 << (vid % 16));
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_DATA0, 2, 2, ®16);
> + if (ret < 0)
> + return ret;
> +
> + reg8 = vlan_ctrl | AX_VLAN_CONTROL_WE;
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, ®8);
> + if (ret < 0)
> + return ret;
> +
> + return 0;
> +}
> +
> +static int ax88179a_vlan_rx_add_vid(struct net_device *net, __be16 proto, u16 vid)
> +{
> + struct usbnet *dev = netdev_priv(net);
> + u8 vlan_ctrl;
> + int ret = 0;
> + u16 reg16;
> + u8 reg8;
> +
> + ret = ax88179_read_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, ®8);
> + if (ret < 0)
> + return ret;
> + vlan_ctrl = reg8;
> +
> + /* Address */
> + reg8 = (vid / 16);
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_ADDRESS, 1, 1, ®8);
> + if (ret < 0)
> + return ret;
> +
> + /* Data */
> + reg8 = vlan_ctrl | AX_VLAN_CONTROL_RD;
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, ®8);
> + if (ret < 0)
> + return ret;
> +
> + ret = ax88179_read_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_DATA0, 2, 2, ®16);
> + if (ret < 0)
> + return ret;
> + reg16 |= (1 << (vid % 16));
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_DATA0, 2, 2, ®16);
> + if (ret < 0)
> + return ret;
> +
> + reg8 = vlan_ctrl | AX_VLAN_CONTROL_WE;
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, ®8);
> + if (ret < 0)
> + return ret;
> +
> + return 0;
> +}
[Severity: Medium]
Can a 0-byte USB read in ax88179a_vlan_rx_add_vid() or
ax88179a_set_features() write uninitialized stack memory into
AX88179A_VLAN_ID_CONTROL?
For 1-byte reads, ax88179_read_cmd() passes the caller's pointer directly
to __usbnet_read_cmd(), which only copies into the buffer when
usb_control_msg() returns > 0. If a control read returns 0, reg8 in
ax88179a_vlan_rx_add_vid() and tmp in ax88179a_set_features() remain
uninitialized because the callers only check ret < 0, and that stack byte
is then modified and written back to AX88179A_VLAN_ID_CONTROL.
Similarly, the 2-byte reads of AX88179A_VLAN_ID_DATA0 only check ret < 0
instead of ret < 2, so a short read leaves reg16 zeroed or partially
populated and causes the subsequent write to clear the other 15 VIDs in
the same (vid / 16) filter entry.
[Severity: Low]
This isn't a bug, but ax88179a_vlan_rx_kill_vid() and
ax88179a_vlan_rx_add_vid() duplicate the same five-step register sequence
and only differ in whether they clear or set BIT(vid % 16) in reg16.
Could they share a common helper taking a boolean flag?
[ ... ]
> @@ -517,6 +599,75 @@ static int ax88179a_mii_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
> return phylink_mii_ioctl(data->phylink, rq, cmd);
> }
>
> +static int ax88179a_set_features(struct net_device *net, netdev_features_t features)
> +{
> + struct usbnet *dev = netdev_priv(net);
> + netdev_features_t changed;
> + int ret;
> + u8 tmp;
> +
> + changed = net->features ^ features;
> +
> + ret = ax88179_set_features(net, features);
> + if (ret)
> + return ret;
> +
> + if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
> + if (features & NETIF_F_HW_VLAN_CTAG_FILTER) {
> + u8 vlan_state = 0;
> +
> + ret = ax88179_read_cmd(dev, AX_ACCESS_MAC,
> + AX88179A_VLAN_ID_CONTROL, 1, 1, &vlan_state);
> + if (ret < 0)
> + return ret;
> +
> + for (int i = 0; i < 256; i++) {
> + /* Address */
> + tmp = i;
> + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_ADDRESS,
> + 1, 1, &tmp);
> + /* Data */
> + ax88179_write_u16(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_DATA0,
> + 2, 0);
> + /* Write-Execute */
> + ax88179_write_u8(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL,
> + 1, vlan_state | AX_VLAN_CONTROL_WE);
> + }
[Severity: Medium]
Should the USB writes inside this loop check for errors?
If any write fails transiently while the final write enabling
AX_VLAN_CONTROL_VFE succeeds, hardware VLAN filtering is enabled over an
incompletely cleared filter table with stale VID entries. On a persistent
USB error, the loop also runs all 768 synchronous control transfers under
rtnl_lock instead of bailing out on the first failure.
> + vlan_state |= AX_VLAN_CONTROL_VFE;
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC,
> + AX88179A_VLAN_ID_CONTROL, 1, 1, &vlan_state);
> + if (ret < 0)
> + return ret;
> + } else {
> + ret = ax88179_read_cmd(dev, AX_ACCESS_MAC,
> + AX88179A_VLAN_ID_CONTROL, 1, 1, &tmp);
> + if (ret < 0)
> + return ret;
> + tmp &= ~AX_VLAN_CONTROL_VFE;
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC,
> + AX88179A_VLAN_ID_CONTROL, 1, 1, &tmp);
> + if (ret < 0)
> + return ret;
> + }
> + }
> +
> + if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
> + ret = ax88179_read_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL,
> + 1, 1, &tmp);
> + if (ret < 0)
> + return ret;
> + if (features & NETIF_F_HW_VLAN_CTAG_RX)
> + tmp |= AX_VLAN_CONTROL_VSO;
> + else
> + tmp &= ~AX_VLAN_CONTROL_VSO;
> + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL,
> + 1, 1, &tmp);
> + if (ret < 0)
> + return ret;
> + }
> + return 0;
> +}
[Severity: Low]
Can a late failure in ax88179a_set_features() leave hardware offload state
out of sync with net->features?
When multiple features are changed at once and a later register access
fails, __netdev_update_features() aborts without updating net->features or
repopulating the VLAN filter table, while earlier changes stay active in
hardware. For example, if enabling NETIF_F_HW_VLAN_CTAG_FILTER succeeds
and the NETIF_F_HW_VLAN_CTAG_RX step fails, AX_VLAN_CONTROL_VFE remains
enabled with an all-zero filter table, and any checksum bits already
toggled via XOR in ax88179_set_features() remain inverted relative to
net->features.
[ ... ]
> @@ -612,9 +766,11 @@ static int ax88179a_bind(struct usbnet *dev, struct usb_interface *intf)
> dev->mii.supports_gmii = 1;
>
> dev->net->features |= NETIF_F_SG | NETIF_F_IP_CSUM |
> - NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO;
> + NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO |
> + NETIF_F_HW_VLAN_CTAG_TX;
>
> dev->net->hw_features |= dev->net->features;
> + dev->net->hw_features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER;
[Severity: Medium]
Can toggling NETIF_F_HW_VLAN_CTAG_TX at runtime cause ax88179a_tx_fixup()
to transmit VLAN-tagged packets without their VLAN tag?
drivers/net/usb/ax88179a_devices.c:ax88179a_tx_fixup() {
...
if ((dev->net->features & NETIF_F_HW_VLAN_CTAG_TX) && (vlan_get_tag(skb, &tci) >= 0)) {
tx_desc |= AX179A_TX_DESC_VLAN;
tx_desc |= FIELD_PREP(AX179A_TX_DESC_VLAN_ID, (u64)tci);
}
...
}
CPU0 CPU1
dev_hard_start_xmit()
validate_xmit_skb()
validate_xmit_vlan()
/* tag left in skb->vlan_tci */
__netdev_update_features()
/* clears NETIF_F_HW_VLAN_CTAG_TX */
ndo_start_xmit()
ax88179a_tx_fixup()
/* skips AX179A_TX_DESC_VLAN */ <-- sent untagged
Now that NETIF_F_HW_VLAN_CTAG_TX is exposed in features and hw_features,
disabling it while packets validated under NETIF_F_HW_VLAN_CTAG_TX are in
flight causes both the feature check in ax88179a_tx_fixup() and
vlan_get_tag() to ignore skb->vlan_tci. Checking skb_vlan_tag_present(skb)
and reading the tag with skb_vlan_tag_get(skb) avoids dropping the tag.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261114-ax88179a-v21-0-c2d34410bcbe@birger-koblitz.de?part=7
next prev parent reply other threads:[~2026-11-15 10:51 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-14 10:50 [PATCH net-next v21 00/13] ax88179_178a: Add support for AX88179A-based chips Birger Koblitz
2026-11-14 10:50 ` [PATCH net-next v21 01/13] phylink: Add phylink_mac_interrupt Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:50 ` [PATCH net-next v21 02/13] phylib: Add support for PHYs with broken forced mode Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:50 ` [PATCH net-next v21 03/13] ax88179_178a: Split driver into library and device specific code Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 04/13] ax88179_178a: Add HW support for AX179A-based chips Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 05/13] ax88179_178a: Add EEE configuration support for AX88179A MACs Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 06/13] ax88179_178a: Add EEE configuration support for AX88179A PHYs Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 07/13] ax88179_178a: Add VLAN offload support for AX88179A Birger Koblitz
2026-11-15 10:51 ` sashiko-bot [this message]
2026-11-14 10:51 ` [PATCH net-next v21 08/13] ax88179_178a: Add AX179A/AX279 multicast configuration Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 09/13] ax88179_178a: Add Suspend/resume support for AX88179A/772D/279 Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 10/13] ax88179_178a: Add ethtool get_drvinfo Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 11/13] ax88179_178a: Update driver name and information Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 12/13] ax88179_178a: Add support for AX88179A/772D/279 EEPROM access Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
2026-11-14 10:51 ` [PATCH net-next v21 13/13] ax88796b: Add support for AX88772D, AX88179A and AX88279 Birger Koblitz
2026-11-15 10:51 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-215420@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=mail@birger-koblitz.de \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox