Page MenuHomeFreeBSD

bhyve e1000: Sanitize transmit ring indices.
ClosedPublic

Authored by jhb on Aug 19 2022, 11:07 PM.
Tags
None
Referenced Files
F107523480: D36269.diff
Wed, Jan 15, 10:10 AM
Unknown Object (File)
Dec 13 2024, 12:49 PM
Unknown Object (File)
Oct 8 2024, 9:15 AM
Unknown Object (File)
Oct 8 2024, 9:15 AM
Unknown Object (File)
Oct 8 2024, 9:14 AM
Unknown Object (File)
Oct 8 2024, 9:14 AM
Unknown Object (File)
Oct 8 2024, 8:32 AM
Unknown Object (File)
Sep 25 2024, 4:08 AM
Subscribers

Details

Summary

When preparing to transmit pending packets, ensure that the head (TDH)
and tail (TDT) indices are in bounds. Note that validating values
when they are written is not sufficient along as the transmit length
(TDLEN) could be changed turning a value that was valid when written
into an out of bounds value.

While here, add further restrictions to the head register (TDH). The
manual states that writing to this value while transmit is enabled can
cause unexpected behavior and that it should only be written after a
reset. As such, ignore attempts to write while transmit is active,
and also ignore writes of non-zero values. Later e1000 chipsets have
this register as read-only.

PR: 264567
Reported by: Robert Morris <rtm@lcs.mit.edu>
Sponsored by: The FreeBSD Foundation

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 47027
Build 43916: arc lint + arc unit

Event Timeline

jhb requested review of this revision.Aug 19 2022, 11:07 PM
usr.sbin/bhyve/pci_e82545.c
1470

Is it possible esc_TDLEN could be zero?

usr.sbin/bhyve/pci_e82545.c
1470

Mmm, yes.

  • Ignore transmit attempts with an empty ring.
emaste added inline comments.
usr.sbin/bhyve/pci_e82545.c
1741–1744

This seems strange to me, why must tdh only be zero? Even if it seems quite unlikely there's a guest that would do so. Maybe commit in two parts so that the rest of this can be MFCd in days, while this could wait longer to catch anything unusual.

This revision is now accepted and ready to land.Aug 29 2022, 5:53 PM
usr.sbin/bhyve/pci_e82545.c
1741–1744

The earlier comment already alluded to this. There is no valid reason to really write to this register except to clear it on reset. Future e1000 chipsets make this register read-only and clear it to 0 on reset implicitly, so drivers that support a range of e1000 chipsets like if_em or the like shouldn't be writing non-zero values. Also, the documented way to add new credits to the transmit ring to indicate there are packets to send is to only write to the tail (TDT). TDH is really owned by the controller as the producer index of the queue.

The description from the manual is:

<quote>
This register contains the head pointer for the transmit descriptor ring. It holds a value that is an offset from the base, and indicates the in–progress descriptor. It points to a 16-byte datum. Hardware controls this pointer. The only time that software should write to this register is after a reset (TCTL.RST or CTRL.RST) and before enabling the transmit function (TCTL.EN). If software were to write to this register while the transmit function was enabled, the on-chip descriptor buffers can be invalidated and indeterminate operation can result. Reading the transmit descriptor head to determine which buffers have been used (and can be returned to the memory pool) is not reliable.
</quote>

While it doesn't explicitly say zero, no other value makes sense after reset.

usr.sbin/bhyve/pci_e82545.c
1741–1744

Sounds good

This revision was automatically updated to reflect the committed changes.