CVE

CVE-2021-47553

Severity:
Pending analysis
Type:
Unavailable / Other
Publication date:
24/05/2024
Last modified:
24/05/2024

Description

In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> sched/scs: Reset task stack state in bringup_cpu()<br /> <br /> To hot unplug a CPU, the idle task on that CPU calls a few layers of C<br /> code before finally leaving the kernel. When KASAN is in use, poisoned<br /> shadow is left around for each of the active stack frames, and when<br /> shadow call stacks are in use. When shadow call stacks (SCS) are in use<br /> the task&amp;#39;s saved SCS SP is left pointing at an arbitrary point within<br /> the task&amp;#39;s shadow call stack.<br /> <br /> When a CPU is offlined than onlined back into the kernel, this stale<br /> state can adversely affect execution. Stale KASAN shadow can alias new<br /> stackframes and result in bogus KASAN warnings. A stale SCS SP is<br /> effectively a memory leak, and prevents a portion of the shadow call<br /> stack being used. Across a number of hotplug cycles the idle task&amp;#39;s<br /> entire shadow call stack can become unusable.<br /> <br /> We previously fixed the KASAN issue in commit:<br /> <br /> e1b77c92981a5222 ("sched/kasan: remove stale KASAN poison after hotplug")<br /> <br /> ... by removing any stale KASAN stack poison immediately prior to<br /> onlining a CPU.<br /> <br /> Subsequently in commit:<br /> <br /> f1a0a376ca0c4ef1 ("sched/core: Initialize the idle task with preemption disabled")<br /> <br /> ... the refactoring left the KASAN and SCS cleanup in one-time idle<br /> thread initialization code rather than something invoked prior to each<br /> CPU being onlined, breaking both as above.<br /> <br /> We fixed SCS (but not KASAN) in commit:<br /> <br /> 63acd42c0d4942f7 ("sched/scs: Reset the shadow stack when idle_task_exit")<br /> <br /> ... but as this runs in the context of the idle task being offlined it&amp;#39;s<br /> potentially fragile.<br /> <br /> To fix these consistently and more robustly, reset the SCS SP and KASAN<br /> shadow of a CPU&amp;#39;s idle task immediately before we online that CPU in<br /> bringup_cpu(). This ensures the idle task always has a consistent state<br /> when it is running, and removes the need to so so when exiting an idle<br /> task.<br /> <br /> Whenever any thread is created, dup_task_struct() will give the task a<br /> stack which is free of KASAN shadow, and initialize the task&amp;#39;s SCS SP,<br /> so there&amp;#39;s no need to specially initialize either for idle thread within<br /> init_idle(), as this was only necessary to handle hotplug cycles.<br /> <br /> I&amp;#39;ve tested this on arm64 with:<br /> <br /> * gcc 11.1.0, defconfig +KASAN_INLINE, KASAN_STACK<br /> * clang 12.0.0, defconfig +KASAN_INLINE, KASAN_STACK, SHADOW_CALL_STACK<br /> <br /> ... offlining and onlining CPUS with:<br /> <br /> | while true; do<br /> | for C in /sys/devices/system/cpu/cpu*/online; do<br /> | echo 0 &gt; $C;<br /> | echo 1 &gt; $C;<br /> | done<br /> | done