summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2025-10-22 13:03:41 +0200
committerSimon Rettberg2025-12-09 15:33:20 +0100
commitcdf12d13d1636db3ef14ea9d8acae3f919d3290b (patch)
treec6bb26028529e3652ad6dc58d8f596fd619ff72a
parent[SERVER] Check if iSCSI server is enabled, check opcode (diff)
downloaddnbd3-cdf12d13d1636db3ef14ea9d8acae3f919d3290b.tar.gz
dnbd3-cdf12d13d1636db3ef14ea9d8acae3f919d3290b.tar.xz
dnbd3-cdf12d13d1636db3ef14ea9d8acae3f919d3290b.zip
[SERVER] iscsi: Fix crashes
-rw-r--r--src/server/iscsi.c62
-rw-r--r--src/server/iscsi.h14
-rw-r--r--src/shared/sockhelper.c2
3 files changed, 41 insertions, 37 deletions
diff --git a/src/server/iscsi.c b/src/server/iscsi.c
index 30e4f7e..30cf312 100644
--- a/src/server/iscsi.c
+++ b/src/server/iscsi.c
@@ -362,7 +362,10 @@ static void iscsi_task_destroy(iscsi_task *task)
if ( task == NULL )
return;
- free( task->scsi_task.buf );
+ if ( task->scsi_task.must_free ) {
+ free( task->scsi_task.buf );
+ }
+ free( task->scsi_task.sense_data );
free( task );
}
@@ -509,6 +512,9 @@ static int iscsi_task_xfer_scsi_data_in(iscsi_connection *conn, iscsi_task *task
res_cnt = (pos - xfer_len);
flags |= ISCSI_SCSI_DATA_IN_RESPONSE_FLAGS_RES_OVERFLOW;
}
+ logadd( LOG_DEBUG1, "iscsi_task_xfer_scsi_data_in: pos=%lu, xfer_len=%lu, seg_len=%lu", pos, xfer_len, seg_len );
+ if ( xfer_len == 0UL )
+ return 0;
uint32_t data_sn = task->data_sn;
uint32_t max_burst_offset = 0UL;
@@ -653,6 +659,7 @@ static void iscsi_scsi_task_create(iscsi_scsi_task *scsi_task)
scsi_task->cdb = NULL;
scsi_task->sense_data = NULL;
scsi_task->buf = NULL;
+ scsi_task->must_free = true;
scsi_task->len = 0UL;
scsi_task->id = 0ULL;
scsi_task->flags = 0;
@@ -775,28 +782,9 @@ static void iscsi_scsi_task_lun_process_none(iscsi_scsi_task *scsi_task)
scsi_task->len = scsi_task->xfer_len;
- if ( cdb->cdb.opcode == ISCSI_SCSI_OPCODE_INQUIRY ) {
- uint len = sizeof(struct iscsi_scsi_std_inquiry_data_packet);
-
- memset( &std_inquiry_data_pkt, 0, len );
-
- std_inquiry_data_pkt.basic_inquiry.peripheral_type_id = (ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_PERIPHERAL_TYPE(ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_UNKNOWN) | ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_PERIPHERAL_ID(ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_NEVER));
- std_inquiry_data_pkt.basic_inquiry.add_len = (uint8_t) (len - sizeof(struct iscsi_scsi_basic_inquiry_data_packet));
-
- const uint alloc_len = iscsi_get_be16(cdb->alloc_len);
-
- if ( len > alloc_len )
- len = alloc_len;
-
- memcpy( scsi_task->buf, &std_inquiry_data_pkt, len );
-
- scsi_task->xfer_pos = len;
- scsi_task->status = ISCSI_SCSI_STATUS_GOOD;
- } else {
- iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_ILLEGAL_REQ, ISCSI_SCSI_ASC_LU_NOT_SUPPORTED, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE );
+ iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_ILLEGAL_REQ, ISCSI_SCSI_ASC_LU_NOT_SUPPORTED, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE );
- scsi_task->xfer_pos = 0UL;
- }
+ scsi_task->xfer_pos = 0UL;
}
/**
@@ -1120,7 +1108,7 @@ static int iscsi_scsi_emu_block_read_write(dnbd3_image_t *image, iscsi_scsi_task
const uint32_t max_xfer_len = ISCSI_MAX_DS_SIZE / ISCSI_SCSI_EMU_BLOCK_SIZE;
- if ( xfer_len > max_xfer_len ) {
+ if ( xfer_len > max_xfer_len || xfer_len * ISCSI_SCSI_EMU_BLOCK_SIZE != scsi_task->len ) {
iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_ILLEGAL_REQ, ISCSI_SCSI_ASC_INVALID_FIELD_IN_CDB, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE );
return ISCSI_SCSI_TASK_RUN_COMPLETE;
@@ -1482,7 +1470,7 @@ static int iscsi_scsi_emu_primary_inquiry(dnbd3_image_t *image, iscsi_scsi_task
iscsi_strcpy_pad( (char *) vpd_page_design_desc_t10_vendor_id_inquiry_data_pkt->vendor_id, ISCSI_SCSI_STD_INQUIRY_DATA_DISK_VENDOR_ID, sizeof(vpd_page_design_desc_t10_vendor_id_inquiry_data_pkt->vendor_id), ' ' );
iscsi_strcpy_pad( (char *) vpd_page_design_desc_t10_vendor_id_inquiry_data_pkt->product_id, image->name, sizeof(vpd_page_design_desc_t10_vendor_id_inquiry_data_pkt->product_id), ' ' );
- iscsi_strcpy_pad( (char *) vpd_page_design_desc_t10_vendor_id_inquiry_data_pkt->unit_serial_num, image->path, sizeof(vpd_page_design_desc_t10_vendor_id_inquiry_data_pkt->unit_serial_num), ' ' );
+ iscsi_strcpy_pad( (char *) vpd_page_design_desc_t10_vendor_id_inquiry_data_pkt->unit_serial_num, image->name, sizeof(vpd_page_design_desc_t10_vendor_id_inquiry_data_pkt->unit_serial_num), ' ' );
alloc_len += (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + sizeof(struct iscsi_scsi_vpd_page_design_desc_t10_vendor_id_inquiry_data_packet));
@@ -1534,7 +1522,7 @@ static int iscsi_scsi_emu_primary_inquiry(dnbd3_image_t *image, iscsi_scsi_task
vpd_page_design_desc_inquiry_data_pkt->reserved = 0U;
vpd_page_design_desc_inquiry_data_pkt->len = sizeof(struct iscsi_scsi_vpd_page_design_desc_logical_unit_group_inquiry_data_packet);
- iscsi_scsi_vpd_page_design_desc_logical_unit_group_inquiry_data_packet *vpd_page_design_desc_logical_unit_group_inquiry_data_pkt = vpd_page_design_desc_inquiry_data_pkt->desc;
+ iscsi_scsi_vpd_page_design_desc_logical_unit_group_inquiry_data_packet *vpd_page_design_desc_logical_unit_group_inquiry_data_pkt = (iscsi_scsi_vpd_page_design_desc_logical_unit_group_inquiry_data_packet*)vpd_page_design_desc_inquiry_data_pkt->desc;
vpd_page_design_desc_logical_unit_group_inquiry_data_pkt->reserved = 0U;
iscsi_put_be16( (uint8_t *) &vpd_page_design_desc_logical_unit_group_inquiry_data_pkt->id, (uint16_t) ISCSI_DEFAULT_DEVICE_ID );
@@ -2206,8 +2194,9 @@ static int iscsi_scsi_emu_primary_process(iscsi_scsi_task *scsi_task)
rc = iscsi_scsi_emu_primary_inquiry( scsi_task->connection->client->image, scsi_task, cdb_inquiry, std_inquiry_data_pkt, len );
if ( (rc >= 0) && (len > 0U) ) {
- if ( len > alloc_len )
+ if ( len > alloc_len ) {
len = alloc_len;
+ }
scsi_task->buf = (uint8_t *) std_inquiry_data_pkt;
@@ -2215,6 +2204,8 @@ static int iscsi_scsi_emu_primary_process(iscsi_scsi_task *scsi_task)
memset( (((uint8_t *) std_inquiry_data_pkt) + rc), 0, (len - rc) );
rc = len;
+ } else {
+ free( std_inquiry_data_pkt );
}
if ( rc >= 0 ) {
@@ -2522,6 +2513,7 @@ static iscsi_connection *iscsi_connection_create(dnbd3_client_t *client)
static void iscsi_connection_destroy(iscsi_connection *conn)
{
if ( conn != NULL ) {
+ iscsi_connection_pdu_destroy( conn->login_response_pdu );
iscsi_session_destroy( conn->session );
iscsi_connection_pdu_destroy( conn->pdu_processing );
free( conn );
@@ -2655,6 +2647,9 @@ static int iscsi_connection_pdu_login_response(iscsi_connection *conn, iscsi_pdu
login_response_pkt->flags &= (int8_t) ~(ISCSI_LOGIN_RESPONSE_FLAGS_TRANSIT | ISCSI_LOGIN_RESPONSE_FLAGS_CURRENT_STAGE_MASK | ISCSI_LOGIN_RESPONSE_FLAGS_NEXT_STAGE_MASK );
iscsi_connection_pdu_write( conn, resp_pdu );
+ if ( conn->login_response_pdu == resp_pdu ) {
+ conn->login_response_pdu = NULL;
+ }
return ISCSI_CONNECT_PDU_READ_OK;
}
@@ -3224,7 +3219,9 @@ static int iscsi_connection_pdu_header_handle_login_req(iscsi_connection *conn,
if ( pdu->ds_len > ISCSI_DEFAULT_RECV_DS_LEN )
return iscsi_connection_handle_reject( conn, pdu, ISCSI_REJECT_REASON_PROTOCOL_ERR );
- iscsi_pdu *login_response_pdu = iscsi_connection_pdu_create( conn, 8192, false );
+ iscsi_pdu *login_response_pdu = conn->login_response_pdu != NULL
+ ? conn->login_response_pdu
+ : iscsi_connection_pdu_create( conn, 8192, false );
if ( login_response_pdu == NULL )
return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
@@ -3312,7 +3309,9 @@ static int iscsi_connection_pdu_header_handle_scsi_cmd(iscsi_connection *conn, i
uint32_t exp_xfer_len = iscsi_get_be32(scsi_cmd_pkt->exp_xfer_len);
- task->scsi_task.buf = (uint8_t *) pdu->ds_cmd_data;
+ //task->scsi_task.buf = (uint8_t *) pdu->ds_cmd_data;
+ //logadd( LOG_DEBUG1, "ds_Cmd_data gets assigned: %d", task->scsi_task.must_free );
+ //task->scsi_task.must_free = false;
task->scsi_task.len = (uint) (((uint8_t *) pdu->ds_cmd_data) - ((uint8_t *) pdu->bhs_pkt));
task->scsi_task.cdb = &scsi_cmd_pkt->scsi_cdb;
task->scsi_task.xfer_len = exp_xfer_len;
@@ -3331,6 +3330,7 @@ static int iscsi_connection_pdu_header_handle_scsi_cmd(iscsi_connection *conn, i
task->scsi_task.flags |= ISCSI_SCSI_TASK_FLAGS_XFER_READ;
if ( (scsi_cmd_pkt->flags_task & ISCSI_SCSI_CMD_FLAGS_TASK_WRITE) != 0 ) {
+ iscsi_task_destroy( task );
return iscsi_connection_handle_reject( conn, pdu, ISCSI_REJECT_REASON_COMMAND_NOT_SUPPORTED );
}
@@ -3882,8 +3882,9 @@ static int iscsi_connection_pdu_data_handle_login_req(iscsi_connection *conn, is
if ( conn->state == ISCSI_CONNECT_STATE_INVALID ) {
rc = iscsi_connection_handle_login_phase_none( conn, login_response_pdu, &pairs, cid );
+ logadd( LOG_DEBUG1, "rc2: %d", rc );
- if ( (rc == ISCSI_CONNECT_PDU_READ_ERR_LOGIN_RESPONSE) || (rc == ISCSI_CONNECT_PDU_READ_ERR_LOGIN_PARAMETER) ) {
+ if ( rc != ISCSI_CONNECT_PDU_READ_OK ) {
iscsi_connection_pdu_login_response( conn, login_response_pdu );
return ISCSI_CONNECT_PDU_READ_OK;
@@ -4207,6 +4208,9 @@ static int iscsi_connection_pdu_read(iscsi_connection *conn)
break;
}
}
+ if ( conn->state == ISCSI_CONNECT_STATE_EXITING ) {
+ return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
+ }
} while ( prev_recv_state != conn->pdu_recv_state );
return 0;
diff --git a/src/server/iscsi.h b/src/server/iscsi.h
index 6dfb515..622d49b 100644
--- a/src/server/iscsi.h
+++ b/src/server/iscsi.h
@@ -1470,10 +1470,10 @@ typedef struct __attribute__((packed)) iscsi_scsi_vpd_page_inquiry_data_packet {
#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_ISCSI 0x05
/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data protocol identifier: First bit of the four bits.
-#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_FIRST_BIT 0
+#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_FIRST_BIT 4
/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data protocol identifier: Last bit of the four bits.
-#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_LAST_BIT ((ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_FIRST_BIT) + 4 - 1)
+#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_LAST_BIT ((ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_FIRST_BIT) + 8 - 1)
/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data protocol identifier: Bit mask.
#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_LAST_BIT))
@@ -1494,10 +1494,10 @@ typedef struct __attribute__((packed)) iscsi_scsi_vpd_page_inquiry_data_packet {
#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_UTF8 0x03
/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data code set: First bit of the four bits.
-#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_FIRST_BIT 4
+#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_FIRST_BIT 0
/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data code set: Last bit of the four bits.
-#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_LAST_BIT ((ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_FIRST_BIT) + 8 - 1)
+#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_LAST_BIT ((ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_FIRST_BIT) + 4 - 1)
/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data code set: Bit mask.
#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_LAST_BIT))
@@ -5897,6 +5897,9 @@ typedef struct iscsi_scsi_task {
/// Output buffer.
uint8_t *buf;
+ /// Whether output buffer os owned by this struct and must be freed on destroy
+ bool must_free;
+
/// Offset in bytes in image for DATA-in command.
size_t file_offset;
@@ -6141,9 +6144,6 @@ typedef struct iscsi_pdu iscsi_pdu;
/// iSCSI connection state: Exiting.
#define ISCSI_CONNECT_STATE_EXITING 2
-/// iSCSI connection state: Invalid.
-#define ISCSI_CONNECT_STATE_EXITED 3
-
/// Number of attempts for writing to iSCSI connection socket.
#define ISCSI_CONNECT_SOCKET_WRITE_RETRIES 3
diff --git a/src/shared/sockhelper.c b/src/shared/sockhelper.c
index 6972957..0aad1a3 100644
--- a/src/shared/sockhelper.c
+++ b/src/shared/sockhelper.c
@@ -435,7 +435,7 @@ ssize_t sock_recv(const int sock, void *buffer, const size_t len)
done += ret;
}
if ( done == 0 ) return ret;
- return done;
+ return (ssize_t)done;
}
bool sock_sendPadding(const int fd, uint32_t bytes)