Thanks Hans, On Tue, May 23, 2023, at 6:46 AM, Hans de Goede wrote: > Hi Mark, > > On 5/17/23 20:19, Mark Pearson wrote: >> Whilst reviewing some documentation from the FW team on using WMI on >> Lenovo system I noticed that we weren't using Opcode support when >> changing BIOS settings in the thinkLMI driver. >> >> We should be doing this to ensure we're future proof as the old >> non-opcode mechanism has been deprecated. >> >> Tested on X1 Carbon G10 and G11. >> >> Signed-off-by: Mark Pearson <mpearson-lenovo@xxxxxxxxx> >> --- >> drivers/platform/x86/think-lmi.c | 23 ++++++++++++++++++++++- >> 1 file changed, 22 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c >> index 1138f770149d..d9341305eba9 100644 >> --- a/drivers/platform/x86/think-lmi.c >> +++ b/drivers/platform/x86/think-lmi.c >> @@ -1001,7 +1001,28 @@ static ssize_t current_value_store(struct kobject *kobj, >> tlmi_priv.pwd_admin->save_signature); >> if (ret) >> goto out; > >> - } else { /* Non certiifcate based authentication */ >> + } else if (tlmi_priv.opcode_support) { >> + /* If opcode support is present use that interface */ >> + set_str = kasprintf(GFP_KERNEL, "%s,%s;", setting->display_name, >> + new_setting); >> + if (!set_str) { >> + ret = -ENOMEM; >> + goto out; >> + } >> + >> + ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTINGS_GUID, set_str); >> + if (ret) >> + goto out; >> + >> + if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { >> + ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin", >> + tlmi_priv.pwd_admin->password); >> + if (ret) >> + goto out; >> + } >> + >> + ret = tlmi_save_bios_settings(""); > > I'm a bit confused about how this works. You are calling the same > LENOVO_SET_BIOS_SETTINGS_GUID as the old non opcode based authentication method > without any auth string. > > And then afterwards you are calling LENOVO_OPCODE_IF_GUID with > "WmiOpcodePasswordAdmin:<passwd>" > > Won't the initial LENOVO_SET_BIOS_SETTINGS_GUID get rejected since > it does not include an auth-string and you have not authenticated > yet using the opcode mechanism either. IOW shouldn't the opcode > auth call go first ? > > And how does this work timing wise, vs races with userspace doing > multiple sysfs writes at once. > > If the authentication done afterwards really acks the last > LENOVO_SET_BIOS_SETTINGS_GUID call then a userspace based > attacker could try to race and overwrite the last > LENOVO_SET_BIOS_SETTINGS_GUID call before the ack happens... ? > > If this code really is correct I think we need to introduce > a mutex to avoid this race. > > And this also needs some comments to explain what is going on. Agreed - and looking at it now....I'm questioning it myself. This was tested so it works...but I wonder if that was more luck than judgement. Let me do some checking - I think I may have messed up here. Mark