diff options
| author | Shih-Yuan Lee <fourdollars@debian.org> | 2026-07-11 17:33:22 +0800 |
|---|---|---|
| committer | Guenter Roeck <linux@roeck-us.net> | 2026-07-27 20:30:44 -0700 |
| commit | e3d0a8c061224e5306bc0c9be5f29b750ba09a1e (patch) | |
| tree | 7964f4d88a67f4fed8d898f9f12b89304fd8658a /drivers/hwmon | |
| parent | e4ef6db5e9acdfcab2162409e21a2b8fbc1e8ff3 (diff) | |
| download | linux-next-e3d0a8c061224e5306bc0c9be5f29b750ba09a1e.tar.gz linux-next-e3d0a8c061224e5306bc0c9be5f29b750ba09a1e.zip | |
hwmon: (applesmc) Fix lockless cache validation data race
In applesmc_get_entry_by_index(), the cache->valid flag is checked
locklessly, but setting it to true lacks memory barriers. This can lead to
a data race (TOCTOU) where another thread sees cache->valid as true
before the actual cache contents (cache->key, cache->len, cache->type, etc.)
are fully committed and visible to that CPU, potentially causing it to read
uninitialized data and send incorrect keys to the Apple SMC hardware.
Introduce memory barriers (smp_load_acquire and smp_store_release) with
explanatory comments to ensure cache synchronization is thread-safe and
fully visible across all CPUs.
Signed-off-by: Shih-Yuan Lee <fourdollars@debian.org>
Link: https://lore.kernel.org/r/20260711093323.14529-3-fourdollars@debian.org
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon')
| -rw-r--r-- | drivers/hwmon/applesmc.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 9b2d9ecb20c0..317135fc4b73 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -33,6 +33,7 @@ #include <linux/workqueue.h> #include <linux/err.h> #include <linux/bits.h> +#include <asm/barrier.h> /* data port used by Apple SMC */ #define APPLESMC_DATA_PORT 0x300 @@ -373,7 +374,8 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(int index) __be32 be; int ret = 0; - if (cache->valid) + /* Pairs with smp_store_release() to ensure cache contents are visible */ + if (smp_load_acquire(&cache->valid)) return cache; mutex_lock(&smcreg.mutex); @@ -392,7 +394,8 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(int index) cache->len = info[0]; memcpy(cache->type, &info[1], 4); cache->flags = info[5]; - cache->valid = true; + /* Pairs with smp_load_acquire() to commit cache contents before setting valid */ + smp_store_release(&cache->valid, true); out: mutex_unlock(&smcreg.mutex); |
