mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-07-19 07:39:54 +02:00
crypto: qat - Fix ADF_DEV_RESET_SYNC memory leak
commitd3b17c6d9d
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:7d42e09760
("crypto: qat - resolve race condition during AER recovery") Cc: <stable@vger.kernel.org> #6.8+ Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Reviewed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d14104360c
commit
c2d443aa1a
|
@ -92,8 +92,7 @@ static void adf_device_reset_worker(struct work_struct *work)
|
||||||
if (adf_dev_restart(accel_dev)) {
|
if (adf_dev_restart(accel_dev)) {
|
||||||
/* The device hanged and we can't restart it so stop here */
|
/* The device hanged and we can't restart it so stop here */
|
||||||
dev_err(&GET_DEV(accel_dev), "Restart device failed\n");
|
dev_err(&GET_DEV(accel_dev), "Restart device failed\n");
|
||||||
if (reset_data->mode == ADF_DEV_RESET_ASYNC ||
|
if (reset_data->mode == ADF_DEV_RESET_ASYNC)
|
||||||
completion_done(&reset_data->compl))
|
|
||||||
kfree(reset_data);
|
kfree(reset_data);
|
||||||
WARN(1, "QAT: device restart failed. Device is unusable\n");
|
WARN(1, "QAT: device restart failed. Device is unusable\n");
|
||||||
return;
|
return;
|
||||||
|
@ -101,16 +100,8 @@ static void adf_device_reset_worker(struct work_struct *work)
|
||||||
adf_dev_restarted_notify(accel_dev);
|
adf_dev_restarted_notify(accel_dev);
|
||||||
clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
|
clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
|
||||||
|
|
||||||
/*
|
/* The dev is back alive. Notify the caller if in sync mode */
|
||||||
* The dev is back alive. Notify the caller if in sync mode
|
if (reset_data->mode == ADF_DEV_RESET_ASYNC)
|
||||||
*
|
|
||||||
* If device restart will take a more time than expected,
|
|
||||||
* the schedule_reset() function can timeout and exit. This can be
|
|
||||||
* detected by calling the completion_done() function. In this case
|
|
||||||
* the reset_data structure needs to be freed here.
|
|
||||||
*/
|
|
||||||
if (reset_data->mode == ADF_DEV_RESET_ASYNC ||
|
|
||||||
completion_done(&reset_data->compl))
|
|
||||||
kfree(reset_data);
|
kfree(reset_data);
|
||||||
else
|
else
|
||||||
complete(&reset_data->compl);
|
complete(&reset_data->compl);
|
||||||
|
@ -145,10 +136,10 @@ static int adf_dev_aer_schedule_reset(struct adf_accel_dev *accel_dev,
|
||||||
if (!timeout) {
|
if (!timeout) {
|
||||||
dev_err(&GET_DEV(accel_dev),
|
dev_err(&GET_DEV(accel_dev),
|
||||||
"Reset device timeout expired\n");
|
"Reset device timeout expired\n");
|
||||||
|
cancel_work_sync(&reset_data->reset_work);
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
} else {
|
|
||||||
kfree(reset_data);
|
|
||||||
}
|
}
|
||||||
|
kfree(reset_data);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user