From: sashiko-bot@kernel.org
To: "Birger Koblitz" <mail@birger-koblitz.de>
Cc: linux-usb@vger.kernel.org
Subject: Re: [PATCH net-next v20 07/13] ax88179_178a: Add VLAN offload support for AX88179A
Date: Sat, 07 Nov 2026 07:21:53 +0000 [thread overview]
Message-ID: <sashiko-outbox-202697@kernel.org> (raw)
In-Reply-To: <20261106-ax88179a-v20-7-37b5a1189983@birger-koblitz.de>
Thank you for your contribution! Sashiko AI review found 5 potential
issues to consider:
- [Medium] net: usb: ax88179: unchecked USB writes in
ax88179a_set_features() loop
- [Medium] net: usb: ax88179: uninitialized stack read on short USB read
- [Medium] net: usb: ax88179_178a: unchecked writes and partial state in
ax88179a_set_features()
- [Medium] net: usb: ax88179_178a: TX VLAN tag drop race in
ax88179a_tx_fixup()
- [Low] net: usb: ax88179_178a: duplicated VLAN filter update logic in
add/kill vid
--
commit 6bf60c56c4445f3486e6c4282f90f25fbd952f48
Author: Birger Koblitz <mail@birger-koblitz.de>
ax88179_178a: Add VLAN offload support for AX88179A
This commit adds TX VLAN tagging, RX VLAN stripping, and RX VLAN filter
offload configuration 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;
[Severity: Medium]
Can ax88179a_vlan_rx_add_vid() and ax88179a_set_features() read
uninitialized stack memory from reg8 and tmp when a 1-byte
ax88179_read_cmd() returns 0?
Unlike the size == 2 and size == 4 cases in ax88179_read_cmd(), a 1-byte
read passes the caller's pointer directly to __usbnet_read_cmd(), which
only copies into data when usb_control_msg() returns err > 0. If a short
transfer returns 0, reg8 here and tmp in the NETIF_F_HW_VLAN_CTAG_FILTER
disable and NETIF_F_HW_VLAN_CTAG_RX paths of ax88179a_set_features() are
left uninitialized and then written back to AX88179A_VLAN_ID_CONTROL,
corrupting the register and leaking a stack byte over USB.
> +
> + /* 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: 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 the bit in reg16 (and the two
copies have already diverged in how reg8 and reg16 are initialized). A
shared helper taking a boolean flag would avoid the duplication.
> @@ -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);\n> + }
[Severity: Medium]
Should the three USB writes inside this loop check for errors and break out
early?
If a write fails transiently and the final AX_VLAN_CONTROL_VFE write
succeeds, hardware VLAN filtering is enabled with stale entries left in the
filter table. On a persistent USB error or timeout, the loop runs all 768
synchronous control transfers under rtnl_lock, stalling for up to 768 *
USB_CTRL_SET_TIMEOUT and logging a warning on each failed transfer.
> + 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: Medium]
Can a failure partway through ax88179a_set_features() leave hardware
offload state out of sync with net->features?
When multiple features change in one call (for example, enabling both
NETIF_F_HW_VLAN_CTAG_FILTER and NETIF_F_HW_VLAN_CTAG_RX) and the later
step fails, returning a negative error causes __netdev_update_features() to
leave dev->features unchanged and skip vlan_get_rx_ctag_filter_info().
AX_VLAN_CONTROL_VFE (or checksum offload changes from
ax88179_set_features()) then stays active in hardware with an all-zero
filter table while dev->features still reports the feature as disabled.
[ ... ]
> @@ -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]
Does enabling NETIF_F_HW_VLAN_CTAG_TX here expose a race in
ax88179a_tx_fixup() that drops VLAN tags when the feature is toggled?
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
validate_xmit_skb()
validate_xmit_vlan()
/* NETIF_F_HW_VLAN_CTAG_TX set:
* tag stays in skb->vlan_tci
*/
__netdev_update_features()
dev->features &=
~NETIF_F_HW_VLAN_CTAG_TX;
ax88179a_tx_fixup()
if (dev->net->features &
NETIF_F_HW_VLAN_CTAG_TX)
<-- false, frame sent untagged
ax88179a_tx_fixup() (added in commit "ax88179_178a: Add HW support for
AX179A-based chips") checks dev->net->features & NETIF_F_HW_VLAN_CTAG_TX
and calls vlan_get_tag() instead of checking skb_vlan_tag_present(skb) and
skb_vlan_tag_get(skb). If NETIF_F_HW_VLAN_CTAG_TX is cleared after
validate_xmit_vlan() has already left the tag out-of-band in skb->vlan_tci,
the frame is transmitted without its VLAN tag.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261106-ax88179a-v20-0-37b5a1189983@birger-koblitz.de?part=7
next prev parent reply other threads:[~2026-11-07 7:21 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-06 7:21 [PATCH net-next v20 00/13] ax88179_178a: Add support for AX88179A-based chips Birger Koblitz
2026-11-06 7:21 ` [PATCH net-next v20 01/13] phylink: Add phylink_mac_interrupt Birger Koblitz
2026-11-06 10:11 ` Maxime Chevallier
2026-11-06 15:32 ` Birger Koblitz
2026-11-06 15:55 ` Andrew Lunn
2026-11-07 7:21 ` sashiko-bot
2026-11-06 7:21 ` [PATCH net-next v20 02/13] phylib: Add support for PHYs with broken forced mode Birger Koblitz
2026-11-07 7:21 ` sashiko-bot
2026-11-06 7:21 ` [PATCH net-next v20 03/13] ax88179_178a: Split driver into library and device specific code Birger Koblitz
2026-11-07 7:21 ` sashiko-bot
2026-11-06 7:21 ` [PATCH net-next v20 04/13] ax88179_178a: Add HW support for AX179A-based chips Birger Koblitz
2026-11-07 7:21 ` sashiko-bot
2026-11-06 7:21 ` [PATCH net-next v20 05/13] ax88179_178a: Add EEE configuration support for AX88179A MACs Birger Koblitz
2026-11-07 7:21 ` sashiko-bot
2026-11-06 7:21 ` [PATCH net-next v20 06/13] ax88179_178a: Add EEE configuration support for AX88179A PHYs Birger Koblitz
2026-11-07 7:21 ` sashiko-bot
2026-11-06 7:21 ` [PATCH net-next v20 07/13] ax88179_178a: Add VLAN offload support for AX88179A Birger Koblitz
2026-11-07 7:21 ` sashiko-bot [this message]
2026-11-06 7:21 ` [PATCH net-next v20 08/13] ax88179_178a: Add AX179A/AX279 multicast configuration Birger Koblitz
2026-11-07 7:21 ` sashiko-bot
2026-11-06 7:21 ` [PATCH net-next v20 09/13] ax88179_178a: Add Suspend/resume support for AX88179A/772D/279 Birger Koblitz
2026-11-07 7:21 ` sashiko-bot
2026-11-06 7:21 ` [PATCH net-next v20 10/13] ax88179_178a: Add ethtool get_drvinfo Birger Koblitz
2026-11-07 7:21 ` sashiko-bot
2026-11-06 7:21 ` [PATCH net-next v20 11/13] ax88179_178a: Update driver name and information Birger Koblitz
2026-11-07 7:21 ` sashiko-bot
2026-11-06 7:21 ` [PATCH net-next v20 12/13] ax88179_178a: Add support for AX88179A/772D/279 EEPROM access Birger Koblitz
2026-11-07 7:21 ` sashiko-bot
2026-11-06 7:21 ` [PATCH net-next v20 13/13] ax88796b: Add support for AX88772D, AX88179A and AX88279 Birger Koblitz
2026-11-07 7:21 ` 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-202697@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