[Bug]: Linux guests sometimes hang at boot: RCU nesting underflow in rtR0MemObjLinuxVirtToPage (fix included)
Maintainer antworten meist innerhalb von 6 Tagen
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Anfängerfreundlichkeit
- 45/100
- Issue-Typ
- Bug
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- c, linux
- Bereich
- backend, operating-systems
Rechercherichtung
Start in src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c at rtR0MemObjLinuxVirtToPage(), where the issue identifies the PTE mapping and unmapping mismatch. Read the Linux version conditionals and compare the suggested fix with vmalloc_to_page() behavior. Done means the guest module no longer causes RCU nesting underflow or boot stalls on the described kernels; the issue gives a deterministic reproduction using vboxguest reload and repeated unshare -m true.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
Version
7.2.22
Host OS Type
Windows
Host OS name + version
Windows / Windows 11 Build 26300 / x86
Host Architecture
x86
Guest OS Type
Linux
Guest Architecture
x86
Guest OS name + version
Ubuntu 24.04, kernel 6.17.0-40-generic, Guest Additions 7.2.6
Component
Guest Additions/Other
What happened?
Linux guests with kernel 6.6+ sometimes hang at boot with rcu_preempt detected expedited stalls. The root cause is the RCU mismatch reported in #359, and it very likely also explains #861 and #227. The code is unchanged in 7.2.22 and on main.
Cause: Since Linux 6.6, pte_unmap() calls rcu_read_unlock(). On 6.5+ and RHEL 9.4+, rtR0MemObjLinuxVirtToPage() reads the PTE with __pte_map(), which takes no RCU lock, and then calls pte_unmap(). That leaves the caller's RCU nesting at −1. vboxguest hits this at module init, when VGDrvCommonProcessOptionsFromHost makes an HGCM call with a buffer on the (vmalloc'ed) stack. Usually this only causes the warning from #227. If an expedited RCU IPI reaches the loading task first, rcu_exp_handler() never reports a quiescent state, and the boot hangs:
WARNING: CPU: 3 PID: 443 at kernel/rcu/tree_exp.h:799 rcu_exp_handler
rcu: INFO: rcu_preempt detected expedited stalls on CPUs/tasks: { 3-...D } ...
Fix: pv is a kernel address, so read the PTE with pte_offset_kernel() and skip pte_unmap(), as vmalloc_to_page() has done since 6.5. E.g.:
--- a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
+++ b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
@@ -1310,7 +1310,13 @@ RTDECL(struct page *) rtR0MemObjLinuxVirtToPage(void *pv)
# endif
# if RTLNX_VER_MIN(6,5,0) || RTLNX_RHEL_RANGE(9,4, 9,99)
- pEntry = __pte_map(&u.Middle, ulAddr);
+ /* pv is a kernel address, so the page table is never in highmem and
+ * pte_offset_kernel() will do, like in vmalloc_to_page(). Don't pair
+ * __pte_map() with pte_unmap() here: since 6.6 (and in newer RHEL 9
+ * kernels) pte_unmap() does rcu_read_unlock() for the rcu_read_lock()
+ * taken by pte_offset_map(). __pte_map() doesn't take it, so that would
+ * leave the caller's RCU read-side nesting at -1. */
+ pEntry = pte_offset_kernel(&u.Middle, ulAddr);
# elif RTLNX_VER_MIN(2,5,5) || defined(pte_offset_map) /* As usual, RHEL 3 had pte_offset_map earlier. */
pEntry = pte_offset_map(&u.Middle, ulAddr);
# else
@@ -1319,7 +1325,9 @@ RTDECL(struct page *) rtR0MemObjLinuxVirtToPage(void *pv)
if (RT_UNLIKELY(!pEntry))
return NULL;
u.Entry = *pEntry;
-# if RTLNX_VER_MIN(2,5,5) || defined(pte_offset_map)
+# if RTLNX_VER_MIN(6,5,0) || RTLNX_RHEL_RANGE(9,4, 9,99)
+ /* pte_offset_kernel() mapped nothing, so there is nothing to unmap. */
+# elif RTLNX_VER_MIN(2,5,5) || defined(pte_offset_map)
pte_unmap(pEntry);
# endif
How can we reproduce this?
Guest kernel 6.6+ with CONFIG_PREEMPT_RCU=y and CONFIG_VMAP_STACK=y, e.g. Ubuntu 24.04 with the HWE kernel:
nm -u $(modinfo -n vboxguest) | grep rcu_readlists __rcu_read_unlock but not __rcu_read_lock.- Most boots log
WARNING ... tree_plugin.h ... rcu_sched_clock_irqin (udev-worker) when vboxguest loads. Some boots hang as above. - Deterministic: unload vboxguest and load it again with
finit_module()from a process that is pinned to one CPU and keeps busy-looping. Then rununshare -m true60 times. Each mount-namespace teardown waits for an expedited grace period, and the loop stalls permanently (0 of 60 after 65 s; 0.09 s without the reload).
Did you upload all of your necessary log files, screenshots, etc.?
- Yes, I've uploaded all pertinent files to this issue.
- Vorherrschende Sprache
- C
- Sterne
- 1.4k
- Forks
- 219
- PR-Merge-Kennzahlen
- Keine gemergten PRs in 30 T.
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Keine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus VirtualBox/virtualbox
-
enhancement
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 68/100
VirtualBox/virtualbox#979 ·
Maintainer antworten meist innerhalb von 6 Tagen
-
[Bug]: Guest Additions 7.2.20 vboxvideo fails to build on Linux kernel 6.12.113 (drm_fb_helper_restore_fbdev_mode_unlocked: too few arguments)Evtl. vergeben @Berbe hat das vor 11 Tagen übernommen. Offenbug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
VirtualBox/virtualbox#918 · 9 Kommentare ·
Maintainer antworten meist innerhalb von 6 Tagen
-
bug
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 12/100
VirtualBox/virtualbox#981 ·
Maintainer antworten meist innerhalb von 6 Tagen
-
bug
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 8/100
VirtualBox/virtualbox#980 ·
Maintainer antworten meist innerhalb von 6 Tagen
-
bug
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 18/100
VirtualBox/virtualbox#977 ·
Maintainer antworten meist innerhalb von 6 Tagen
Alle Issues in VirtualBox/virtualbox
Ähnliche Issues
-
bug good first issue
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 85/100
Maintainer antworten meist innerhalb von 1 Tag
-
Status: Opened
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 62/100
-
Status: Opened
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 64/100
Maintainer antworten meist innerhalb von 1 Tag
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 72/100
FriendsofECCE/ECCE#1018 ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 62/100
immortalwrt/immortalwrt#2522 ·