[BUG] drivers/net/lan9250.c: `.bss`/global `pktbuf` overflow in `lan9250_recv_buffer` — RX-status packet length bounded only by `DEBUGASSERT` (SPI path only)
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 68/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- c
- 領域
- embedded-iot
調査の方向性
drivers/net/lan9250.c の lan9250_receive() と lan9250_recv_buffer() から始めてください。次に、pktbuf のサイズの決まり方と、SPI および QSPI/SQI の各経路でデータをどのようにコピーするかを確認してください。各コピーの前に常に有効な容量チェックを追加し、大きすぎるフレームを破棄してください。受信した長さによって、どちらの経路でも pktbuf の範囲を超えて書き込まれない状態になれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Description / Steps to reproduce the issue
In drivers/net/lan9250.c (LAN9250 Ethernet driver over SPI/QSPI) the received frame length taken
from the RX Status FIFO is used as a copy length into priv->pktbuf, bounded on the SPI path only
by an assert that compiles to nothing in the default build, and on the QSPI/SQI path by no capacity
check at all. priv is a static global object, so this is an out-of-bounds write into .bss
that first clobbers the structure members immediately following pktbuf (a watchdog timer and several
work structures) and then adjacent globals. The attacker is a peer on the same L2 network sending an
oversized frame, or a malicious/faulty LAN9250 PHY.
lan9250_receive() takes the received frame length from the LAN9250 RX Status FIFO register and
passes it as the copy length, with only a non-zero check:
/* drivers/net/lan9250.c:1747-1748 (lan9250_receive) */
regval = lan9250_get_reg(priv, LAN9250_RXSFR); /* RX Status FIFO register */
pktlen = (regval & RXSFF_PL_M) >> RXSFF_PL_S; /* 14-bit length field, 0..16383 */
if (pktlen) /* only a non-zero check */
lan9250_recv_buffer(priv, priv->dev.d_buf, pktlen); /* buflen = pktlen */
The copy then runs into priv->pktbuf. On the SPI path the length is bounded only by a
DEBUGASSERT; on the QSPI/SQI path there is no capacity check:
/* drivers/net/lan9250.c:853 (inside #ifdef CONFIG_LAN9250_SPI) */
DEBUGASSERT(buflen <= sizeof(priv->pktbuf)); /* SPI path: default-off assert */
...
SPI_RECVBLOCK(priv->spi, buffer, buflen); /* buffer = priv->dev.d_buf = priv->pktbuf */
/* drivers/net/lan9250.c:881-899 (#else — QSPI/SQI path) */
meminfo.buflen = buflen; /* no capacity check at all */
QSPI_MEMORY(priv->qspi, &meminfo);
priv->pktbuf is uint32_t pktbuf[LAN9250_PKTBUF_SIZE / 4] (:212), with
LAN9250_PKTBUF_SIZE = LAN9250_ALIGN(MAX_NETDEV_PKTSIZE + CONFIG_NET_GUARDSIZE + 4) (:142). In the
default IPv4/Ethernet config (CONFIG_NET_ETH_PKTSIZE = 590, CONFIG_NET_GUARDSIZE = 2) that is
ALIGN(596) = 596 bytes — about one max Ethernet frame. Any ordinary frame larger than ~596 bytes
(a normal 1514/1518-byte Ethernet frame already qualifies) therefore overflows it. pktlen is a
14-bit RX-status register field (max 16383); that width is the hardware status-field size, not a
demonstration that a peer can inject a 16 KB frame — the practically reachable and sufficient case is
simply "frame > ~596 bytes".
Memory class: the driver state is a static global, not a heap allocation:
/* drivers/net/lan9250.c:230 */
static struct lan9250_driver_s g_lan9250;
/* :2440 / :2512 */ priv = &g_lan9250; /* no kmm_malloc/kmm_zalloc of the driver state */
pktbuf (:212) is immediately followed in the struct by txtout_timer (struct wdog_s),
txtout_work / txpoll_work / irq_work (struct work_s), and dev (:214-224). So the overflow
is a .bss/global-buffer overflow that corrupts those sibling members (watchdog + work queue
state) first, then neighbouring .bss objects — it is not a heap overflow.
Configuration dimension:
- SPI build,
CONFIG_DEBUG_ASSERTIONS = n(default): the guard is compiled out → overflow. - SPI build,
CONFIG_DEBUG_ASSERTIONS = y: the assert fires → controlled panic (DoS), no overflow. - QSPI/SQI build (
#elsepath): there is no capacity check in any configuration, so enabling
assertions does not prevent the overflow on QSPI/SQI targets.
Why this is a bug: the length is a parameter at the sink (lan9250_recv_buffer)
that originates in the caller (lan9250_receive), and the only guard anywhere on the SPI path is the
default-off DEBUGASSERT at :853 (and nothing at all on the QSPI path). The caller's if (pktlen)
check is non-zero-only, with no upper bound against MAX_NETDEV_PKTSIZE before handing the
device-reported length to the copy.
Steps:
- Build the LAN9250 driver (SPI with default
CONFIG_DEBUG_ASSERTIONSunset, or any QSPI/SQI build). - A peer on the same L2 network sends a frame larger than ~596 bytes (an ordinary full-size Ethernet
frame suffices), or a malicious/faulty LAN9250 PHY reports an oversized RX-status length. - The copy writes
pktlenbytes into the 596-byteg_lan9250.pktbuf, overflowing into the adjacent
watchdog/work members and.bss.
An AddressSanitizer build of the copy with the real buffer sizing (as a 596-byte global region)
reports a global-buffer-overflow WRITE.
Suggested fix: add an always-compiled check before lan9250_recv_buffer, and/or replace the
DEBUGASSERT, and add the equivalent check on the QSPI/SQI path:
if (pktlen > MAX_NETDEV_PKTSIZE)
{
/* drop oversized frame */
return;
}
and in lan9250_recv_buffer replace the SPI DEBUGASSERT with if (buflen > sizeof(priv->pktbuf)) return;
and add the same guard before the QSPI QSPI_MEMORY transfer.
On which OS does this issue occur?
[OS: Linux]
What is the version of your OS?
ubuntu 22
NuttX Version
master
Issue Architecture
[Arch: all]
Issue Area
[Area: Drivers]
Host information
No response
Verification
- I have verified before submitting the report.
- 主要言語
- C
- スター
- 4.1k
- フォーク
- 1.7k
- 平均マージ
- 1日 10時間
- マージ済み PR(30日)
- 649
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
apache/nuttx のほかの issue
-
Arch: all Area: Drivers OS: Linux Type: Bug
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
apache/nuttx#19435 · コメント 8 件 ·
メンテナーはふだん 1 日以内に返信
-
Type: Bug
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
apache/nuttx#17343 · コメント 4 件 ·
メンテナーはふだん 1 日以内に返信
-
Arch: all OS: Linux Type: Bug
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
apache/nuttx#16249 · コメント 7 件 ·
メンテナーはふだん 1 日以内に返信
-
Arch: arm Area: Build system OS: Mac Type: Bug
難易度 4/5 3〜5日 初心者へのやさしさ 15/100
メンテナーはふだん 1 日以内に返信
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
zephyrproject-rtos/zephyr#124160 ·
メンテナーはふだん 3 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
メンテナーはふだん 1 日以内に返信
-
area:docs area:stdlib found-by:duet-audit kind:docs-drift
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
InauguralSystems/EigenScript#2251 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
flux-framework/flux-coral2#513 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
ly05010419/MacNativeGames#1420 ·
メンテナーはふだん 1 日以内に返信