core: no defined synchronisation for `libusb_device::parent_dev`
まだ誰も着手していません。
評価
調査の方向性
Start by reading libusbi.h and the parent_dev accesses in core.c, hotplug.c, and Darwin's process_new_device. Decide how synchronization and references should protect readers and writers, checking lock ordering and existing tests before choosing an approach. Done means concurrent device-list walks and re-enumeration no longer race or leave readers with an unreferenced parent; validate with concurrency testing such as TSan.
索引モデルが issue の本文から書いたものです。
説明
core: no defined synchronisation for libusb_device::parent_dev
parent_dev is a plain struct libusb_device * (libusbi.h:523) with no documented or
enforced locking rule, and the code currently makes three different assumptions about it.
Public readers take no lock. libusb_get_port_numbers (core.c) walks the chain twice,
and libusb_get_parent returns the pointer directly. Neither acquires anything.
One core path assumes ctx->usb_devs_lock. usbi_hotplug_exit walks and mutates
whole parent chains through usbi_recursively_remove_parents (hotplug.c:229) while
holding that lock (hotplug.c:219-233).
Backends write it without any lock. The darwin backend is currently the only one that
rewrites the field on a device that is already published to the application: on
re-enumeration, process_new_device resolves and stores a new parent. Linux and Windows
assign it only while constructing a fresh device.
The documented contracts differ too. libusb_get_parent tells callers to stay inside a
libusb_get_device_list() / libusb_free_device_list() block, which incidentally keeps a
reference on the parent. libusb_get_port_numbers carries no such requirement, so a caller
following the documentation can walk the chain with no reference held on anything but the
leaf device.
Evidence
TSan reports it directly when a device list walk runs concurrently with a re-enumeration,
from @mcuee's runs on #1886:
Read of size 8 at 0x…2390 by thread T2:
#0 libusb_get_port_numbers
Previous write of size 8 at 0x…2390 by thread T1:
#0 process_new_device
#1 darwin_devices_attached
Location is heap block of size 120 at 0x…2380 allocated by main thread:
#1 usbi_alloc_device
Offset 16 with size 8 is parent_dev (refcnt 0, ctx 8, parent_dev 16), and the
120-byte block matches PTR_ALIGN(sizeof(struct libusb_device)) plus darwin's 8-byte
device private data.
Candidate fixes
Make the field atomic. Smallest change, removes the C11 data race and the TSan report.
Touches libusbi.h and every backend that assigns the field. It does not stop a reader from
holding a pointer that is freed after it loads it.
Give the field a lock. ctx->usb_devs_lock is the natural candidate, since
usbi_hotplug_exit already treats it that way. This would mean libusb_get_port_numbers
acquiring it around the walk and backends acquiring it around the update. It closes the
race properly, but it introduces locking into a public accessor that has never taken one,
so it needs a look at lock ordering and at what callers may already hold.
Either way, the reader also has to hold a reference on each device it walks if the
use-after-free window is to be closed rather than narrowed.
Related
#1915 bounds the fill loop in libusb_get_port_numbers so a chain that changes length
between its two passes cannot write outside the caller's array. That removes the memory
corruption, not the race.
#1917 narrows the window on Darwin side: the new parent is
stored before the old one is released, so the field always holds either NULL or a
referenced device. A walk that already loaded the old pointer can still race.
Assisted-by: claude-code:claude-opus-5
- 主要言語
- C
- スター
- 6.2k
- フォーク
- 2.1k
- 平均マージ
- 28日 9時間
- マージ済み PR(30日)
- 1
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
libusb/libusb のほかの issue
-
build_ci
難易度 2/5 1〜3時間 初心者へのやさしさ 67/100
-
android core
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
-
Windows version of libusb-master (MSVC build) can't be built when git installed w/o bash対応中かも @Youw が 21 日前に担当しました。 オープンwindows
-
windows
難易度 4/5 3〜5日 初心者へのやさしさ 48/100
-
core enhancement
難易度 5/5 1週間以上 初心者へのやさしさ 30/100
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
DaveGamble/cJSON#1100 ·
-
UB: (int) cast of a user double outside int range in dispatch / vm_index_is_int / flat_index_atオープンarea:runtime-vm
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
InauguralSystems/EigenScript#1748 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
leanprover/lean4#15677 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 2 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
wasm-micro-runtime/wasm-micro-runtime#5159 ·
メンテナーはふだん 7 日以内に返信