iser-target: Fix NULL dereference in SW mode DIF
authorSagi Grimberg <sagig@mellanox.com>
Tue, 2 Dec 2014 14:57:34 +0000 (16:57 +0200)
committerNicholas Bellinger <nab@linux-iscsi.org>
Sat, 13 Dec 2014 07:32:26 +0000 (23:32 -0800)
Fallback to software mode DIF if HCA does not support
PI (without crashing obviously). It is still possible to
run with backend protection and an unprotected frontend,
so looking at the command prot_op is not enough. Check
device PI capability on a per-IO basis (isert_prot_cmd
inline static) to determine if we need to handle protection
information.

Trace:
BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
IP: [<ffffffffa037f8b1>] isert_reg_sig_mr+0x351/0x3b0 [ib_isert]
Call Trace:
 [<ffffffff812b003a>] ? swiotlb_map_sg_attrs+0x7a/0x130
 [<ffffffffa038184d>] isert_reg_rdma+0x2fd/0x370 [ib_isert]
 [<ffffffff8108f2ec>] ? idle_balance+0x6c/0x2c0
 [<ffffffffa0382b68>] isert_put_datain+0x68/0x210 [ib_isert]
 [<ffffffffa02acf5b>] lio_queue_data_in+0x2b/0x30 [iscsi_target_mod]
 [<ffffffffa02306eb>] target_complete_ok_work+0x21b/0x310 [target_core_mod]
 [<ffffffff8106ece2>] process_one_work+0x182/0x3b0
 [<ffffffff8106fda0>] worker_thread+0x120/0x3c0
 [<ffffffff8106fc80>] ? maybe_create_worker+0x190/0x190
 [<ffffffff8107594e>] kthread+0xce/0xf0
 [<ffffffff81075880>] ? kthread_freezable_should_stop+0x70/0x70
 [<ffffffff8159a22c>] ret_from_fork+0x7c/0xb0
 [<ffffffff81075880>] ? kthread_freezable_should_stop+0x70/0x70

Reported-by: Slava Shwartsman <valyushash@gmail.com>
Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Cc: <stable@vger.kernel.org> # v3.14+
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
drivers/infiniband/ulp/isert/ib_isert.c

index b0e58f196d9098d4899fab986e26ad1cf975bd46..618c81576b056a96d4cf474f909429a90187ee76 100644 (file)
@@ -61,6 +61,14 @@ static int
 isert_rdma_accept(struct isert_conn *isert_conn);
 struct rdma_cm_id *isert_setup_id(struct isert_np *isert_np);
 
+static inline bool
+isert_prot_cmd(struct isert_conn *conn, struct se_cmd *cmd)
+{
+       return (conn->conn_device->pi_capable &&
+               cmd->prot_op != TARGET_PROT_NORMAL);
+}
+
+
 static void
 isert_qp_event_callback(struct ib_event *e, void *context)
 {
@@ -2919,8 +2927,7 @@ isert_reg_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        if (ret)
                return ret;
 
-       if (wr->data.dma_nents != 1 ||
-           se_cmd->prot_op != TARGET_PROT_NORMAL) {
+       if (wr->data.dma_nents != 1 || isert_prot_cmd(isert_conn, se_cmd)) {
                spin_lock_irqsave(&isert_conn->conn_lock, flags);
                fr_desc = list_first_entry(&isert_conn->conn_fr_pool,
                                           struct fast_reg_descriptor, list);
@@ -2934,7 +2941,7 @@ isert_reg_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        if (ret)
                goto unmap_cmd;
 
-       if (se_cmd->prot_op != TARGET_PROT_NORMAL) {
+       if (isert_prot_cmd(isert_conn, se_cmd)) {
                ret = isert_handle_prot_cmd(isert_conn, isert_cmd, wr);
                if (ret)
                        goto unmap_cmd;
@@ -2959,7 +2966,7 @@ isert_reg_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                send_wr->opcode = IB_WR_RDMA_WRITE;
                send_wr->wr.rdma.remote_addr = isert_cmd->read_va;
                send_wr->wr.rdma.rkey = isert_cmd->read_stag;
-               send_wr->send_flags = se_cmd->prot_op == TARGET_PROT_NORMAL ?
+               send_wr->send_flags = !isert_prot_cmd(isert_conn, se_cmd) ?
                                      0 : IB_SEND_SIGNALED;
        } else {
                send_wr->opcode = IB_WR_RDMA_READ;
@@ -3001,7 +3008,7 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
                return rc;
        }
 
-       if (se_cmd->prot_op == TARGET_PROT_NORMAL) {
+       if (!isert_prot_cmd(isert_conn, se_cmd)) {
                /*
                 * Build isert_conn->tx_desc for iSCSI response PDU and attach
                 */
@@ -3024,7 +3031,7 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
                atomic_sub(wr->send_wr_num, &isert_conn->post_send_buf_count);
        }
 
-       if (se_cmd->prot_op == TARGET_PROT_NORMAL)
+       if (!isert_prot_cmd(isert_conn, se_cmd))
                pr_debug("Cmd: %p posted RDMA_WRITE + Response for iSER Data "
                         "READ\n", isert_cmd);
        else