From: Li Nan linan122@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5HL0X CVE: NA
-------------------------------
In struct iscsi_transport, "unbind_conn" was added and the kabi is broken. Fix it by using "tgt_dscvr" and caps flag.
Signed-off-by: Li Nan linan122@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Reviewed-by: linan linan122@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com --- drivers/infiniband/ulp/iser/iscsi_iser.c | 9 +++++-- drivers/scsi/be2iscsi/be_main.c | 9 +++++-- drivers/scsi/bnx2i/bnx2i_iscsi.c | 9 +++++-- drivers/scsi/cxgbi/cxgb3i/cxgb3i.c | 9 +++++-- drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 9 +++++-- drivers/scsi/qedi/qedi_iscsi.c | 8 ++++-- drivers/scsi/qla4xxx/ql4_os.c | 8 ++++-- drivers/scsi/scsi_transport_iscsi.c | 31 ++++++++++++++++++------ include/scsi/iscsi_if.h | 1 + include/scsi/scsi_transport_iscsi.h | 17 ++++++++++++- 10 files changed, 87 insertions(+), 23 deletions(-)
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index a16e066989fa..4884b122e413 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -979,17 +979,22 @@ static struct scsi_host_template iscsi_iser_sht = { .track_queue_depth = 1, };
+static struct iscsi_transport_expand iscsi_iser_expand = { + .unbind_conn = iscsi_conn_unbind, +}; + static struct iscsi_transport iscsi_iser_transport = { .owner = THIS_MODULE, .name = "iser", - .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_TEXT_NEGO, + .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_TEXT_NEGO + | CAP_OPS_EXPAND, /* session management */ .create_session = iscsi_iser_session_create, .destroy_session = iscsi_iser_session_destroy, /* connection management */ .create_conn = iscsi_iser_conn_create, .bind_conn = iscsi_iser_conn_bind, - .unbind_conn = iscsi_conn_unbind, + .ops_expand = &iscsi_iser_expand, .destroy_conn = iscsi_conn_teardown, .attr_is_visible = iser_attr_is_visible, .set_param = iscsi_iser_set_param, diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index b977e039bb78..06f697bfc49f 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -5801,16 +5801,21 @@ static struct pci_error_handlers beiscsi_eeh_handlers = { .resume = beiscsi_eeh_resume, };
+struct iscsi_transport_expand beiscsi_iscsi_expand = { + .unbind_conn = iscsi_conn_unbind, +}; + struct iscsi_transport beiscsi_iscsi_transport = { .owner = THIS_MODULE, .name = DRV_NAME, .caps = CAP_RECOVERY_L0 | CAP_HDRDGST | CAP_TEXT_NEGO | - CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD, + CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD | + CAP_OPS_EXPAND, .create_session = beiscsi_session_create, .destroy_session = beiscsi_session_destroy, .create_conn = beiscsi_conn_create, .bind_conn = beiscsi_conn_bind, - .unbind_conn = iscsi_conn_unbind, + .ops_expand = &beiscsi_iscsi_expand, .destroy_conn = iscsi_conn_teardown, .attr_is_visible = beiscsi_attr_is_visible, .set_iface_param = beiscsi_iface_set_param, diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 8cf2f9a7cfdc..e13c77a76150 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -2274,18 +2274,23 @@ static struct scsi_host_template bnx2i_host_template = { .track_queue_depth = 1, };
+ +static struct iscsi_transport_expand bnx2i_iscsi_expand = { + .unbind_conn = iscsi_conn_unbind, +}; + struct iscsi_transport bnx2i_iscsi_transport = { .owner = THIS_MODULE, .name = "bnx2i", .caps = CAP_RECOVERY_L0 | CAP_HDRDGST | CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD | - CAP_TEXT_NEGO, + CAP_TEXT_NEGO | CAP_OPS_EXPAND, .create_session = bnx2i_session_create, .destroy_session = bnx2i_session_destroy, .create_conn = bnx2i_conn_create, .bind_conn = bnx2i_conn_bind, - .unbind_conn = iscsi_conn_unbind, + .ops_expand = &bnx2i_iscsi_expand, .destroy_conn = bnx2i_conn_destroy, .attr_is_visible = bnx2i_attr_is_visible, .set_param = iscsi_set_param, diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c index edcd3fab6973..65eb6230d390 100644 --- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c +++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c @@ -100,13 +100,18 @@ static struct scsi_host_template cxgb3i_host_template = { .track_queue_depth = 1, };
+static struct iscsi_transport_expand cxgb3i_iscsi_expand = { + .unbind_conn = iscsi_conn_unbind, +}; + static struct iscsi_transport cxgb3i_iscsi_transport = { .owner = THIS_MODULE, .name = DRV_MODULE_NAME, /* owner and name should be set already */ .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST | CAP_DATADGST | CAP_DIGEST_OFFLOAD | - CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO, + CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO | + CAP_OPS_EXPAND, .attr_is_visible = cxgbi_attr_is_visible, .get_host_param = cxgbi_get_host_param, .set_host_param = cxgbi_set_host_param, @@ -117,7 +122,7 @@ static struct iscsi_transport cxgb3i_iscsi_transport = { /* connection management */ .create_conn = cxgbi_create_conn, .bind_conn = cxgbi_bind_conn, - .unbind_conn = iscsi_conn_unbind, + .ops_expand = &cxgb3i_iscsi_expand, .destroy_conn = iscsi_tcp_conn_teardown, .start_conn = iscsi_conn_start, .stop_conn = iscsi_conn_stop, diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index efb3e2b3398e..88f96964c356 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -118,12 +118,17 @@ static struct scsi_host_template cxgb4i_host_template = { .track_queue_depth = 1, };
+static struct iscsi_transport_expand cxgb4i_iscsi_expand = { + .unbind_conn = iscsi_conn_unbind, +}; + static struct iscsi_transport cxgb4i_iscsi_transport = { .owner = THIS_MODULE, .name = DRV_MODULE_NAME, .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST | CAP_DATADGST | CAP_DIGEST_OFFLOAD | - CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO, + CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO | + CAP_OPS_EXPAND, .attr_is_visible = cxgbi_attr_is_visible, .get_host_param = cxgbi_get_host_param, .set_host_param = cxgbi_set_host_param, @@ -134,7 +139,7 @@ static struct iscsi_transport cxgb4i_iscsi_transport = { /* connection management */ .create_conn = cxgbi_create_conn, .bind_conn = cxgbi_bind_conn, - .unbind_conn = iscsi_conn_unbind, + .ops_expand = &cxgb4i_iscsi_expand, .destroy_conn = iscsi_tcp_conn_teardown, .start_conn = iscsi_conn_start, .stop_conn = iscsi_conn_stop, diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c index 5f7e62f19d83..ba9a22e55e32 100644 --- a/drivers/scsi/qedi/qedi_iscsi.c +++ b/drivers/scsi/qedi/qedi_iscsi.c @@ -1430,16 +1430,20 @@ static void qedi_cleanup_task(struct iscsi_task *task) cmd->scsi_cmd = NULL; }
+static struct iscsi_transport_expand qedi_iscsi_expand = { + .unbind_conn = iscsi_conn_unbind, +}; + struct iscsi_transport qedi_iscsi_transport = { .owner = THIS_MODULE, .name = QEDI_MODULE_NAME, .caps = CAP_RECOVERY_L0 | CAP_HDRDGST | CAP_MULTI_R2T | CAP_DATADGST | - CAP_DATA_PATH_OFFLOAD | CAP_TEXT_NEGO, + CAP_DATA_PATH_OFFLOAD | CAP_TEXT_NEGO | CAP_OPS_EXPAND, .create_session = qedi_session_create, .destroy_session = qedi_session_destroy, .create_conn = qedi_conn_create, .bind_conn = qedi_conn_bind, - .unbind_conn = iscsi_conn_unbind, + .ops_expand = &qedi_iscsi_expand, .start_conn = qedi_conn_start, .stop_conn = iscsi_conn_stop, .destroy_conn = qedi_conn_destroy, diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 8d82d2a83059..377d83762099 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -246,20 +246,24 @@ static struct scsi_host_template qla4xxx_driver_template = { .vendor_id = SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC, };
+static struct iscsi_transport_expand qla4xxx_iscsi_expand = { + .unbind_conn = iscsi_conn_unbind, +}; + static struct iscsi_transport qla4xxx_iscsi_transport = { .owner = THIS_MODULE, .name = DRIVER_NAME, .caps = CAP_TEXT_NEGO | CAP_DATA_PATH_OFFLOAD | CAP_HDRDGST | CAP_DATADGST | CAP_LOGIN_OFFLOAD | - CAP_MULTI_R2T, + CAP_MULTI_R2T | CAP_OPS_EXPAND, .attr_is_visible = qla4_attr_is_visible, .create_session = qla4xxx_session_create, .destroy_session = qla4xxx_session_destroy, .start_conn = qla4xxx_conn_start, .create_conn = qla4xxx_conn_create, .bind_conn = qla4xxx_conn_bind, - .unbind_conn = iscsi_conn_unbind, + .ops_expand = &qla4xxx_iscsi_expand, .stop_conn = iscsi_conn_stop, .destroy_conn = qla4xxx_conn_destroy, .set_param = iscsi_set_param, diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 55b4ada390a6..e23cb62ab216 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2253,7 +2253,11 @@ static void iscsi_ep_disconnect(struct iscsi_cls_conn *conn, bool is_active) ep = conn->ep; conn->ep = NULL;
- session->transport->unbind_conn(conn, is_active); + if (session->transport->caps & CAP_OPS_EXPAND && + session->transport->ops_expand && + session->transport->ops_expand->unbind_conn) + session->transport->ops_expand->unbind_conn(conn, is_active); + session->transport->ep_disconnect(ep); ISCSI_DBG_TRANS_CONN(conn, "disconnect ep done.\n"); } @@ -3119,10 +3123,19 @@ iscsi_tgt_dscvr(struct iscsi_transport *transport, struct Scsi_Host *shost; struct sockaddr *dst_addr; int err; + int (*tgt_dscvr)(struct Scsi_Host *shost, enum iscsi_tgt_dscvr type, + uint32_t enable, struct sockaddr *dst_addr);
- if (!transport->tgt_dscvr) - return -EINVAL; - + if (transport->caps & CAP_OPS_EXPAND) { + if (!transport->ops_expand || !transport->ops_expand->tgt_dscvr) + return -EINVAL; + tgt_dscvr = transport->ops_expand->tgt_dscvr; + } else { + if (!transport->ops_expand) + return -EINVAL; + tgt_dscvr = (int (*)(struct Scsi_Host *, enum iscsi_tgt_dscvr, uint32_t, + struct sockaddr *))(transport->ops_expand); + } shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no); if (!shost) { printk(KERN_ERR "target discovery could not find host no %u\n", @@ -3132,8 +3145,8 @@ iscsi_tgt_dscvr(struct iscsi_transport *transport,
dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev)); - err = transport->tgt_dscvr(shost, ev->u.tgt_dscvr.type, - ev->u.tgt_dscvr.enable, dst_addr); + err = tgt_dscvr(shost, ev->u.tgt_dscvr.type, + ev->u.tgt_dscvr.enable, dst_addr); scsi_host_put(shost); return err; } @@ -4786,8 +4799,10 @@ iscsi_register_transport(struct iscsi_transport *tt) int err;
BUG_ON(!tt); - WARN_ON(tt->ep_disconnect && !tt->unbind_conn); - + if (tt->caps & CAP_OPS_EXPAND) { + BUG_ON(!tt->ops_expand); + WARN_ON(tt->ep_disconnect && !tt->ops_expand->unbind_conn); + } priv = iscsi_if_transport_lookup(tt); if (priv) return NULL; diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index 5225a23f2d0e..5679b9fb2b1e 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -761,6 +761,7 @@ enum iscsi_ping_status_code { and verification */ #define CAP_LOGIN_OFFLOAD 0x4000 /* offload session login */
+#define CAP_OPS_EXPAND 0x8000 /* oiscsi_transport->ops_expand flag */ /* * These flags describes reason of stop_conn() call */ diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 6f55690d3986..f9297176dcb8 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -29,6 +29,15 @@ struct bsg_job; struct iscsi_bus_flash_session; struct iscsi_bus_flash_conn;
+/* + * The expansion of iscsi_transport to fix kabi while adding members. + */ +struct iscsi_transport_expand { + int (*tgt_dscvr)(struct Scsi_Host *shost, enum iscsi_tgt_dscvr type, + uint32_t enable, struct sockaddr *dst_addr); + void (*unbind_conn)(struct iscsi_cls_conn *conn, bool is_active); +}; + /** * struct iscsi_transport - iSCSI Transport template * @@ -82,7 +91,6 @@ struct iscsi_transport { void (*destroy_session) (struct iscsi_cls_session *session); struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess, uint32_t cid); - void (*unbind_conn) (struct iscsi_cls_conn *conn, bool is_active); int (*bind_conn) (struct iscsi_cls_session *session, struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, int is_leading); @@ -124,8 +132,15 @@ struct iscsi_transport { int non_blocking); int (*ep_poll) (struct iscsi_endpoint *ep, int timeout_ms); void (*ep_disconnect) (struct iscsi_endpoint *ep); +#ifdef __GENKSYMS__ int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type, uint32_t enable, struct sockaddr *dst_addr); +#else + /* + * onece ops_expand is used, caps must be set to CAP_OPS_EXPAND + */ + struct iscsi_transport_expand *ops_expand; +#endif int (*set_path) (struct Scsi_Host *shost, struct iscsi_path *params); int (*set_iface_param) (struct Scsi_Host *shost, void *data, uint32_t len);