Skip to content

Commit d0fd124

Browse files
herbertxgregkh
authored andcommitted
crypto: qat - Fix ADF_DEV_RESET_SYNC memory leak
commit d3b17c6 upstream. Using completion_done to determine whether the caller has gone away only works after a complete call. Furthermore it's still possible that the caller has not yet called wait_for_completion, resulting in another potential UAF. Fix this by making the caller use cancel_work_sync and then freeing the memory safely. Fixes: 7d42e09 ("crypto: qat - resolve race condition during AER recovery") Cc: <[email protected]> #6.8+ Signed-off-by: Herbert Xu <[email protected]> Reviewed-by: Giovanni Cabiddu <[email protected]> Signed-off-by: Herbert Xu <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 83633e9 commit d0fd124

File tree

1 file changed

+5
-14
lines changed

1 file changed

+5
-14
lines changed

drivers/crypto/intel/qat/qat_common/adf_aer.c

+5-14
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,7 @@ static void adf_device_reset_worker(struct work_struct *work)
130130
if (adf_dev_restart(accel_dev)) {
131131
/* The device hanged and we can't restart it so stop here */
132132
dev_err(&GET_DEV(accel_dev), "Restart device failed\n");
133-
if (reset_data->mode == ADF_DEV_RESET_ASYNC ||
134-
completion_done(&reset_data->compl))
133+
if (reset_data->mode == ADF_DEV_RESET_ASYNC)
135134
kfree(reset_data);
136135
WARN(1, "QAT: device restart failed. Device is unusable\n");
137136
return;
@@ -147,16 +146,8 @@ static void adf_device_reset_worker(struct work_struct *work)
147146
adf_dev_restarted_notify(accel_dev);
148147
clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
149148

150-
/*
151-
* The dev is back alive. Notify the caller if in sync mode
152-
*
153-
* If device restart will take a more time than expected,
154-
* the schedule_reset() function can timeout and exit. This can be
155-
* detected by calling the completion_done() function. In this case
156-
* the reset_data structure needs to be freed here.
157-
*/
158-
if (reset_data->mode == ADF_DEV_RESET_ASYNC ||
159-
completion_done(&reset_data->compl))
149+
/* The dev is back alive. Notify the caller if in sync mode */
150+
if (reset_data->mode == ADF_DEV_RESET_ASYNC)
160151
kfree(reset_data);
161152
else
162153
complete(&reset_data->compl);
@@ -191,10 +182,10 @@ static int adf_dev_aer_schedule_reset(struct adf_accel_dev *accel_dev,
191182
if (!timeout) {
192183
dev_err(&GET_DEV(accel_dev),
193184
"Reset device timeout expired\n");
185+
cancel_work_sync(&reset_data->reset_work);
194186
ret = -EFAULT;
195-
} else {
196-
kfree(reset_data);
197187
}
188+
kfree(reset_data);
198189
return ret;
199190
}
200191
return 0;

0 commit comments

Comments
 (0)