Skip to content

Commit f88814c

Browse files
committed
efi/efivars: Expose RT service availability via efivars abstraction
Commit bf67fad ("efi: Use more granular check for availability for variable services") introduced a check into the efivarfs, efi-pstore and other drivers that aborts loading of the module if not all three variable runtime services (GetVariable, SetVariable and GetNextVariable) are supported. However, this results in efivarfs being unavailable entirely if only SetVariable support is missing, which is only needed if you want to make any modifications. Also, efi-pstore and the sysfs EFI variable interface could be backed by another implementation of the 'efivars' abstraction, in which case it is completely irrelevant which services are supported by the EFI firmware. So make the generic 'efivars' abstraction dependent on the availibility of the GetVariable and GetNextVariable EFI runtime services, and add a helper 'efivar_supports_writes()' to find out whether the currently active efivars abstraction supports writes (and wire it up to the availability of SetVariable for the generic one). Then, use the efivar_supports_writes() helper to decide whether to permit efivarfs to be mounted read-write, and whether to enable efi-pstore or the sysfs EFI variable interface altogether. Fixes: bf67fad ("efi: Use more granular check for availability for variable services") Reported-by: Heinrich Schuchardt <[email protected]> Acked-by: Ilias Apalodimas <[email protected]> Tested-by: Ilias Apalodimas <[email protected]> Signed-off-by: Ard Biesheuvel <[email protected]>
1 parent 3230d95 commit f88814c

File tree

6 files changed

+20
-15
lines changed

6 files changed

+20
-15
lines changed

drivers/firmware/efi/efi-pstore.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -356,10 +356,7 @@ static struct pstore_info efi_pstore_info = {
356356

357357
static __init int efivars_pstore_init(void)
358358
{
359-
if (!efi_rt_services_supported(EFI_RT_SUPPORTED_VARIABLE_SERVICES))
360-
return 0;
361-
362-
if (!efivars_kobject())
359+
if (!efivars_kobject() || !efivar_supports_writes())
363360
return 0;
364361

365362
if (efivars_pstore_disable)

drivers/firmware/efi/efi.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,13 @@ static struct efivar_operations generic_ops;
176176
static int generic_ops_register(void)
177177
{
178178
generic_ops.get_variable = efi.get_variable;
179-
generic_ops.set_variable = efi.set_variable;
180-
generic_ops.set_variable_nonblocking = efi.set_variable_nonblocking;
181179
generic_ops.get_next_variable = efi.get_next_variable;
182180
generic_ops.query_variable_store = efi_query_variable_store;
183181

182+
if (efi_rt_services_supported(EFI_RT_SUPPORTED_SET_VARIABLE)) {
183+
generic_ops.set_variable = efi.set_variable;
184+
generic_ops.set_variable_nonblocking = efi.set_variable_nonblocking;
185+
}
184186
return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
185187
}
186188

@@ -382,7 +384,8 @@ static int __init efisubsys_init(void)
382384
return -ENOMEM;
383385
}
384386

385-
if (efi_rt_services_supported(EFI_RT_SUPPORTED_VARIABLE_SERVICES)) {
387+
if (efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE |
388+
EFI_RT_SUPPORTED_GET_NEXT_VARIABLE_NAME)) {
386389
efivar_ssdt_load();
387390
error = generic_ops_register();
388391
if (error)
@@ -416,7 +419,8 @@ static int __init efisubsys_init(void)
416419
err_remove_group:
417420
sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
418421
err_unregister:
419-
if (efi_rt_services_supported(EFI_RT_SUPPORTED_VARIABLE_SERVICES))
422+
if (efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE |
423+
EFI_RT_SUPPORTED_GET_NEXT_VARIABLE_NAME))
420424
generic_ops_unregister();
421425
err_put:
422426
kobject_put(efi_kobj);

drivers/firmware/efi/efivars.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -680,11 +680,8 @@ int efivars_sysfs_init(void)
680680
struct kobject *parent_kobj = efivars_kobject();
681681
int error = 0;
682682

683-
if (!efi_rt_services_supported(EFI_RT_SUPPORTED_VARIABLE_SERVICES))
684-
return -ENODEV;
685-
686683
/* No efivars has been registered yet */
687-
if (!parent_kobj)
684+
if (!parent_kobj || !efivar_supports_writes())
688685
return 0;
689686

690687
printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,

drivers/firmware/efi/vars.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,3 +1229,9 @@ int efivars_unregister(struct efivars *efivars)
12291229
return rv;
12301230
}
12311231
EXPORT_SYMBOL_GPL(efivars_unregister);
1232+
1233+
int efivar_supports_writes(void)
1234+
{
1235+
return __efivars && __efivars->ops->set_variable;
1236+
}
1237+
EXPORT_SYMBOL_GPL(efivar_supports_writes);

fs/efivarfs/super.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ static int efivarfs_fill_super(struct super_block *sb, struct fs_context *fc)
201201
sb->s_d_op = &efivarfs_d_ops;
202202
sb->s_time_gran = 1;
203203

204+
if (!efivar_supports_writes())
205+
sb->s_flags |= SB_RDONLY;
206+
204207
inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0, true);
205208
if (!inode)
206209
return -ENOMEM;
@@ -252,9 +255,6 @@ static struct file_system_type efivarfs_type = {
252255

253256
static __init int efivarfs_init(void)
254257
{
255-
if (!efi_rt_services_supported(EFI_RT_SUPPORTED_VARIABLE_SERVICES))
256-
return -ENODEV;
257-
258258
if (!efivars_kobject())
259259
return -ENODEV;
260260

include/linux/efi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,7 @@ int efivars_register(struct efivars *efivars,
994994
int efivars_unregister(struct efivars *efivars);
995995
struct kobject *efivars_kobject(void);
996996

997+
int efivar_supports_writes(void);
997998
int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *),
998999
void *data, bool duplicates, struct list_head *head);
9991000

0 commit comments

Comments
 (0)