Skip to content

Commit 2af5610

Browse files
herbertxroxanan1996
authored andcommitted
crypto: qat - Fix ADF_DEV_RESET_SYNC memory leak
BugLink: https://bugs.launchpad.net/bugs/2072617 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: <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> Signed-off-by: Portia Stephens <portia.stephens@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
1 parent ffe149f commit 2af5610

File tree

1 file changed

+5
-14
lines changed

1 file changed

+5
-14
lines changed

drivers/crypto/qat/qat_common/adf_aer.c

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -95,25 +95,16 @@ static void adf_device_reset_worker(struct work_struct *work)
9595
if (adf_dev_init(accel_dev) || adf_dev_start(accel_dev)) {
9696
/* The device hanged and we can't restart it so stop here */
9797
dev_err(&GET_DEV(accel_dev), "Restart device failed\n");
98-
if (reset_data->mode == ADF_DEV_RESET_ASYNC ||
99-
completion_done(&reset_data->compl))
98+
if (reset_data->mode == ADF_DEV_RESET_ASYNC)
10099
kfree(reset_data);
101100
WARN(1, "QAT: device restart failed. Device is unusable\n");
102101
return;
103102
}
104103
adf_dev_restarted_notify(accel_dev);
105104
clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
106105

107-
/*
108-
* The dev is back alive. Notify the caller if in sync mode
109-
*
110-
* If device restart will take a more time than expected,
111-
* the schedule_reset() function can timeout and exit. This can be
112-
* detected by calling the completion_done() function. In this case
113-
* the reset_data structure needs to be freed here.
114-
*/
115-
if (reset_data->mode == ADF_DEV_RESET_ASYNC ||
116-
completion_done(&reset_data->compl))
106+
/* The dev is back alive. Notify the caller if in sync mode */
107+
if (reset_data->mode == ADF_DEV_RESET_ASYNC)
117108
kfree(reset_data);
118109
else
119110
complete(&reset_data->compl);
@@ -148,10 +139,10 @@ static int adf_dev_aer_schedule_reset(struct adf_accel_dev *accel_dev,
148139
if (!timeout) {
149140
dev_err(&GET_DEV(accel_dev),
150141
"Reset device timeout expired\n");
142+
cancel_work_sync(&reset_data->reset_work);
151143
ret = -EFAULT;
152-
} else {
153-
kfree(reset_data);
154144
}
145+
kfree(reset_data);
155146
return ret;
156147
}
157148
return 0;

0 commit comments

Comments
 (0)