From: Alexander Usyskin alexander.usyskin@intel.com
[ Upstream commit bb29fc32ae56393269d8fe775159fd59e45682d1 ]
Connect ioctl has the same memory for in and out parameters. Copy in parameter (client uuid) to the local stack to avoid it be overwritten by out parameters fill.
Signed-off-by: Alexander Usyskin alexander.usyskin@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Link: https://lore.kernel.org/r/20250918130435.3327400-3-alexander.usyskin@intel.c... Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
YES - `struct mei_connect_client_data` and `_vtag` overlay input and output fields in a union (`include/uapi/linux/mei.h:44`, `include/uapi/linux/mei.h:90`), so once the driver fills `out_client_properties` the original UUID bytes are lost. - `mei_ioctl_connect_client()` reuses the saved UUID pointer in its retry loop at `drivers/misc/mei/main.c:426` while the same call path overwrites the union with output data at `drivers/misc/mei/main.c:452`, so during the second iteration `mei_me_cl_by_uuid()` sees garbage and the ioctl fails with `-ENOTTY`. - The patch copies the UUID into a stack variable (`drivers/misc/mei/main.c:672`, `drivers/misc/mei/main.c:700`) and passes a pointer to that stable copy (`drivers/misc/mei/main.c:708`, `drivers/misc/mei/main.c:750`), ensuring the retry logic added for D3cold link-reset recovery actually succeeds. - Without this fix, user space cannot reconnect to the firmware client after a link reset triggered by powering a discrete card back up, so the bug is user-visible and regresses the very scenario the previous retry change was meant to solve. - Risk is minimal: it is a self-contained stack copy with no API changes. When backporting, pair it with the `mei: retry connect if interrupted by link reset` commit so the recovery flow on stable kernels works end-to-end.
drivers/misc/mei/main.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 8a149a15b8610..77e7b641b8e97 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -641,7 +641,7 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data) struct mei_cl *cl = file->private_data; struct mei_connect_client_data conn; struct mei_connect_client_data_vtag conn_vtag; - const uuid_le *cl_uuid; + uuid_le cl_uuid; struct mei_client *props; u8 vtag; u32 notify_get, notify_req; @@ -669,18 +669,18 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data) rets = -EFAULT; goto out; } - cl_uuid = &conn.in_client_uuid; + cl_uuid = conn.in_client_uuid; props = &conn.out_client_properties; vtag = 0;
- rets = mei_vt_support_check(dev, cl_uuid); + rets = mei_vt_support_check(dev, &cl_uuid); if (rets == -ENOTTY) goto out; if (!rets) - rets = mei_ioctl_connect_vtag(file, cl_uuid, props, + rets = mei_ioctl_connect_vtag(file, &cl_uuid, props, vtag); else - rets = mei_ioctl_connect_client(file, cl_uuid, props); + rets = mei_ioctl_connect_client(file, &cl_uuid, props); if (rets) goto out;
@@ -702,14 +702,14 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data) goto out; }
- cl_uuid = &conn_vtag.connect.in_client_uuid; + cl_uuid = conn_vtag.connect.in_client_uuid; props = &conn_vtag.out_client_properties; vtag = conn_vtag.connect.vtag;
- rets = mei_vt_support_check(dev, cl_uuid); + rets = mei_vt_support_check(dev, &cl_uuid); if (rets == -EOPNOTSUPP) cl_dbg(dev, cl, "FW Client %pUl does not support vtags\n", - cl_uuid); + &cl_uuid); if (rets) goto out;
@@ -719,7 +719,7 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data) goto out; }
- rets = mei_ioctl_connect_vtag(file, cl_uuid, props, vtag); + rets = mei_ioctl_connect_vtag(file, &cl_uuid, props, vtag); if (rets) goto out;