mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 16:54:20 +08:00
habanalabs: fix race when waiting on encaps signal
Scenario: 1. CS which is part of encaps signal has been completed and now executing kref_put to its encaps signal handle. The refcount of the handle decremented to 0, and called the encaps signal handle release function - hl_encaps_handle_do_release. 2. At this point the user starts waiting on the signal, and finds the encaps signal handle in the handlers list and increment the habdle refcount to 1. 3. Immediately after, hl_encaps_handle_do_release removed the handle from the list and free its memory. 4. Wait function using the handle although it has been freed. This scenario caused the slab area which was previously allocated for the handle to be poison overwritten which triggered kernel bug the next time the OS needed to allocate this slab. Fixed by getting the refcount of the handle only in case it is not zero. Signed-off-by: Dani Liberman <dliberman@habana.ai> Reviewed-by: Oded Gabbay <ogabbay@kernel.org> Signed-off-by: Oded Gabbay <ogabbay@kernel.org>
This commit is contained in:
parent
a8076c47f6
commit
b32cd10480
@ -2063,13 +2063,16 @@ static int cs_ioctl_signal_wait(struct hl_fpriv *hpriv, enum hl_cs_type cs_type,
|
||||
idp = &ctx->sig_mgr.handles;
|
||||
idr_for_each_entry(idp, encaps_sig_hdl, id) {
|
||||
if (encaps_sig_hdl->cs_seq == signal_seq) {
|
||||
handle_found = true;
|
||||
/* get refcount to protect removing
|
||||
* this handle from idr, needed when
|
||||
* multiple wait cs are used with offset
|
||||
/* get refcount to protect removing this handle from idr,
|
||||
* needed when multiple wait cs are used with offset
|
||||
* to wait on reserved encaps signals.
|
||||
* Since kref_put of this handle is executed outside the
|
||||
* current lock, it is possible that the handle refcount
|
||||
* is 0 but it yet to be removed from the list. In this
|
||||
* case need to consider the handle as not valid.
|
||||
*/
|
||||
kref_get(&encaps_sig_hdl->refcount);
|
||||
if (kref_get_unless_zero(&encaps_sig_hdl->refcount))
|
||||
handle_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user