[PATCH 2/2] nvme-hwmon: notify hwmon alarms on the SMART / Health Status AEN
sashiko-bot at kernel.org
sashiko-bot at kernel.org
Mon Nov 9 04:19:32 PST 2026
Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [High] nvme: nvme_enable_aen() masks NVME_AEN_CFG_SMART with
ctrl->oaes
- [High] nvme: nvme_complete_async_event() requeues AER without clearing
SMART log
- [Medium] nvme-hwmon: nvme_hwmon_smart_notify() bypasses
hwmon_notify_event()
It also noticed 1 related pre-existing issue this patch does not
introduce:
- [Critical] nvme: use-after-free in nvme_handle_aen_notice() [1]
--
commit 33552d2b2131791945c267787b8393f1a3c9f467
Author: Guixin Liu <kanie at linux.alibaba.com>
nvme-hwmon: notify hwmon alarms on the SMART / Health Status AEN
This commit subscribes to the NVMe SMART / Health Status asynchronous
event and schedules a work item on completion to notify sysfs pollers on
temp1_alarm.
> diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
> index a7a4d09644c13..ef488d3ac081f 100644
> --- a/drivers/nvme/host/core.c
> +++ b/drivers/nvme/host/core.c
> @@ -1784,7 +1784,7 @@ int nvme_set_queue_count(struct nvme_ctrl *ctrl, int *count)
> EXPORT_SYMBOL_GPL(nvme_set_queue_count);
>
> #define NVME_AEN_SUPPORTED \
> - (NVME_AEN_CFG_NS_ATTR | NVME_AEN_CFG_FW_ACT | \
> + (NVME_AEN_CFG_SMART | NVME_AEN_CFG_NS_ATTR | NVME_AEN_CFG_FW_ACT | \
> NVME_AEN_CFG_ANA_CHANGE | NVME_AEN_CFG_DISC_CHANGE)
>
> static void nvme_enable_aen(struct nvme_ctrl *ctrl)
[Severity: High]
Does adding NVME_AEN_CFG_SMART to NVME_AEN_SUPPORTED actually enable SMART
asynchronous events in nvme_enable_aen()?
nvme_enable_aen() masks NVME_AEN_SUPPORTED against ctrl->oaes:
drivers/nvme/host/core.c:nvme_enable_aen() {
u32 result, supported_aens = ctrl->oaes & NVME_AEN_SUPPORTED;
int status;
if (!supported_aens)
return;
...
}
ctrl->oaes comes from the Identify Controller OAES field, where bits 7:0
are reserved and zero on compliant controllers (see NVMET_AEN_CFG_OPTIONAL
vs NVMET_AEN_CFG_ALL in drivers/nvme/target/nvmet.h). In Set Features for
NVME_FEAT_ASYNC_EVENT, bits 7:0 are the mandatory SMART warning bitmask
(NVME_SMART_CRIT_SPARE, NVME_SMART_CRIT_TEMPERATURE, etc.), so masking
with ctrl->oaes clears NVME_AEN_CFG_SMART and never enables the event.
> @@ -4993,8 +4993,12 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
> nvme_handle_aer_persistent_error(ctrl);
> return;
> }
> - fallthrough;
> + ctrl->aen_result = result;
> + break;
> case NVME_AER_SMART:
> + nvme_hwmon_smart_event(ctrl);
> + ctrl->aen_result = result;
> + break;
> case NVME_AER_CSS:
> case NVME_AER_VS:
> ctrl->aen_result = result;
[Severity: High]
Does completing NVME_AER_SMART with requeue = true re-arm the Asynchronous
Event Request before the SMART / Health Information log page is read?
Per the NVMe specification, an asynchronous event remains latched on the
controller until host software reads the corresponding log page
(NVME_LOG_SMART) with RAE cleared. Other AEN handlers such as
nvme_fw_act_work() read their log page before queueing
ctrl->async_event_work, whereas here ctrl->async_event_work resubmits the
AER immediately while nvme_hwmon_smart_notify() only calls sysfs_notify().
Before userspace wakes up and reads temp1_alarm (or if nothing polls
temp1_alarm, or CONFIG_NVME_HWMON is disabled), the new AER completes
immediately with the same uncleared event in a tight loop.
[Severity: Critical]
This problem wasn't introduced by this patch, but can a late
NVME_AER_NOTICE_ANA completion in nvme_complete_async_event() cause a
use-after-free [1] on ctrl during controller teardown?
CPU0 CPU1
nvme_remove_ctrl()
...
nvme_stop_ctrl()
nvme_mpath_stop()
cancel_work_sync(&ctrl->ana_work)
nvme_complete_async_event()
nvme_handle_aen_notice()
queue_work(nvme_wq, &ctrl->ana_work)
nvme_uninit_ctrl()
nvme_put_ctrl() -> kfree(ctrl)
nvme_ana_work()
/* dereferences freed ctrl */
<-- use-after-free
nvme_handle_aen_notice() checks ctrl->ana_log_buf but does not verify that
the controller is still live before queueing ctrl->ana_work, allowing the
work item to run after the controller has been freed.
> diff --git a/drivers/nvme/host/hwmon.c b/drivers/nvme/host/hwmon.c
> index 406203d8b9adb..564d5cae8001b 100644
> --- a/drivers/nvme/host/hwmon.c
> +++ b/drivers/nvme/host/hwmon.c
[ ... ]
> @@ -223,6 +225,32 @@ static const struct hwmon_chip_info nvme_hwmon_chip_info = {
> .info = nvme_hwmon_info,
> };
>
> +/*
> + * Called from the admin completion path on a SMART / Health Status AEN.
> + * The completion context can be a hardirq, so only queue the work here;
> + * the notify itself is done in process context. No log refresh is
> + * needed: userspace re-reads temp1_alarm, which fetches the SMART log
> + * on demand.
> + */
> +void nvme_hwmon_smart_event(struct nvme_ctrl *ctrl)
> +{
> + struct nvme_hwmon_data *data;
> +
> + if (!ctrl->hwmon_device)
> + return;
> +
> + data = dev_get_drvdata(ctrl->hwmon_device);
> + queue_work(nvme_wq, &data->smart_work);
> +}
> +
> +static void nvme_hwmon_smart_notify(struct work_struct *work)
> +{
> + struct nvme_hwmon_data *data =
> + container_of(work, struct nvme_hwmon_data, smart_work);
> +
> + sysfs_notify(&data->ctrl->hwmon_device->kobj, NULL, "temp1_alarm");
> +}
[Severity: Medium]
Should nvme_hwmon_smart_notify() call hwmon_notify_event() instead of
calling sysfs_notify() directly?
hwmon_notify_event(data->ctrl->hwmon_device, hwmon_temp, hwmon_temp_alarm,
0) notifies the sysfs attribute, emits the standard hwmon KOBJ_CHANGE
uevent, and calls hwmon_thermal_notify() to update the thermal zone
registered via HWMON_C_REGISTER_TZ. Also, the commit message notes that
polling temp1_alarm reports spare-block conditions, but nvme_hwmon_read()
only checks NVME_SMART_CRIT_TEMPERATURE for temp1_alarm and never checks
NVME_SMART_CRIT_SPARE.
[1] https://sashiko.dev/#/bug/linux-216101c0-b2a4-4615-97e0-5cfa127dc568
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261109120207.1352165-1-kanie@linux.alibaba.com?part=2
More information about the Linux-nvme
mailing list