From 0ae66a082ea716de4382a06c48a98243f830206e Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Sat, 3 Jun 2017 04:02:22 +0000 Subject: [PATCH] Fix dereference beyond last sg element Reported-By: David Butterfield git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@7204 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t/qla2x00-target/qla2x00t.c | 9 ++++++--- scst/include/scst.h | 8 ++++++-- scst/src/scst_lib.c | 8 +++++--- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/qla2x00t/qla2x00-target/qla2x00t.c b/qla2x00t/qla2x00-target/qla2x00t.c index f91ca9d83..2903ded28 100644 --- a/qla2x00t/qla2x00-target/qla2x00t.c +++ b/qla2x00t/qla2x00-target/qla2x00t.c @@ -2634,7 +2634,8 @@ static void q2t_load_cont_data_segments(struct q2t_prm *prm) (unsigned long long int)pci_dma_lo32(dma_addr), (int)sg_dma_len(prm->sg)); - prm->sg = __sg_next_inline(prm->sg); + /* prm->sg might be last here */ + prm->sg = sg_next_inline(prm->sg); } TRACE_BUFFER("Continuation packet data", @@ -2695,7 +2696,8 @@ static void q2x_load_data_segments(struct q2t_prm *prm) (unsigned long long int)pci_dma_lo32(dma_addr), (int)sg_dma_len(prm->sg)); - prm->sg = __sg_next_inline(prm->sg); + /* prm->sg might be last here */ + prm->sg = sg_next_inline(prm->sg); } TRACE_BUFFER("Scatter/gather, CTIO packet data", pkt, @@ -2756,7 +2758,8 @@ static void q24_load_data_segments(struct q2t_prm *prm) (unsigned long long int)pci_dma_lo32(dma_addr), (int)sg_dma_len(prm->sg)); - prm->sg = __sg_next_inline(prm->sg); + /* prm->sg might be last here */ + prm->sg = sg_next_inline(prm->sg); } q2t_load_cont_data_segments(prm); diff --git a/scst/include/scst.h b/scst/include/scst.h index 3b684be55..5fd6c3733 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -4946,6 +4946,10 @@ void scst_aen_done(struct scst_aen *aen); static inline struct scatterlist *__sg_next_inline(struct scatterlist *sg) { +#ifdef CONFIG_SCST_EXTRACHECKS + BUG_ON(sg_is_last(sg)); +#endif + sg++; if (unlikely(sg_is_chain(sg))) sg = sg_chain_ptr(sg); @@ -5006,7 +5010,7 @@ static inline int __scst_get_buf(struct scst_cmd *cmd, int sg_cnt, res = sg->length; cmd->get_sg_buf_entry_num++; - cmd->get_sg_buf_cur_sg_entry = __sg_next_inline(sg); + cmd->get_sg_buf_cur_sg_entry = sg_next_inline(sg); out: return res; @@ -5147,7 +5151,7 @@ static inline int __scst_get_sg_page(struct scst_cmd *cmd, int sg_cnt, res = sg->length; cmd->get_sg_buf_entry_num++; - cmd->get_sg_buf_cur_sg_entry = __sg_next_inline(sg); + cmd->get_sg_buf_cur_sg_entry = sg_next_inline(sg); out: return res; diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 08c09684d..dfedd150c 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -7506,7 +7506,8 @@ static void scst_restore_dif_sg(struct scst_cmd *cmd) left -= sg->length; TRACE_DBG("DIF sg %p, restored len %d (left %d)", sg, sg->length, left); - sg = __sg_next_inline(sg); + /* sg might be last here */ + sg = sg_next_inline(sg); } while (left > 0); out: @@ -7569,8 +7570,9 @@ int scst_alloc_space(struct scst_cmd *cmd) left -= sgt->length; sgt->length = (sgd->length >> block_shift) << SCST_DIF_TAG_SHIFT; TRACE_SG("sgt %p, new len %d", sgt, sgt->length); - sgd = __sg_next_inline(sgd); - sgt = __sg_next_inline(sgt); + /* sgd/sgt might be last here */ + sgd = sg_next_inline(sgd); + sgt = sg_next_inline(sgt); } while (left > 0); cmd->dif_sg_normalized = 1;