Re: [PATCH] efivarfs: Rate limit statfs() handler
Richard Lyu <[email protected]>
| Newsgroups | org.kernel.vger.linux-efi,org.kernel.vger.stable |
|---|---|
| Message-ID | <aob-R-ULD6S38waw@r1chard> |
On 2026/08/18 16:11, Ard Biesheuvel wrote: >Ravi reports that statfs() may be called by unprivileged users on the >efivarfs mount point, which may result in a flood of calls to the >QueryVariableInfo() runtime service. These calls are disproportionately >costly on x86 systems where the variable store is backed by SMM, as each >SMM entry requires a rendez-vous of all the CPUs. > >So rate limit the calls to QueryVariableInfo() at twice per second, and >return the most recently obtained values for calls that are elided. > >Cc: <[email protected]> >Cc: Anisse Astier <[email protected]> >Reported-by: Ravi Bangoria <[email protected]> >Fixes: d86ff3333cb1 ("efivarfs: expose used and total size") >Signed-off-by: Ard Biesheuvel <[email protected]> >--- >This supersedes [0], which had some issues, the main one being that a >cache that requires explicit invalidation may go out of sync due to >direct calls to SetVariable() made by other drivers. > >[0] https://lore.kernel.org/all/[email protected]/ > > fs/efivarfs/super.c | 30 ++++++++++++++++---- > 1 file changed, 24 insertions(+), 6 deletions(-) > >diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c >index 733c19571f1c..8d33f11db2a1 100644 >--- a/fs/efivarfs/super.c >+++ b/fs/efivarfs/super.c >@@ -89,12 +89,30 @@ static int efivarfs_statfs(struct dentry *dentry, struct kstatfs *buf) > /* Some UEFI firmware does not implement QueryVariableInfo() */ > storage_space = remaining_space = 0; > if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) { >- status = efivar_query_variable_info(attr, &storage_space, >- &remaining_space, >- &max_variable_size); >- if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) >- pr_warn_ratelimited("query_variable_info() failed: 0x%lx\n", >- status); >+ static DEFINE_RATELIMIT_STATE(_rs, 2 * HZ, 5); >+ static u64 storage, remaining; >+ static DEFINE_SPINLOCK(lock); >+ >+ if (!__ratelimit(&_rs)) { >+ ratelimit_set_flags(&_rs, RATELIMIT_MSG_ON_RELEASE); >+ >+ spin_lock(&lock); >+ storage_space = storage; >+ remaining_space = remaining; >+ spin_unlock(&lock); >+ } else { >+ status = efivar_query_variable_info(attr, &storage_space, >+ &remaining_space, >+ &max_variable_size); >+ if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) >+ pr_warn("query_variable_info() failed: 0x%lx\n", >+ status); >+ >+ spin_lock(&lock); >+ storage = storage_space; >+ remaining = remaining_space; >+ spin_unlock(&lock); >+ } > } > > /* >-- >2.55.0.699.gb54405d56f-goog > > Reviewed-by: Richard Lyu <[email protected]>