Commit a2f054c1 authored by Jacob Keller's avatar Jacob Keller Committed by Tony Nguyen

iavf: fix potential deadlock on allocation failure

In iavf_adminq_task(), if kzalloc() fails to allocate the event.msg_buf,
the function will exit without releasing the adapter->crit_lock.

This is unlikely, but if it happens, the next access to that mutex will
deadlock.

Fix this by moving the unlock to the end of the function, and adding a new
label to allow jumping to the unlock portion of the function exit flow.

Fixes: fc2e6b3b ("iavf: Rework mutexes for better synchronisation")
Signed-off-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Tested-by: default avatarRafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 043b1f18
...@@ -3264,7 +3264,7 @@ static void iavf_adminq_task(struct work_struct *work) ...@@ -3264,7 +3264,7 @@ static void iavf_adminq_task(struct work_struct *work)
event.buf_len = IAVF_MAX_AQ_BUF_SIZE; event.buf_len = IAVF_MAX_AQ_BUF_SIZE;
event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL); event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);
if (!event.msg_buf) if (!event.msg_buf)
goto out; goto unlock;
do { do {
ret = iavf_clean_arq_element(hw, &event, &pending); ret = iavf_clean_arq_element(hw, &event, &pending);
...@@ -3279,7 +3279,6 @@ static void iavf_adminq_task(struct work_struct *work) ...@@ -3279,7 +3279,6 @@ static void iavf_adminq_task(struct work_struct *work)
if (pending != 0) if (pending != 0)
memset(event.msg_buf, 0, IAVF_MAX_AQ_BUF_SIZE); memset(event.msg_buf, 0, IAVF_MAX_AQ_BUF_SIZE);
} while (pending); } while (pending);
mutex_unlock(&adapter->crit_lock);
if (iavf_is_reset_in_progress(adapter)) if (iavf_is_reset_in_progress(adapter))
goto freedom; goto freedom;
...@@ -3323,6 +3322,8 @@ static void iavf_adminq_task(struct work_struct *work) ...@@ -3323,6 +3322,8 @@ static void iavf_adminq_task(struct work_struct *work)
freedom: freedom:
kfree(event.msg_buf); kfree(event.msg_buf);
unlock:
mutex_unlock(&adapter->crit_lock);
out: out:
/* re-enable Admin queue interrupt cause */ /* re-enable Admin queue interrupt cause */
iavf_misc_irq_enable(adapter); iavf_misc_irq_enable(adapter);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment