From: Breno Leitao <leitao@debian.org>
To: Ard Biesheuvel <ardb@kernel.org>,
Ilias Apalodimas <ilias.apalodimas@linaro.org>,
Borislav Petkov <bp@suse.de>, Andy Lutomirski <luto@kernel.org>,
Kees Cook <kees@kernel.org>, Tony Luck <tony.luck@intel.com>,
"Guilherme G. Piccoli" <gpiccoli@igalia.com>,
Thomas Gleixner <tglx@kernel.org>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>
Cc: linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org,
Breno Leitao <leitao@debian.org>,
kernel-team@meta.com
Subject: [PATCH v2 4/6] efi/runtime-wrappers: bound the wait for EFI runtime service calls
Date: Fri, 12 Jun 2026 04:01:31 -0700 [thread overview]
Message-ID: <20260612-efi_timeout-v2-4-f714bb016df6@debian.org> (raw)
In-Reply-To: <20260612-efi_timeout-v2-0-f714bb016df6@debian.org>
When an EFI runtime service hangs in firmware, the efi_rts_wq worker is
stuck inside the call and cannot be cancelled. __efi_queue_work() then
waits on the completion forever while holding efi_runtime_lock, so every
later EFI caller is wedged until reboot; the only symptom is a "workqueue
lockup" and tasks piling up on the semaphore.
Replace wait_for_completion() with wait_for_completion_timeout() bounded
by EFI_RTS_TIMEOUT (120 seconds). On timeout, clear EFI_RUNTIME_SERVICES
and return EFI_ABORTED so later callers fail fast at the entry check
instead of each paying another 120 seconds. The wedged worker is
intentionally leaked and keeps ownership of efi_rts_work.
Known limitation: the efi_rts_args the worker holds points into the
caller's stack frame; if firmware unblocks after the timeout and writes
the output buffers, they land in reused memory. Firmware hung this long
rarely recovers; a follow-up could bounce the buffers through kmalloc.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
drivers/firmware/efi/runtime-wrappers.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c
index 0cd350760446c..8badf0419a148 100644
--- a/drivers/firmware/efi/runtime-wrappers.c
+++ b/drivers/firmware/efi/runtime-wrappers.c
@@ -118,6 +118,14 @@ union efi_rts_args {
struct efi_runtime_work efi_rts_work;
+/*
+ * Upper bound on how long we wait for a single EFI runtime service
+ * call to finish before declaring firmware wedged. Chosen to be longer
+ * than any plausible legitimate call (including UpdateCapsule on slow
+ * SPI-NOR) while still bounding userspace wait time.
+ */
+#define EFI_RTS_TIMEOUT (120 * HZ)
+
/*
* efi_queue_work: Queue EFI runtime service call and wait for completion
* @_rts: EFI runtime service function identifier
@@ -342,7 +350,13 @@ static efi_status_t __efi_queue_work(enum efi_rts_ids id,
goto exit;
}
- wait_for_completion(&efi_rts_work.efi_rts_comp);
+ if (!wait_for_completion_timeout(&efi_rts_work.efi_rts_comp,
+ EFI_RTS_TIMEOUT)) {
+ pr_err("EFI runtime service %d wedged in firmware; disabling EFI runtime services\n",
+ id);
+ clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
+ return EFI_ABORTED;
+ }
WARN_ON_ONCE(efi_rts_work.status == EFI_ABORTED);
exit:
--
2.53.0-Meta
next prev parent reply other threads:[~2026-06-12 11:02 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-12 11:01 [PATCH v2 0/6] efi/runtime-wrappers: bound the wait for EFI runtime service calls Breno Leitao
2026-06-12 11:01 ` [PATCH v2 1/6] efi: fix stale reference to efi_recover_from_page_fault() Breno Leitao
2026-06-12 11:01 ` [PATCH v2 2/6] efi/runtime-wrappers: handle queue_work() failure with goto exit Breno Leitao
2026-06-12 11:01 ` [PATCH v2 3/6] efi/runtime-wrappers: check EFI_RUNTIME_SERVICES before using efi_rts_work Breno Leitao
2026-06-12 11:01 ` Breno Leitao [this message]
2026-06-12 11:01 ` [PATCH v2 5/6] efi/runtime-wrappers: honour EFI_RUNTIME_SERVICES in the non-blocking paths Breno Leitao
2026-06-16 12:10 ` Breno Leitao
2026-06-12 11:01 ` [PATCH v2 6/6] efi/runtime-wrappers: retire the worker if a wedged call ever returns Breno Leitao
2026-06-12 11:11 ` Ard Biesheuvel
2026-06-16 10:13 ` Breno Leitao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260612-efi_timeout-v2-4-f714bb016df6@debian.org \
--to=leitao@debian.org \
--cc=ardb@kernel.org \
--cc=bp@alien8.de \
--cc=bp@suse.de \
--cc=dave.hansen@linux.intel.com \
--cc=gpiccoli@igalia.com \
--cc=hpa@zytor.com \
--cc=ilias.apalodimas@linaro.org \
--cc=kees@kernel.org \
--cc=kernel-team@meta.com \
--cc=linux-efi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mingo@redhat.com \
--cc=tglx@kernel.org \
--cc=tony.luck@intel.com \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.