Skip to content

aq(4): Fix OOB write in RSS table packing (no link / panic)#2232

Open
DominoTree wants to merge 2 commits into
freebsd:mainfrom
DominoTree:aq-rss-oob-fix
Open

aq(4): Fix OOB write in RSS table packing (no link / panic)#2232
DominoTree wants to merge 2 commits into
freebsd:mainfrom
DominoTree:aq-rss-oob-fix

Conversation

@DominoTree
Copy link
Copy Markdown

Fix an out-of-bounds stack write in aq_hw_rss_set(). RSS table entries are 3 bits (8 queues max), but with more than 8 RX rings rss_table[] holds larger values; the 32-bit write then spills one uint16_t past bitary[] and corrupts the stack, so the NIC never links or the kernel panics. Mask each value to 3 bits and pack 16 bits at a time to keep the write in bounds.

Confirmed on AQC107 (firmware 3.1.88) under FreeBSD 15.0-RELEASE: with the OOB write the interface attached but stayed "no carrier"; removed, link negotiates 1000baseT full-duplex and passes traffic.

cc @emaste

Fix an out-of-bounds stack write in aq_hw_rss_set().  RSS table entries
are 3 bits (8 queues max), but with more than 8 RX rings rss_table[] holds
larger values; the 32-bit write then spills one uint16_t past bitary[]
and corrupts the stack, so the NIC never links or the kernel panics.
Mask each value to 3 bits and pack 16 bits at a time to keep the write
in bounds.

Confirmed on AQC107 (firmware 3.1.88) under FreeBSD 15.0-RELEASE: with the
OOB write the interface attached but stayed "no carrier"; removed, link
negotiates 1000baseT full-duplex and passes traffic.

Signed-off-by: Nick Price <nick@spun.io>
@DominoTree
Copy link
Copy Markdown
Author

Cross-posted at freebsd/freebsd-ports#522 to fix things for existing users before aq(4) lands

aq_if_attach_post() built the RSS indirection table with
	rss_table[i] = i & (rx_rings_count - 1);
which assumes rx_rings_count is a power of two.  iflib does not
guarantee that (queue counts such as 6, 12 or 24 are possible), so the
mask left some queues with no entries and skewed the hash distribution.
When rx_rings_count was 0 the (count - 1) underflow also turned the mask
into a no-op rather than failing safe.

Use a modulo over min(rx_rings_count, HW_ATL_RSS_QUEUES_MAX) instead.
The redirection-table field is 3 bits wide, so the hardware can only
hash across 8 queues regardless of ring count; capping here keeps the
table values in range and complements the bounds fix in aq_hw_rss_set().

Signed-off-by: Nick Price <nick@spun.io>
@DominoTree
Copy link
Copy Markdown
Author

(Added a second small commit with another RSS fix)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant