diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-08-04 19:47:37 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-08-04 19:47:37 -0700 |
| commit | 746fc76b820dce8cbb17a1e5e70a1558db4d7406 (patch) | |
| tree | 724898336ce5b4fd8c79d817c06b978929e28410 /drivers/target | |
| parent | 328141e51e6fc79d21168bfd4e356dddc2ec7491 (diff) | |
| parent | 8fcdc238ce1b492e1f57a73a2ce4131d63f45397 (diff) | |
| download | linux-746fc76b820dce8cbb17a1e5e70a1558db4d7406.tar.gz linux-746fc76b820dce8cbb17a1e5e70a1558db4d7406.tar.bz2 linux-746fc76b820dce8cbb17a1e5e70a1558db4d7406.zip | |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"Updates to the usual drivers (ufs, qla2xx, target, lpfc, smartpqi,
mpi3mr).
The main driver change that might cause issues on down the road is the
conversion of some of our oldest surviving drivers to the DMA API
(should only affect m68k).
The only major core change is the rework of async resume; the rest are
either completely trivial or for updating deprecated APIs"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (195 commits)
scsi: target: Remove XDWRITEREAD emulated support
scsi: megaraid: Remove the static variable initialisation
scsi: ch: Do not initialise statics to 0
scsi: ufs: core: Fix spelling mistake "Cannnot" -> "Cannot"
scsi: target: iscsi: Do not require target authentication
scsi: target: iscsi: Allow AuthMethod=None
scsi: target: iscsi: Support base64 in CHAP
scsi: target: iscsi: Add support for extended CDB AHS
scsi: ufs: dt-bindings: Add SC8280XP binding
scsi: target: iscsi: Fix clang -Wformat warnings
scsi: ufs: core: Read device property for ref clock
scsi: libsas: Resume SAS host for phy reset or enable via sysfs
scsi: hisi_sas: Modify v3 HW SATA completion error processing
scsi: hisi_sas: Relocate DMA unmap of SMP task
scsi: hisi_sas: Remove unnecessary variable to hold DMA map elements
scsi: hisi_sas: Call hisi_sas_slave_configure() from slave_configure_v3_hw()
scsi: mpi3mr: Delete a stray tab
scsi: mpi3mr: Unlock on error path
scsi: mpi3mr: Reduce VD queue depth on detecting throttling
scsi: mpi3mr: Resource Based Metering
...
Diffstat (limited to 'drivers/target')
| -rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 57 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_auth.c | 122 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_configfs.c | 113 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_login.c | 17 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_nego.c | 160 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_nego.h | 3 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_nodeattrib.c | 1 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_tpg.c | 3 | ||||
| -rw-r--r-- | drivers/target/target_core_alua.c | 2 | ||||
| -rw-r--r-- | drivers/target/target_core_configfs.c | 27 | ||||
| -rw-r--r-- | drivers/target/target_core_device.c | 6 | ||||
| -rw-r--r-- | drivers/target/target_core_file.c | 37 | ||||
| -rw-r--r-- | drivers/target/target_core_iblock.c | 13 | ||||
| -rw-r--r-- | drivers/target/target_core_sbc.c | 99 |
14 files changed, 389 insertions, 271 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index e368f038ff5c..baf4da7bb3b4 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1004,8 +1004,10 @@ int iscsit_setup_scsi_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd, unsigned char *buf) { int data_direction, payload_length; + struct iscsi_ecdb_ahdr *ecdb_ahdr; struct iscsi_scsi_req *hdr; int iscsi_task_attr; + unsigned char *cdb; int sam_task_attr; atomic_long_inc(&conn->sess->cmd_pdus); @@ -1106,6 +1108,27 @@ int iscsit_setup_scsi_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd, ISCSI_REASON_BOOKMARK_INVALID, buf); } + cdb = hdr->cdb; + + if (hdr->hlength) { + ecdb_ahdr = (struct iscsi_ecdb_ahdr *) (hdr + 1); + if (ecdb_ahdr->ahstype != ISCSI_AHSTYPE_CDB) { + pr_err("Additional Header Segment type %d not supported!\n", + ecdb_ahdr->ahstype); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_CMD_NOT_SUPPORTED, buf); + } + + cdb = kmalloc(be16_to_cpu(ecdb_ahdr->ahslength) + 15, + GFP_KERNEL); + if (cdb == NULL) + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); + memcpy(cdb, hdr->cdb, ISCSI_CDB_SIZE); + memcpy(cdb + ISCSI_CDB_SIZE, ecdb_ahdr->ecdb, + be16_to_cpu(ecdb_ahdr->ahslength) - 1); + } + data_direction = (hdr->flags & ISCSI_FLAG_CMD_WRITE) ? DMA_TO_DEVICE : (hdr->flags & ISCSI_FLAG_CMD_READ) ? DMA_FROM_DEVICE : DMA_NONE; @@ -1153,9 +1176,12 @@ int iscsit_setup_scsi_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd, struct iscsi_datain_req *dr; dr = iscsit_allocate_datain_req(); - if (!dr) + if (!dr) { + if (cdb != hdr->cdb) + kfree(cdb); return iscsit_add_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); + } iscsit_attach_datain_req(cmd, dr); } @@ -1176,9 +1202,12 @@ int iscsit_setup_scsi_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd, target_get_sess_cmd(&cmd->se_cmd, true); cmd->se_cmd.tag = (__force u32)cmd->init_task_tag; - cmd->sense_reason = target_cmd_init_cdb(&cmd->se_cmd, hdr->cdb, + cmd->sense_reason = target_cmd_init_cdb(&cmd->se_cmd, cdb, GFP_KERNEL); + if (cdb != hdr->cdb) + kfree(cdb); + if (cmd->sense_reason) { if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) { return iscsit_add_reject_cmd(cmd, @@ -4036,8 +4065,9 @@ static bool iscsi_target_check_conn_state(struct iscsit_conn *conn) static void iscsit_get_rx_pdu(struct iscsit_conn *conn) { int ret; - u8 *buffer, opcode; + u8 *buffer, *tmp_buf, opcode; u32 checksum = 0, digest = 0; + struct iscsi_hdr *hdr; struct kvec iov; buffer = kcalloc(ISCSI_HDR_LEN, sizeof(*buffer), GFP_KERNEL); @@ -4062,6 +4092,25 @@ static void iscsit_get_rx_pdu(struct iscsit_conn *conn) break; } + hdr = (struct iscsi_hdr *) buffer; + if (hdr->hlength) { + iov.iov_len = hdr->hlength * 4; + tmp_buf = krealloc(buffer, + ISCSI_HDR_LEN + iov.iov_len, + GFP_KERNEL); + if (!tmp_buf) + break; + + buffer = tmp_buf; + iov.iov_base = &buffer[ISCSI_HDR_LEN]; + + ret = rx_data(conn, &iov, 1, iov.iov_len); + if (ret != iov.iov_len) { + iscsit_rx_thread_wait_for_tcp(conn); + break; + } + } + if (conn->conn_ops->HeaderDigest) { iov.iov_base = &digest; iov.iov_len = ISCSI_CRC_LEN; @@ -4361,7 +4410,7 @@ int iscsit_close_connection( spin_lock_bh(&sess->conn_lock); atomic_dec(&sess->nconn); - pr_debug("Decremented iSCSI connection count to %hu from node:" + pr_debug("Decremented iSCSI connection count to %d from node:" " %s\n", atomic_read(&sess->nconn), sess->sess_ops->InitiatorName); /* diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c index 6e5611d8f51b..c8a248bd11be 100644 --- a/drivers/target/iscsi/iscsi_target_auth.c +++ b/drivers/target/iscsi/iscsi_target_auth.c @@ -205,6 +205,38 @@ static struct iscsi_chap *chap_server_open( return chap; } +static const char base64_lookup_table[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static int chap_base64_decode(u8 *dst, const char *src, size_t len) +{ + int i, bits = 0, ac = 0; + const char *p; + u8 *cp = dst; + + for (i = 0; i < len; i++) { + if (src[i] == '=') + return cp - dst; + + p = strchr(base64_lookup_table, src[i]); + if (p == NULL || src[i] == 0) + return -2; + + ac <<= 6; + ac += (p - base64_lookup_table); + bits += 6; + if (bits >= 8) { + *cp++ = (ac >> (bits - 8)) & 0xff; + ac &= ~(BIT(16) - BIT(bits - 8)); + bits -= 8; + } + } + if (ac) + return -1; + + return cp - dst; +} + static int chap_server_compute_hash( struct iscsit_conn *conn, struct iscsi_node_auth *auth, @@ -295,16 +327,27 @@ static int chap_server_compute_hash( pr_err("Could not find CHAP_R.\n"); goto out; } - if (type != HEX) { - pr_err("Could not find CHAP_R.\n"); - goto out; - } - if (strlen(chap_r) != chap->digest_size * 2) { - pr_err("Malformed CHAP_R\n"); - goto out; - } - if (hex2bin(client_digest, chap_r, chap->digest_size) < 0) { - pr_err("Malformed CHAP_R\n"); + + switch (type) { + case HEX: + if (strlen(chap_r) != chap->digest_size * 2) { + pr_err("Malformed CHAP_R\n"); + goto out; + } + if (hex2bin(client_digest, chap_r, chap->digest_size) < 0) { + pr_err("Malformed CHAP_R: invalid HEX\n"); + goto out; + } + break; + case BASE64: + if (chap_base64_decode(client_digest, chap_r, strlen(chap_r)) != + chap->digest_size) { + pr_err("Malformed CHAP_R: invalid BASE64\n"); + goto out; + } + break; + default: + pr_err("Could not find CHAP_R\n"); goto out; } @@ -373,7 +416,13 @@ static int chap_server_compute_hash( /* * Get CHAP_I. */ - if (extract_param(nr_in_ptr, "CHAP_I", 10, identifier, &type) < 0) { + ret = extract_param(nr_in_ptr, "CHAP_I", 10, identifier, &type); + if (ret == -ENOENT) { + pr_debug("Could not find CHAP_I. Initiator uses One way authentication.\n"); + auth_ret = 0; + goto out; + } + if (ret < 0) { pr_err("Could not find CHAP_I.\n"); goto out; } @@ -404,23 +453,46 @@ static int chap_server_compute_hash( goto out; } - if (type != HEX) { + switch (type) { + case HEX: + initiatorchg_len = DIV_ROUND_UP(strlen(initiatorchg), 2); + if (!initiatorchg_len) { + pr_err("Unable to convert incoming challenge\n"); + goto out; + } + if (initiatorchg_len > 1024) { + pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n"); + goto out; + } + + if (hex2bin(initiatorchg_binhex, initiatorchg, + initiatorchg_len) < 0) { + pr_err("Malformed CHAP_C: invalid HEX\n"); + goto out; + } + break; + case BASE64: + initiatorchg_len = chap_base64_decode(initiatorchg_binhex, + initiatorchg, + strlen(initiatorchg)); + if (initiatorchg_len < 0) { + pr_err("Malformed CHAP_C: invalid BASE64\n"); + goto out; + } + if (!initiatorchg_len) { + pr_err("Unable to convert incoming challenge\n"); + goto out; + } + if (initiatorchg_len > 1024) { + pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n"); + goto out; + } + break; + default: pr_err("Could not find CHAP_C.\n"); goto out; } - initiatorchg_len = DIV_ROUND_UP(strlen(initiatorchg), 2); - if (!initiatorchg_len) { - pr_err("Unable to convert incoming challenge\n"); - goto out; - } - if (initiatorchg_len > 1024) { - pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n"); - goto out; - } - if (hex2bin(initiatorchg_binhex, initiatorchg, initiatorchg_len) < 0) { - pr_err("Malformed CHAP_C\n"); - goto out; - } + pr_debug("[server] Got CHAP_C=%s\n", initiatorchg); /* * During mutual authentication, the CHAP_C generated by the diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index ce14540ba650..5d0f51822414 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -210,7 +210,7 @@ static struct se_tpg_np *lio_target_call_addnptotpg( return ERR_PTR(ret); } - tpg = container_of(se_tpg, struct iscsi_portal_group, tpg_se_tpg); + tpg = to_iscsi_tpg(se_tpg); ret = iscsit_get_tpg(tpg); if (ret < 0) return ERR_PTR(-EINVAL); @@ -281,9 +281,7 @@ static ssize_t iscsi_nacl_attrib_##name##_show(struct config_item *item,\ char *page) \ { \ struct se_node_acl *se_nacl = attrib_to_nacl(item); \ - struct iscsi_node_acl *nacl = container_of(se_nacl, struct iscsi_node_acl, \ - se_node_acl); \ - \ + struct iscsi_node_acl *nacl = to_iscsi_nacl(se_nacl); \ return sprintf(page, "%u\n", nacl->node_attrib.name); \ } \ \ @@ -291,8 +289,7 @@ static ssize_t iscsi_nacl_attrib_##name##_store(struct config_item *item,\ const char *page, size_t count) \ { \ struct se_node_acl *se_nacl = attrib_to_nacl(item); \ - struct iscsi_node_acl *nacl = container_of(se_nacl, struct iscsi_node_acl, \ - se_node_acl); \ + struct iscsi_node_acl *nacl = to_iscsi_nacl(se_nacl); \ u32 val; \ int ret; \ \ @@ -317,6 +314,36 @@ ISCSI_NACL_ATTR(random_datain_pdu_offsets); ISCSI_NACL_ATTR(random_datain_seq_offsets); ISCSI_NACL_ATTR(random_r2t_offsets); +static ssize_t iscsi_nacl_attrib_authentication_show(struct config_item *item, + char *page) +{ + struct se_node_acl *se_nacl = attrib_to_nacl(item); + struct iscsi_node_acl *nacl = to_iscsi_nacl(se_nacl); + + return sprintf(page, "%d\n", nacl->node_attrib.authentication); +} + +static ssize_t iscsi_nacl_attrib_authentication_store(struct config_item *item, + const char *page, size_t count) +{ + struct se_node_acl *se_nacl = attrib_to_nacl(item); + struct iscsi_node_acl *nacl = to_iscsi_nacl(se_nacl); + s32 val; + int ret; + + ret = kstrtos32(page, 0, &val); + if (ret) + return ret; + if (val != 0 && val != 1 && val != NA_AUTHENTICATION_INHERITED) + return -EINVAL; + + nacl->node_attrib.authentication = val; + + return count; +} + +CONFIGFS_ATTR(iscsi_nacl_attrib_, authentication); + static struct configfs_attribute *lio_target_nacl_attrib_attrs[] = { &iscsi_nacl_attrib_attr_dataout_timeout, &iscsi_nacl_attrib_attr_dataout_timeout_retries, @@ -326,6 +353,7 @@ static struct configfs_attribute *lio_target_nacl_attrib_attrs[] = { &iscsi_nacl_attrib_attr_random_datain_pdu_offsets, &iscsi_nacl_attrib_attr_random_datain_seq_offsets, &iscsi_nacl_attrib_attr_random_r2t_offsets, + &iscsi_nacl_attrib_attr_authentication, NULL, }; @@ -377,15 +405,14 @@ static ssize_t iscsi_nacl_auth_##name##_show(struct config_item *item, \ char *page) \ { \ struct se_node_acl *nacl = auth_to_nacl(item); \ - return __iscsi_nacl_auth_##name##_show(container_of(nacl, \ - struct iscsi_node_acl, se_node_acl), page); \ + return __iscsi_nacl_auth_##name##_show(to_iscsi_nacl(nacl), page); \ } \ static ssize_t iscsi_nacl_auth_##name##_store(struct config_item *item, \ const char *page, size_t count) \ { \ struct se_node_acl *nacl = auth_to_nacl(item); \ - return __iscsi_nacl_auth_##name##_store(container_of(nacl, \ - struct iscsi_node_acl, se_node_acl), page, count); \ + return __iscsi_nacl_auth_##name##_store(to_iscsi_nacl(nacl), \ + page, count); \ } \ \ CONFIGFS_ATTR(iscsi_nacl_auth_, name) @@ -417,8 +444,7 @@ static ssize_t iscsi_nacl_auth_##name##_show(struct config_item *item, \ char *page) \ { \ struct se_node_acl *nacl = auth_to_nacl(item); \ - return __iscsi_nacl_auth_##name##_show(container_of(nacl, \ - struct iscsi_node_acl, se_node_acl), page); \ + return __iscsi_nacl_auth_##name##_show(to_iscsi_nacl(nacl), page); \ } \ \ CONFIGFS_ATTR_RO(iscsi_nacl_auth_, name) @@ -623,8 +649,7 @@ static ssize_t lio_target_nacl_cmdsn_depth_store(struct config_item *item, { struct se_node_acl *se_nacl = acl_to_nacl(item); struct se_portal_group *se_tpg = se_nacl->se_tpg; - struct iscsi_portal_group *tpg = container_of(se_tpg, - struct iscsi_portal_group, tpg_se_tpg); + struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); struct config_item *acl_ci, *tpg_ci, *wwn_ci; u32 cmdsn_depth = 0; int ret; @@ -700,8 +725,7 @@ static struct configfs_attribute *lio_target_initiator_attrs[] = { static int lio_target_init_nodeacl(struct se_node_acl *se_nacl, const char *name) { - struct iscsi_node_acl *acl = - container_of(se_nacl, struct iscsi_node_acl, se_node_acl); + struct iscsi_node_acl *acl = to_iscsi_nacl(se_nacl); config_group_init_type_name(&acl->node_stat_grps.iscsi_sess_stats_group, "iscsi_sess_stats", &iscsi_stat_sess_cit); @@ -720,8 +744,7 @@ static ssize_t iscsi_tpg_attrib_##name##_show(struct config_item *item, \ char *page) \ { \ struct se_portal_group *se_tpg = attrib_to_tpg(item); \ - struct iscsi_portal_group *tpg = container_of(se_tpg, \ - struct iscsi_portal_group, tpg_se_tpg); \ + struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); \ ssize_t rb; \ \ if (iscsit_get_tpg(tpg) < 0) \ @@ -736,8 +759,7 @@ static ssize_t iscsi_tpg_attrib_##name##_store(struct config_item *item,\ const char *page, size_t count) \ { \ struct se_portal_group *se_tpg = attrib_to_tpg(item); \ - struct iscsi_portal_group *tpg = container_of(se_tpg, \ - struct iscsi_portal_group, tpg_se_tpg); \ + struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); \ u32 val; \ int ret; \ \ @@ -800,8 +822,7 @@ static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = { static ssize_t __iscsi_##prefix##_##name##_show(struct se_portal_group *se_tpg, \ char *page) \ { \ - struct iscsi_portal_group *tpg = container_of(se_tpg, \ - struct iscsi_portal_group, tpg_se_tpg); \ + struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); \ struct iscsi_node_auth *auth = &tpg->tpg_demo_auth; \ \ if (!capable(CAP_SYS_ADMIN)) \ @@ -813,8 +834,7 @@ static ssize_t __iscsi_##prefix##_##name##_show(struct se_portal_group *se_tpg, static ssize_t __iscsi_##prefix##_##name##_store(struct se_portal_group *se_tpg,\ const char *page, size_t count) \ { \ - struct iscsi_portal_group *tpg = container_of(se_tpg, \ - struct iscsi_portal_group, tpg_se_tpg); \ + struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); \ struct iscsi_node_auth *auth = &tpg->tpg_demo_auth; \ \ if (!capable(CAP_SYS_ADMIN)) \ @@ -861,8 +881,7 @@ DEF_TPG_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET); static ssize_t __iscsi_##prefix##_##name##_show(struct se_portal_group *se_tpg, \ char *page) \ { \ - struct iscsi_portal_group *tpg = container_of(se_tpg, \ - struct iscsi_portal_group, tpg_se_tpg); \ + struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); \ struct iscsi_node_auth *auth = &tpg->tpg_demo_auth; \ \ if (!capable(CAP_SYS_ADMIN)) \ @@ -900,8 +919,7 @@ static ssize_t iscsi_tpg_param_##name##_show(struct config_item *item, \ char *page) \ { \ struct se_portal_group *se_tpg = param_to_tpg(item); \ - struct iscsi_portal_group *tpg = container_of(se_tpg, \ - struct iscsi_portal_group, tpg_se_tpg); \ + struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); \ struct iscsi_param *param; \ ssize_t rb; \ \ @@ -923,8 +941,7 @@ static ssize_t iscsi_tpg_param_##name##_store(struct config_item *item, \ const char *page, size_t count) \ { \ struct se_portal_group *se_tpg = param_to_tpg(item); \ - struct iscsi_portal_group *tpg = container_of(se_tpg, \ - struct iscsi_portal_group, tpg_se_tpg); \ + struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); \ char *buf; \ int ret, len; \ \ @@ -1073,8 +1090,7 @@ free_out: static int lio_target_tiqn_enabletpg(struct se_portal_group *se_tpg, bool enable) { - struct iscsi_portal_group *tpg = container_of(se_tpg, - struct iscsi_portal_group, tpg_se_tpg); + struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); int ret; ret = iscsit_get_tpg(tpg); @@ -1106,7 +1122,7 @@ static void lio_target_tiqn_deltpg(struct se_portal_group *se_tpg) struct iscsi_portal_group *tpg; struct iscsi_tiqn *tiqn; - tpg = container_of(se_tpg, struct iscsi_portal_group, tpg_se_tpg); + tpg = to_iscsi_tpg(se_tpg); tiqn = tpg->tpg_tiqn; /* * iscsit_tpg_del_portal_group() assumes force=1 @@ -1416,46 +1432,41 @@ static void lio_aborted_task(struct se_cmd *se_cmd) cmd->conn->conn_transport->iscsit_aborted_task(cmd->conn, cmd); } -static inline struct iscsi_portal_group *iscsi_tpg(struct se_portal_group *se_tpg) -{ - return container_of(se_tpg, struct iscsi_portal_group, tpg_se_tpg); -} - static char *lio_tpg_get_endpoint_wwn(struct se_portal_group *se_tpg) { - return iscsi_tpg(se_tpg)->tpg_tiqn->tiqn; + return to_iscsi_tpg(se_tpg)->tpg_tiqn->tiqn; } static u16 lio_tpg_get_tag(struct se_portal_group *se_tpg) { - return iscsi_tpg(se_tpg)->tpgt; + return to_iscsi_tpg(se_tpg)->tpgt; } static u32 lio_tpg_get_default_depth(struct se_portal_group *se_tpg) { - return iscsi_tpg(se_tpg)->tpg_attrib.default_cmdsn_depth; + return to_iscsi_tpg(se_tpg)->tpg_attrib.default_cmdsn_depth; } static int lio_tpg_check_demo_mode(struct se_portal_group *se_tpg) { - return iscsi_tpg(se_tpg)->tpg_attrib.generate_node_acls; + return to_iscsi_tpg(se_tpg)->tpg_attrib.generate_node_acls; } static int lio_tpg_check_demo_mode_cache(struct se_portal_group *se_tpg) { - return iscsi_tpg(se_tpg)->tpg_attrib.cache_dynamic_acls; + return to_iscsi_tpg(se_tpg)->tpg_attrib.cache_dynamic_acls; } static int lio_tpg_check_demo_mode_write_protect( struct se_portal_group *se_tpg) { - return iscsi_tpg(se_tpg)->tpg_attrib.demo_mode_write_protect; + return to_iscsi_tpg(se_tpg)->tpg_attrib.demo_mode_write_protect; } static int lio_tpg_check_prod_mode_write_protect( struct se_portal_group *se_tpg) { - return iscsi_tpg(se_tpg)->tpg_attrib.prod_mode_write_protect; + return to_iscsi_tpg(se_tpg)->tpg_attrib.prod_mode_write_protect; } static int lio_tpg_check_prot_fabric_only( @@ -1465,9 +1476,9 @@ static int lio_tpg_check_prot_fabric_only( * Only report fabric_prot_type if t10_pi has also been enabled * for incoming ib_isert sessions. */ - if (!iscsi_tpg(se_tpg)->tpg_attrib.t10_pi) + if (!to_iscsi_tpg(se_tpg)->tpg_attrib.t10_pi) return 0; - return iscsi_tpg(se_tpg)->tpg_attrib.fabric_prot_type; + return to_iscsi_tpg(se_tpg)->tpg_attrib.fabric_prot_type; } /* @@ -1504,16 +1515,14 @@ static void lio_tpg_close_session(struct se_session *se_sess) static u32 lio_tpg_get_inst_index(struct se_portal_group *se_tpg) { - return iscsi_tpg(se_tpg)->tpg_tiqn->tiqn_index; + return to_iscsi_tpg(se_tpg)->tpg_tiqn->tiqn_index; } static void lio_set_default_node_attributes(struct se_node_acl *se_acl) { - struct iscsi_node_acl *acl = container_of(se_acl, struct iscsi_node_acl, - se_node_acl); + struct iscsi_node_acl *acl = to_iscsi_nacl(se_acl); struct se_portal_group *se_tpg = se_acl->se_tpg; - struct iscsi_portal_group *tpg = container_of(se_tpg, - struct iscsi_portal_group, tpg_se_tpg); + struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); acl->node_attrib.nacl = acl; iscsit_set_default_node_attribues(acl, tpg); diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 6b94eecc4790..27e448c2d066 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -341,6 +341,7 @@ static int iscsi_login_zero_tsih_s2( { struct iscsi_node_attrib *na; struct iscsit_session *sess = conn->sess; + struct iscsi_param *param; bool iser = false; sess->tpg = conn->tpg; @@ -375,6 +376,18 @@ static int iscsi_login_zero_tsih_s2( na = iscsit_tpg_get_node_attrib(sess); /* + * If ACL allows non-authorized access in TPG with CHAP, + * then set None to AuthMethod. + */ + param = iscsi_find_param_from_key(AUTHMETHOD, conn->param_list); + if (param && !strstr(param->value, NONE)) { + if (!iscsi_conn_auth_required(conn)) + if (iscsi_change_param_sprintf(conn, "AuthMethod=%s", + NONE)) + return -1; + } + + /* * Need to send TargetPortalGroupTag back in first login response * on any iSCSI connection where the Initiator provides TargetName. * See 5.3.1. Login Phase Start @@ -715,7 +728,7 @@ void iscsi_post_login_handler( list_add_tail(&conn->conn_list, &sess->sess_conn_list); atomic_inc(&sess->nconn); - pr_debug("Incremented iSCSI Connection count to %hu" + pr_debug("Incremented iSCSI Connection count to %d" " from node: %s\n", atomic_read(&sess->nconn), sess->sess_ops->InitiatorName); spin_unlock_bh(&sess->conn_lock); @@ -763,7 +776,7 @@ void iscsi_post_login_handler( spin_lock_bh(&sess->conn_lock); list_add_tail(&conn->conn_list, &sess->sess_conn_list); atomic_inc(&sess->nconn); - pr_debug("Incremented iSCSI Connection count to %hu from node:" + pr_debug("Incremented iSCSI Connection count to %d from node:" " %s\n", atomic_read(&sess->nconn), sess->sess_ops->InitiatorName); spin_unlock_bh(&sess->conn_lock); diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index b34ac9ecac31..f2919319ad38 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -62,31 +62,34 @@ int extract_param( int len; if (!in_buf || !pattern || !out_buf || !type) - return -1; + return -EINVAL; ptr = strstr(in_buf, pattern); if (!ptr) - return -1; + return -ENOENT; ptr = strstr(ptr, "="); if (!ptr) - return -1; + return -EINVAL; ptr += 1; if (*ptr == '0' && (*(ptr+1) == 'x' || *(ptr+1) == 'X')) { ptr += 2; /* skip 0x */ *type = HEX; + } else if (*ptr == '0' && (*(ptr+1) == 'b' || *(ptr+1) == 'B')) { + ptr += 2; /* skip 0b */ + *type = BASE64; } else *type = DECIMAL; len = strlen_semi(ptr); if (len < 0) - return -1; + return -EINVAL; if (len >= max_length) { pr_err("Length of input: %d exceeds max_length:" " %d\n", len, max_length); - return -1; + return -EINVAL; } memcpy(out_buf, ptr, len); out_buf[len] = '\0'; @@ -94,6 +97,31 @@ int extract_param( return 0; } +static struct iscsi_node_auth *iscsi_get_node_auth(struct iscsit_conn *conn) +{ + struct iscsi_portal_group *tpg; + struct iscsi_node_acl *nacl; + struct se_node_acl *se_nacl; + + if (conn->sess->sess_ops->SessionType) + return &iscsit_global->discovery_acl.node_auth; + + se_nacl = conn->sess->se_sess->se_node_acl; + if (!se_nacl) { + pr_err("Unable to locate struct se_node_acl for CHAP auth\n"); + return NULL; + } + + if (se_nacl->dynamic_node_acl) { + tpg = to_iscsi_tpg(se_nacl->se_tpg); + return &tpg->tpg_demo_auth; + } + + nacl = to_iscsi_nacl(se_nacl); + + return &nacl->node_auth; +} + static u32 iscsi_handle_authentication( struct iscsit_conn *conn, char *in_buf, @@ -102,40 +130,11 @@ static u32 iscsi_handle_authentication( int *out_length, unsigned char *authtype) { - struct iscsit_session *sess = conn->sess; struct iscsi_node_auth *auth; - struct iscsi_node_acl *iscsi_nacl; - struct iscsi_portal_group *iscsi_tpg; - struct se_node_acl *se_nacl; - - if (!sess->sess_ops->SessionType) { - /* - * For SessionType=Normal - */ - se_nacl = conn->sess->se_sess->se_node_acl; - if (!se_nacl) { - pr_err("Unable to locate struct se_node_acl for" - " CHAP auth\n"); - return -1; - } - - if (se_nacl->dynamic_node_acl) { - iscsi_tpg = container_of(se_nacl->se_tpg, - struct iscsi_portal_group, tpg_se_tpg); - - auth = &iscsi_tpg->tpg_demo_auth; - } else { - iscsi_nacl = container_of(se_nacl, struct iscsi_node_acl, - se_node_acl); - auth = &iscsi_nacl->node_auth; - } - } else { - /* - * For SessionType=Discovery - */ - auth = &iscsit_global->discovery_acl.node_auth; - } + auth = iscsi_get_node_auth(conn); + if (!auth) + return -1; if (strstr("CHAP", authtype)) strcpy(conn->sess->auth_type, "CHAP"); @@ -815,6 +814,42 @@ static int iscsi_target_do_authentication( return 0; } +bool iscsi_conn_auth_required(struct iscsit_conn *conn) +{ + struct iscsi_node_acl *nacl; + struct se_node_acl *se_nacl; + + if (conn->sess->sess_ops->SessionType) { + /* + * For SessionType=Discovery + */ + return conn->tpg->tpg_attrib.authentication; + } + /* + * For SessionType=Normal + */ + se_nacl = conn->sess->se_sess->se_node_acl; + if (!se_nacl) { + pr_debug("Unknown ACL is trying to connect\n"); + return true; + } + + if (se_nacl->dynamic_node_acl) { + pr_debug("Dynamic ACL %s is trying to connect\n", + se_nacl->initiatorname); + return conn->tpg->tpg_attrib.authentication; + } + + pr_debug("Known ACL %s is trying to connect\n", + se_nacl->initiatorname); + + nacl = to_iscsi_nacl(se_nacl); + if (nacl->node_attrib.authentication == NA_AUTHENTICATION_INHERITED) + return conn->tpg->tpg_attrib.authentication; + + return nacl->node_attrib.authentication; +} + static int iscsi_target_handle_csg_zero( struct iscsit_conn *conn, struct iscsi_login *login) @@ -876,22 +911,26 @@ static int iscsi_target_handle_csg_zero( return -1; if (!iscsi_check_negotiated_keys(conn->param_list)) { - if (conn->tpg->tpg_attrib.authentication && - !strncmp(param->value, NONE, 4)) { - pr_err("Initiator sent AuthMethod=None but" - " Target is enforcing iSCSI Authentication," - " login failed.\n"); - iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, - ISCSI_LOGIN_STATUS_AUTH_FAILED); - return -1; - } + bool auth_required = iscsi_conn_auth_required(conn); + + if (auth_required) { + if (!strncmp(param->value, NONE, 4)) { + pr_err("Initiator sent AuthMethod=None but" + " Target is enforcing iSCSI Authentication," + " login failed.\n"); + iscsit_tx_login_rsp(conn, + ISCSI_STATUS_CLS_INITIATOR_ERR, + ISCSI_LOGIN_STATUS_AUTH_FAILED); + return -1; + } - if (conn->tpg->tpg_attrib.authentication && - !login->auth_complete) - return 0; + if (!login->auth_complete) + return 0; - if (strncmp(param->value, NONE, 4) && !login->auth_complete) - return 0; + if (strncmp(param->value, NONE, 4) && + !login->auth_complete) + return 0; + } if ((login_req->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE1) && (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT)) { @@ -906,6 +945,18 @@ do_auth: return iscsi_target_do_authentication(conn, login); } +static bool iscsi_conn_authenticated(struct iscsit_conn *conn, + struct iscsi_login *login) +{ + if (!iscsi_conn_auth_required(conn)) + return true; + + if (login->auth_complete) + return true; + + return false; +} + static int iscsi_target_handle_csg_one(struct iscsit_conn *conn, struct iscsi_login *login) { int ret; @@ -949,11 +1000,10 @@ static int iscsi_target_handle_csg_one(struct iscsit_conn *conn, struct iscsi_lo return -1; } - if (!login->auth_complete && - conn->tpg->tpg_attrib.authentication) { + if (!iscsi_conn_authenticated(conn, login)) { pr_err("Initiator is requesting CSG: 1, has not been" - " successfully authenticated, and the Target is" - " enforcing iSCSI Authentication, login failed.\n"); + " successfully authenticated, and the Target is" + " enforcing iSCSI Authentication, login failed.\n"); iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, ISCSI_LOGIN_STATUS_AUTH_FAILED); return -1; diff --git a/drivers/target/iscsi/iscsi_target_nego.h b/drivers/target/iscsi/iscsi_target_nego.h index ed30b9ee75e6..41c3db3ddeaa 100644 --- a/drivers/target/iscsi/iscsi_target_nego.h +++ b/drivers/target/iscsi/iscsi_target_nego.h @@ -4,6 +4,7 @@ #define DECIMAL 0 #define HEX 1 +#define BASE |
