diff options
author | Mark Pearson <mpearson-lenovo@squebb.ca> | 2023-06-01 16:05:45 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-07-19 16:21:36 +0200 |
commit | 61545eb787fe7b6274a239f9a7637e357c8c8011 (patch) | |
tree | 358b1e4ad3776ca5a7e4689ea3fdde19f36bfe97 | |
parent | d1390b057d594f0b8c8ea15780902f462cb2d70a (diff) | |
download | linux-stable-61545eb787fe7b6274a239f9a7637e357c8c8011.tar.gz linux-stable-61545eb787fe7b6274a239f9a7637e357c8c8011.tar.bz2 linux-stable-61545eb787fe7b6274a239f9a7637e357c8c8011.zip |
platform/x86: think-lmi: mutex protection around multiple WMI calls
[ Upstream commit c41e0121a1221894a1a9c4666156db9e1def4d6c ]
When an attribute is being changed if the Admin account is enabled, or if
a password is being updated then multiple WMI calls are needed.
Add mutex protection to ensure no race conditions are introduced.
Fixes: b49f72e7f96d ("platform/x86: think-lmi: Certificate authentication support")
Signed-off-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20230601200552.4396-1-mpearson-lenovo@squebb.ca
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r-- | drivers/platform/x86/think-lmi.c | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c index 336b9029d151..4e6040c0a220 100644 --- a/drivers/platform/x86/think-lmi.c +++ b/drivers/platform/x86/think-lmi.c @@ -14,6 +14,7 @@ #include <linux/acpi.h> #include <linux/errno.h> #include <linux/fs.h> +#include <linux/mutex.h> #include <linux/string.h> #include <linux/types.h> #include <linux/dmi.h> @@ -195,6 +196,7 @@ static const char * const level_options[] = { }; static struct think_lmi tlmi_priv; static struct class *fw_attr_class; +static DEFINE_MUTEX(tlmi_mutex); /* ------ Utility functions ------------*/ /* Strip out CR if one is present */ @@ -437,6 +439,9 @@ static ssize_t new_password_store(struct kobject *kobj, /* Strip out CR if one is present, setting password won't work if it is present */ strip_cr(new_pwd); + /* Use lock in case multiple WMI operations needed */ + mutex_lock(&tlmi_mutex); + pwdlen = strlen(new_pwd); /* pwdlen == 0 is allowed to clear the password */ if (pwdlen && ((pwdlen < setting->minlen) || (pwdlen > setting->maxlen))) { @@ -493,6 +498,7 @@ static ssize_t new_password_store(struct kobject *kobj, kfree(auth_str); } out: + mutex_unlock(&tlmi_mutex); kfree(new_pwd); return ret ?: count; } @@ -982,6 +988,9 @@ static ssize_t current_value_store(struct kobject *kobj, /* Strip out CR if one is present */ strip_cr(new_setting); + /* Use lock in case multiple WMI operations needed */ + mutex_lock(&tlmi_mutex); + /* Check if certificate authentication is enabled and active */ if (tlmi_priv.certificate_support && tlmi_priv.pwd_admin->cert_installed) { if (!tlmi_priv.pwd_admin->signature || !tlmi_priv.pwd_admin->save_signature) { @@ -1040,6 +1049,7 @@ static ssize_t current_value_store(struct kobject *kobj, kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE); } out: + mutex_unlock(&tlmi_mutex); kfree(auth_str); kfree(set_str); kfree(new_setting); |