qed: Fix potential use-after-free in qed_spq_post()
authorRoland Dreier <roland@purestorage.com>
Mon, 15 Jan 2018 20:24:49 +0000 (12:24 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 16 Jan 2018 19:57:34 +0000 (14:57 -0500)
We need to check if p_ent->comp_mode is QED_SPQ_MODE_EBLOCK before
calling qed_spq_add_entry().  The test is fine is the mode is EBLOCK,
but if it isn't then qed_spq_add_entry() might kfree(p_ent).

Signed-off-by: Roland Dreier <roland@purestorage.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/qlogic/qed/qed_spq.c

index be48d9abd0010ed88cb6c6161cbf4e7b81429710..3588081b2e274f2308eb795ca06632b9a5a442e8 100644 (file)
@@ -776,6 +776,7 @@ int qed_spq_post(struct qed_hwfn *p_hwfn,
        int rc = 0;
        struct qed_spq *p_spq = p_hwfn ? p_hwfn->p_spq : NULL;
        bool b_ret_ent = true;
+       bool eblock;
 
        if (!p_hwfn)
                return -EINVAL;
@@ -794,6 +795,11 @@ int qed_spq_post(struct qed_hwfn *p_hwfn,
        if (rc)
                goto spq_post_fail;
 
+       /* Check if entry is in block mode before qed_spq_add_entry,
+        * which might kfree p_ent.
+        */
+       eblock = (p_ent->comp_mode == QED_SPQ_MODE_EBLOCK);
+
        /* Add the request to the pending queue */
        rc = qed_spq_add_entry(p_hwfn, p_ent, p_ent->priority);
        if (rc)
@@ -811,7 +817,7 @@ int qed_spq_post(struct qed_hwfn *p_hwfn,
 
        spin_unlock_bh(&p_spq->lock);
 
-       if (p_ent->comp_mode == QED_SPQ_MODE_EBLOCK) {
+       if (eblock) {
                /* For entries in QED BLOCK mode, the completion code cannot
                 * perform the necessary cleanup - if it did, we couldn't
                 * access p_ent here to see whether it's successful or not.