]> git.baikalelectronics.ru Git - kernel.git/commitdiff
iavf: fix potential deadlock on allocation failure
authorJacob Keller <jacob.e.keller@intel.com>
Mon, 10 Jul 2023 20:41:27 +0000 (13:41 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Aug 2023 08:23:58 +0000 (10:23 +0200)
[ Upstream commit a2f054c10bef0b54600ec9cb776508443e941343 ]

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: fc2e6b3b132a ("iavf: Rework mutexes for better synchronisation")
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/intel/iavf/iavf_main.c

index c1f91c55e1ca741a6b5f705469f6db215a4a5764..650a969a69a14899cdd68967443ba2e49e757e9a 100644 (file)
@@ -3300,7 +3300,7 @@ static void iavf_adminq_task(struct work_struct *work)
        event.buf_len = IAVF_MAX_AQ_BUF_SIZE;
        event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);
        if (!event.msg_buf)
-               goto out;
+               goto unlock;
 
        do {
                ret = iavf_clean_arq_element(hw, &event, &pending);
@@ -3315,7 +3315,6 @@ static void iavf_adminq_task(struct work_struct *work)
                if (pending != 0)
                        memset(event.msg_buf, 0, IAVF_MAX_AQ_BUF_SIZE);
        } while (pending);
-       mutex_unlock(&adapter->crit_lock);
 
        if (iavf_is_reset_in_progress(adapter))
                goto freedom;
@@ -3359,6 +3358,8 @@ static void iavf_adminq_task(struct work_struct *work)
 
 freedom:
        kfree(event.msg_buf);
+unlock:
+       mutex_unlock(&adapter->crit_lock);
 out:
        /* re-enable Admin queue interrupt cause */
        iavf_misc_irq_enable(adapter);