No description
  • C 96.9%
  • Assembly 0.9%
  • Rust 0.6%
  • Shell 0.6%
  • Python 0.5%
  • Other 0.3%
Find a file
Douglas Anderson 34fdc6c621 driver core: Don't let a device probe until it's ready
[ Upstream commit a2225b6e83 ]

The moment we link a "struct device" into the list of devices for the
bus, it's possible probe can happen. This is because another thread
can load the driver at any time and that can cause the device to
probe. This has been seen in practice with a stack crawl that looks
like this [1]:

  really_probe()
  __driver_probe_device()
  driver_probe_device()
  __driver_attach()
  bus_for_each_dev()
  driver_attach()
  bus_add_driver()
  driver_register()
  __platform_driver_register()
  init_module() [some module]
  do_one_initcall()
  do_init_module()
  load_module()
  __arm64_sys_finit_module()
  invoke_syscall()

As a result of the above, it was seen that device_links_driver_bound()
could be called for the device before "dev->fwnode->dev" was
assigned. This prevented __fw_devlink_pickup_dangling_consumers() from
being called which meant that other devices waiting on our driver's
sub-nodes were stuck deferring forever.

It's believed that this problem is showing up suddenly for two
reasons:
1. Android has recently (last ~1 year) implemented an optimization to
   the order it loads modules [2]. When devices opt-in to this faster
   loading, modules are loaded one-after-the-other very quickly. This
   is unlike how other distributions do it. The reproduction of this
   problem has only been seen on devices that opt-in to Android's
   "parallel module loading".
2. Android devices typically opt-in to fw_devlink, and the most
   noticeable issue is the NULL "dev->fwnode->dev" in
   device_links_driver_bound(). fw_devlink is somewhat new code and
   also not in use by all Linux devices.

Even though the specific symptom where "dev->fwnode->dev" wasn't
assigned could be fixed by moving that assignment higher in
device_add(), other parts of device_add() (like the call to
device_pm_add()) are also important to run before probe. Only moving
the "dev->fwnode->dev" assignment would likely fix the current
symptoms but lead to difficult-to-debug problems in the future.

Fix the problem by preventing probe until device_add() has run far
enough that the device is ready to probe. If somehow we end up trying
to probe before we're allowed, __driver_probe_device() will return
-EPROBE_DEFER which will make certain the device is noticed.

In the race condition that was seen with Android's faster module
loading, we will temporarily add the device to the deferred list and
then take it off immediately when device_add() probes the device.

Instead of adding another flag to the bitfields already in "struct
device", instead add a new "flags" field and use that. This allows us
to freely change the bit from different thread without worrying about
corrupting nearby bits (and means threads changing other bit won't
corrupt us).

[1] Captured on a machine running a downstream 6.6 kernel
[2] https://cs.android.com/android/platform/superproject/main/+/main:system/core/libmodprobe/libmodprobe.cpp?q=LoadModulesParallel

Cc: stable@vger.kernel.org
Fixes: 2023c610dc ("Driver core: add new device to bus's list before probing")
Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
Reviewed-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
Reviewed-by: Danilo Krummrich <dakr@kernel.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Link: https://patch.msgid.link/20260406162231.v5.1.Id750b0fbcc94f23ed04b7aecabcead688d0d8c17@changeid
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
History 2026-06-01 17:35:14 +02:00
arch x86/uprobes: Fix XOL allocation failure for 32-bit tasks 2026-06-01 17:35:09 +02:00
block blk-mq: use quiesced elevator switch when reinitializing queues 2026-06-01 17:35:09 +02:00
certs certs/blacklist_hashes.c: fix const confusion in certs blacklist 2022-06-22 14:22:01 +02:00
crypto crypto: algif_aead - Fix minimum RX size check for decryption 2026-04-30 11:24:38 +02:00
Documentation dt-bindings: auxdisplay: ht16k33: Use unevaluatedProperties to fix common property warning 2026-04-18 10:33:29 +02:00
drivers driver core: Don't let a device probe until it's ready 2026-06-01 17:35:14 +02:00
fs ocfs2: split transactions in dio completion to avoid credit exhaustion 2026-06-01 17:35:14 +02:00
include driver core: Don't let a device probe until it's ready 2026-06-01 17:35:14 +02:00
init init: handle bootloader identifier in kernel parameters 2025-10-19 16:21:45 +02:00
io_uring io_uring/poll: correctly handle io_poll_add() return value on update 2026-04-18 10:33:39 +02:00
ipc ipc: fix to protect IPCS lookups using RCU 2025-06-27 11:05:26 +01:00
kernel padata: Fix pd UAF once and for all 2026-06-01 17:35:14 +02:00
lib netlink: add nla be16/32 types to minlen array 2026-04-18 10:33:37 +02:00
LICENSES LICENSES/dual/CC-BY-4.0: Git rid of "smart quotes" 2021-07-15 06:31:24 -06:00
mm mm: blk-cgroup: fix use-after-free in cgwb_release_workfn() 2026-06-01 17:35:08 +02:00
net rxrpc: Fix missing validation of ticket length in non-XDR key preparsing 2026-06-01 17:35:12 +02:00
samples samples: mei: Fix building on musl libc 2025-08-28 16:24:07 +02:00
scripts scripts/dtc: Remove unused dts_version in dtc-lexer.l 2026-06-01 17:35:12 +02:00
security apparmor: fix race between freeing data and fs accessing it 2026-04-18 10:33:36 +02:00
sound ALSA: usb-audio: Evaluate packsize caps at the right place 2026-06-01 17:35:13 +02:00
tools x86/CPU/AMD: Prevent improper isolation of shared resources in Zen2's op cache 2026-05-15 14:48:45 +02:00
usr kbuild: hdrcheck: fix cross build with clang 2025-06-27 11:05:22 +01:00
virt KVM: Don't clobber irqfd routing type when deassigning irqfd 2026-02-11 13:35:27 +01:00
.clang-format clang-format: Update with the latest for_each macro list 2021-05-12 23:32:39 +02:00
.cocciconfig scripts: add Linux .cocciconfig for coccinelle 2016-07-22 12:13:39 +02:00
.get_maintainer.ignore Opt out of scripts/get_maintainer.pl 2019-05-16 10:53:40 -07:00
.gitattributes .gitattributes: use 'dts' diff driver for dts files 2019-12-04 19:44:11 -08:00
.gitignore Remove *.orig pattern from .gitignore 2024-10-17 15:11:10 +02:00
.mailmap mailmap: add Andrej Shadura 2021-10-18 20:22:03 -10:00
COPYING COPYING: state that all contributions really are covered by this file 2020-02-10 13:32:20 -08:00
CREDITS MAINTAINERS: Move Daniel Drake to credits 2021-09-21 08:34:58 +03:00
Kbuild kbuild: rename hostprogs-y/always to hostprogs/always-y 2020-02-04 01:53:07 +09:00
Kconfig kbuild: ensure full rebuild when the compiler is updated 2020-05-12 13:28:33 +09:00
MAINTAINERS staging: rtl8712: Remove driver using deprecated API wext 2025-12-07 06:09:36 +09:00
Makefile Linux 5.15.208 2026-05-23 13:40:45 +02:00
README Drop all 00-INDEX files from Documentation/ 2018-09-09 15:08:58 -06:00

Linux kernel
============

There are several guides for kernel developers and users. These guides can
be rendered in a number of formats, like HTML and PDF. Please read
Documentation/admin-guide/README.rst first.

In order to build the documentation, use ``make htmldocs`` or
``make pdfdocs``.  The formatted documentation can also be read online at:

    https://www.kernel.org/doc/html/latest/

There are various text files in the Documentation/ subdirectory,
several of them using the Restructured Text markup notation.

Please read the Documentation/process/changes.rst file, as it contains the
requirements for building and running the kernel, and information about
the problems which may result by upgrading your kernel.