Browse Source

libiscsi package creation

Signed-off-by: basebuilder_pel7x64builder0 <basebuilder@powerel.org>
master
basebuilder_pel7x64builder0 6 years ago
parent
commit
82c7f999b0
  1. 36
      SOURCES/0001-do-not-reconnect-if-reconnect-is-already-defered.patch
  2. 31
      SOURCES/0002-fix-leak-of-iscsi_context-in-iscsi_reconnect.patch
  3. 77
      SOURCES/0003-Add-ASCQ-codes-related-to-thin-provisioning.patch
  4. 388
      SOURCES/0004-Create-safe-16-32-64-bit-accessors-for-reading-from-.patch
  5. 27
      SOURCES/0005-fix-bug-in-md5-code.patch
  6. 163
      SOURCES/0006-use-libgcrypt-for-MD5.patch
  7. 235
      SOURCES/0007-URL-encoded-Targetnames.patch
  8. 539
      SOURCES/0008-SCSI-add-a-safe-function-to-read-a-byte-from-the-dat.patch
  9. 114
      SOURCES/0009-scsi-lowlevel-do-not-use-unsafe-pointer-casts.patch
  10. 27
      SOURCES/0010-Add-a-cast-to-ssize_t.patch
  11. 26
      SOURCES/0011-do-not-build-test-tool.patch
  12. 25
      SOURCES/0012-bump-soname.patch
  13. 23
      SOURCES/0013-disable-ld_iscsi.patch
  14. 30
      SOURCES/0014-fix-another-aliasing-problem.patch
  15. 174
      SOURCES/0015-fix-arm-aliasing-problem.patch
  16. 78
      SOURCES/0016-avoid-casting-struct-sockaddr.patch
  17. 91
      SOURCES/0018-cleanup-rename-pdu-written.patch
  18. 155
      SOURCES/0019-fix-iovec-short-reads.patch
  19. 63
      SOURCES/0020-iscsi_reconnect-Fix-a-use-after-free.patch
  20. 38
      SOURCES/0021-Dont-reference-pdu-after-it-has-been-freed.patch
  21. 35
      SOURCES/0022-lib-Make-scsi_free_scsi_task-accept-a-NULL-task-pointer.patch
  22. 103
      SOURCES/0023-lib-Fix-a-memory-leak-in-scsi_cdb_persistent_reserve_out.patch
  23. 77
      SOURCES/0024-reconnect-do-not-initialize-iscsi-to-old_iscsi-use-old_iscsi-if-appropriate.patch
  24. 31
      SOURCES/0025-log-failures-typically-malloc-of-iscsi_create_context-during-reconnect.patch
  25. 27
      SOURCES/0026-exit-after-malloc-failure-when-allocating-sense-data-blob.patch
  26. 79
      SOURCES/0027-do-not-test-arrays-against-NULL.patch
  27. 40
      SOURCES/0028-handle-bad-iscsi--fd-in-iscsi_service.patch
  28. 145
      SOURCES/0029-rework-login-and-discovery-code-to-avoid-strlen-beyond-end-of-data.patch
  29. 36
      SOURCES/0030-check-for-a-target-being-there-before-processing-TargetAddress.patch
  30. 89
      SOURCES/0031-fix-CHAP-authentication.patch
  31. 81
      SOURCES/libiscsi-Discovery-return-multiple-portals-for-the-same-disco.patch
  32. 45
      SOURCES/libiscsi-iscsi-ls-skip-link-local-IPv6-addresses.patch
  33. 206
      SPECS/libiscsi.spec

36
SOURCES/0001-do-not-reconnect-if-reconnect-is-already-defered.patch

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
From 327b51ed5b2bdf0a4fc0b50a9cdd8c1f4993e49a Mon Sep 17 00:00:00 2001
From: Peter Lieven <pl@kamp.de>
Date: Mon, 11 Mar 2013 08:44:11 +0100
Subject: [RHEL7 libiscsi PATCH 01/18] do not reconnect if reconnect is already defered

If the amount of reconnects is limited with iscsi_set_reconnect_max_retries()
it might happen that iscsi_reconnect is called while there is already a deferred
reconnect.

Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from upstream commit 327b51ed5b2bdf0a4fc0b50a9cdd8c1f4993e49a)
---
lib/connect.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/lib/connect.c b/lib/connect.c
index 86a60f8..d3fa9d1 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -219,6 +219,12 @@ int iscsi_reconnect(struct iscsi_context *old_iscsi)
{
struct iscsi_context *iscsi = old_iscsi;
+ /* if there is already a deferred reconnect do not try again */
+ if (iscsi->reconnect_deferred) {
+ ISCSI_LOG(iscsi, 2, "reconnect initiated, but reconnect is already deferred");
+ return -1;
+ }
+
ISCSI_LOG(iscsi, 2, "reconnect initiated");
/* This is mainly for tests, where we do not want to automatically
--
1.8.1.4

31
SOURCES/0002-fix-leak-of-iscsi_context-in-iscsi_reconnect.patch

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
From 5a94d5d73a18369e6f7b7c54674dc20b9c7d0a8e Mon Sep 17 00:00:00 2001
From: Peter Lieven <pl@kamp.de>
Date: Mon, 11 Mar 2013 08:51:18 +0100
Subject: [RHEL7 libiscsi PATCH 02/18] fix leak of iscsi_context in iscsi_reconnect

in case the maximum number of reconnects is limited with
iscsi_set_reconnect_max_retries() the an iscsi_context
is leaked if the limit is exhausted.

Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from upstream commit 5a94d5d73a18369e6f7b7c54674dc20b9c7d0a8e)
---
lib/connect.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/lib/connect.c b/lib/connect.c
index d3fa9d1..7429496 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -277,6 +277,7 @@ try_again:
if (iscsi_full_connect_sync(iscsi, iscsi->portal, iscsi->lun) != 0) {
if (iscsi->reconnect_max_retries != -1 && retry >= iscsi->reconnect_max_retries) {
iscsi_defer_reconnect(old_iscsi);
+ iscsi_destroy_context(iscsi);
return -1;
}
int backoff=retry;
--
1.8.1.4

77
SOURCES/0003-Add-ASCQ-codes-related-to-thin-provisioning.patch

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
From 80ef1807ef0c11ec5940d5763b12f3c0d4b6d32e Mon Sep 17 00:00:00 2001
From: Peter Lieven <pl@kamp.de>
Date: Mon, 11 Mar 2013 12:13:42 +0100
Subject: [RHEL7 libiscsi PATCH 03/18] Add ASCQ codes related to thin-provisioning

Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from upstream commit 80ef1807ef0c11ec5940d5763b12f3c0d4b6d32e)
---
include/scsi-lowlevel.h | 31 +++++++++++++++++--------------
lib/scsi-lowlevel.c | 6 ++++++
2 files changed, 23 insertions(+), 14 deletions(-)

diff --git a/include/scsi-lowlevel.h b/include/scsi-lowlevel.h
index cd1abd4..07d39be 100644
--- a/include/scsi-lowlevel.h
+++ b/include/scsi-lowlevel.h
@@ -144,20 +144,23 @@ enum scsi_sense_key {
EXTERN const char *scsi_sense_key_str(int key);
/* ascq */
-#define SCSI_SENSE_ASCQ_MISCOMPARE_DURING_VERIFY 0x1d00
-#define SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE 0x2000
-#define SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE 0x2100
-#define SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB 0x2400
-#define SCSI_SENSE_ASCQ_LOGICAL_UNIT_NOT_SUPPORTED 0x2500
-#define SCSI_SENSE_ASCQ_WRITE_PROTECTED 0x2700
-#define SCSI_SENSE_ASCQ_BUS_RESET 0x2900
-#define SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED 0x2a09
-#define SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT 0x3a00
-#define SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_CLOSED 0x3a01
-#define SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_OPEN 0x3a02
-#define SCSI_SENSE_ASCQ_INTERNAL_TARGET_FAILURE 0x4400
-#define SCSI_SENSE_ASCQ_MEDIUM_LOAD_OR_EJECT_FAILED 0x5300
-#define SCSI_SENSE_ASCQ_MEDIUM_REMOVAL_PREVENTED 0x5302
+#define SCSI_SENSE_ASCQ_MISCOMPARE_DURING_VERIFY 0x1d00
+#define SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE 0x2000
+#define SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE 0x2100
+#define SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB 0x2400
+#define SCSI_SENSE_ASCQ_LOGICAL_UNIT_NOT_SUPPORTED 0x2500
+#define SCSI_SENSE_ASCQ_WRITE_PROTECTED 0x2700
+#define SCSI_SENSE_ASCQ_BUS_RESET 0x2900
+#define SCSI_SENSE_ASCQ_MODE_PARAMETERS_CHANGED 0x2a01
+#define SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED 0x2a09
+#define SCSI_SENSE_ASCQ_THIN_PROVISION_SOFT_THRES_REACHED 0x3807
+#define SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT 0x3a00
+#define SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_CLOSED 0x3a01
+#define SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_OPEN 0x3a02
+#define SCSI_SENSE_ASCQ_INQUIRY_DATA_HAS_CHANGED 0x3f03
+#define SCSI_SENSE_ASCQ_INTERNAL_TARGET_FAILURE 0x4400
+#define SCSI_SENSE_ASCQ_MEDIUM_LOAD_OR_EJECT_FAILED 0x5300
+#define SCSI_SENSE_ASCQ_MEDIUM_REMOVAL_PREVENTED 0x5302
EXTERN const char *scsi_sense_ascq_str(int ascq);
diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c
index b6af650..b49e873 100644
--- a/lib/scsi-lowlevel.c
+++ b/lib/scsi-lowlevel.c
@@ -149,8 +149,14 @@ scsi_sense_ascq_str(int ascq)
"MEDIUM_NOT_PRESENT-TRAY_OPEN"},
{SCSI_SENSE_ASCQ_BUS_RESET,
"BUS_RESET"},
+ {SCSI_SENSE_ASCQ_MODE_PARAMETERS_CHANGED,
+ "MODE PARAMETERS CHANGED"},
{SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED,
"CAPACITY_DATA_HAS_CHANGED"},
+ {SCSI_SENSE_ASCQ_THIN_PROVISION_SOFT_THRES_REACHED,
+ "THIN PROVISIONING SOFT THRESHOLD REACHED"},
+ {SCSI_SENSE_ASCQ_INQUIRY_DATA_HAS_CHANGED,
+ "INQUIRY DATA HAS CHANGED"},
{SCSI_SENSE_ASCQ_INTERNAL_TARGET_FAILURE,
"INTERNAL_TARGET_FAILURE"},
{SCSI_SENSE_ASCQ_MISCOMPARE_DURING_VERIFY,
--
1.8.1.4

388
SOURCES/0004-Create-safe-16-32-64-bit-accessors-for-reading-from-.patch

@ -0,0 +1,388 @@ @@ -0,0 +1,388 @@
From d280ce8ad742426bebe610ebfd8559b46876f4ee Mon Sep 17 00:00:00 2001
From: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Date: Mon, 22 Apr 2013 22:11:53 -0700
Subject: [RHEL7 libiscsi PATCH 04/18] Create safe 16/32/64 bit accessors for reading from the
datain buffer and use it throughout the scsi lowlevel file.

We probably want a safe accessor for byte access to at some stage.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from upstream commit d280ce8ad742426bebe610ebfd8559b46876f4ee)
---
lib/scsi-lowlevel.c | 154 +++++++++++++++++++++++++++++++++-------------------
1 file changed, 98 insertions(+), 56 deletions(-)

diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c
index c517d57..77c0bb6 100644
--- a/lib/scsi-lowlevel.c
+++ b/lib/scsi-lowlevel.c
@@ -232,6 +232,48 @@ scsi_get_uint16(const unsigned char *c)
return ntohs(*(uint16_t *)c);
}
+static inline uint64_t
+task_get_uint64(struct scsi_task *task, int offset)
+{
+ if (offset <= task->datain.size - 8) {
+ const unsigned char *c = &task->datain.data[offset];
+ uint64_t val;
+
+ val = ntohl(*(uint32_t *)c);
+ val <<= 32;
+ c += 4;
+ val |= ntohl(*(uint32_t *)c);
+
+ return val;
+ } else {
+ return 0;
+ }
+}
+
+static inline uint32_t
+task_get_uint32(struct scsi_task *task, int offset)
+{
+ if (offset <= task->datain.size - 4) {
+ const unsigned char *c = &task->datain.data[offset];
+
+ return ntohl(*(uint32_t *)c);
+ } else {
+ return 0;
+ }
+}
+
+static inline uint16_t
+task_get_uint16(struct scsi_task *task, int offset)
+{
+ if (offset <= task->datain.size - 2) {
+ const unsigned char *c = &task->datain.data[offset];
+
+ return ntohs(*(uint16_t *)c);
+ } else {
+ return 0;
+ }
+}
+
inline void
scsi_set_uint64(unsigned char *c, uint64_t v)
{
@@ -319,7 +361,7 @@ scsi_reportluns_datain_getfullsize(struct scsi_task *task)
{
uint32_t list_size;
- list_size = scsi_get_uint32(&task->datain.data[0]) + 8;
+ list_size = task_get_uint32(task, 0) + 8;
return list_size;
}
@@ -338,7 +380,7 @@ scsi_reportluns_datain_unmarshall(struct scsi_task *task)
return NULL;
}
- list_size = scsi_get_uint32(&task->datain.data[0]) + 8;
+ list_size = task_get_uint32(task, 0) + 8;
if (list_size < task->datain.size) {
return NULL;
}
@@ -352,7 +394,7 @@ scsi_reportluns_datain_unmarshall(struct scsi_task *task)
list->num = num_luns;
for (i = 0; i < num_luns; i++) {
- list->luns[i] = scsi_get_uint16(&task->datain.data[i*8+8]);
+ list->luns[i] = task_get_uint16(task, i * 8 + 8);
}
return list;
@@ -442,7 +484,7 @@ scsi_readtoc_datain_getfullsize(struct scsi_task *task)
{
uint16_t toc_data_len;
- toc_data_len = scsi_get_uint16(&task->datain.data[0]) + 2;
+ toc_data_len = task_get_uint16(task, 0) + 2;
return toc_data_len;
}
@@ -465,7 +507,7 @@ scsi_readtoc_desc_unmarshall(struct scsi_task *task, struct scsi_readtoc_list *l
list->desc[i].desc.toc.track
= task->datain.data[4+8*i+2];
list->desc[i].desc.toc.lba
- = scsi_get_uint32(&task->datain.data[4+8*i+4]);
+ = task_get_uint32(task, 4 + 8 * i + 4);
break;
case SCSI_READ_SESSION_INFO:
list->desc[i].desc.ses.adr
@@ -475,7 +517,7 @@ scsi_readtoc_desc_unmarshall(struct scsi_task *task, struct scsi_readtoc_list *l
list->desc[i].desc.ses.first_in_last
= task->datain.data[4+8*i+2];
list->desc[i].desc.ses.lba
- = scsi_get_uint32(&task->datain.data[4+8*i+4]);
+ = task_get_uint32(task, 4 + 8 * i + 4);
break;
case SCSI_READ_FULL_TOC:
list->desc[i].desc.full.session
@@ -610,22 +652,22 @@ scsi_serviceactionin_datain_unmarshall(struct scsi_task *task)
if (rc16 == NULL) {
return NULL;
}
- rc16->returned_lba = scsi_get_uint32(&task->datain.data[0]);
- rc16->returned_lba = (rc16->returned_lba << 32) | scsi_get_uint32(&task->datain.data[4]);
- rc16->block_length = scsi_get_uint32(&task->datain.data[8]);
+ rc16->returned_lba = task_get_uint32(task, 0);
+ rc16->returned_lba = (rc16->returned_lba << 32) | task_get_uint32(task, 4);
+ rc16->block_length = task_get_uint32(task, 8);
rc16->p_type = (task->datain.data[12] >> 1) & 0x07;
rc16->prot_en = task->datain.data[12] & 0x01;
rc16->p_i_exp = (task->datain.data[13] >> 4) & 0x0f;
rc16->lbppbe = task->datain.data[13] & 0x0f;
rc16->lbpme = !!(task->datain.data[14] & 0x80);
rc16->lbprz = !!(task->datain.data[14] & 0x40);
- rc16->lalba = scsi_get_uint16(&task->datain.data[14]) & 0x3fff;
+ rc16->lalba = task_get_uint16(task, 14) & 0x3fff;
return rc16;
}
case SCSI_GET_LBA_STATUS: {
struct scsi_get_lba_status *gls = scsi_malloc(task,
sizeof(*gls));
- int32_t len = scsi_get_uint32(&task->datain.data[0]);
+ int32_t len = task_get_uint32(task, 0);
int i;
if (gls == NULL) {
@@ -646,11 +688,11 @@ scsi_serviceactionin_datain_unmarshall(struct scsi_task *task)
}
for (i = 0; i < (int)gls->num_descriptors; i++) {
- gls->descriptors[i].lba = scsi_get_uint32(&task->datain.data[8 + i * sizeof(struct scsi_lba_status_descriptor) + 0]);
+ gls->descriptors[i].lba = task_get_uint32(task, 8 + i * sizeof(struct scsi_lba_status_descriptor) + 0);
gls->descriptors[i].lba <<= 32;
- gls->descriptors[i].lba |= scsi_get_uint32(&task->datain.data[8 + i * sizeof(struct scsi_lba_status_descriptor) + 4]);
+ gls->descriptors[i].lba |= task_get_uint32(task, 8 + i * sizeof(struct scsi_lba_status_descriptor) + 4);
- gls->descriptors[i].num_blocks = scsi_get_uint32(&task->datain.data[8 + i * sizeof(struct scsi_lba_status_descriptor) + 8]);
+ gls->descriptors[i].num_blocks = task_get_uint32(task, 8 + i * sizeof(struct scsi_lba_status_descriptor) + 8);
gls->descriptors[i].provisioning = task->datain.data[8 + i * sizeof(struct scsi_lba_status_descriptor) + 12] & 0x0f;
}
@@ -676,7 +718,7 @@ scsi_persistentreservein_datain_getfullsize(struct scsi_task *task)
{
switch (scsi_persistentreservein_sa(task)) {
case SCSI_PERSISTENT_RESERVE_READ_KEYS:
- return scsi_get_uint32(&task->datain.data[4]) + 8;
+ return task_get_uint32(task, 4) + 8;
case SCSI_PERSISTENT_RESERVE_READ_RESERVATION:
return 8;
case SCSI_PERSISTENT_RESERVE_REPORT_CAPABILITIES:
@@ -696,24 +738,24 @@ scsi_persistentreservein_datain_unmarshall(struct scsi_task *task)
switch (scsi_persistentreservein_sa(task)) {
case SCSI_PERSISTENT_RESERVE_READ_KEYS:
- i = scsi_get_uint32(&task->datain.data[4]);
+ i = task_get_uint32(task, 4);
rk = scsi_malloc(task, offsetof(struct scsi_persistent_reserve_in_read_keys, keys) + i);
if (rk == NULL) {
return NULL;
}
- rk->prgeneration = scsi_get_uint32(&task->datain.data[0]);
- rk->additional_length = scsi_get_uint32(&task->datain.data[4]);
+ rk->prgeneration = task_get_uint32(task, 0);
+ rk->additional_length = task_get_uint32(task, 4);
rk->num_keys = rk->additional_length / 8;
for (i = 0; i < (int)rk->num_keys; i++) {
- rk->keys[i] = scsi_get_uint64(&task->datain.data[8 + i * 8]);
+ rk->keys[i] = task_get_uint64(task, 8 + i * 8);
}
return rk;
case SCSI_PERSISTENT_RESERVE_READ_RESERVATION: {
size_t alloc_sz;
- i = scsi_get_uint32(&task->datain.data[4]);
+ i = task_get_uint32(task, 4);
alloc_sz = offsetof(
struct scsi_persistent_reserve_in_read_reservation,
reserved) + i;
@@ -723,12 +765,12 @@ scsi_persistentreservein_datain_unmarshall(struct scsi_task *task)
return NULL;
}
memset(rr, 0, alloc_sz);
- rr->prgeneration = scsi_get_uint32(&task->datain.data[0]);
+ rr->prgeneration = task_get_uint32(task, 0);
if (i > 0) {
rr->reserved = 1;
rr->reservation_key =
- scsi_get_uint64(&task->datain.data[8]);
+ task_get_uint64(task, 8);
rr->pr_type = task->datain.data[21] & 0xff;
}
@@ -739,14 +781,14 @@ scsi_persistentreservein_datain_unmarshall(struct scsi_task *task)
if (rc == NULL) {
return NULL;
}
- rc->length = scsi_get_uint16(&task->datain.data[0]);
+ rc->length = task_get_uint16(task, 0);
rc->crh = !!(task->datain.data[2] & 0x10);
rc->sip_c = !!(task->datain.data[2] & 0x08);
rc->atp_c = !!(task->datain.data[2] & 0x04);
rc->ptpl_c = !!(task->datain.data[2] & 0x01);
rc->tmv = !!(task->datain.data[3] & 0x80);
rc->allow_commands = task->datain.data[3] >> 4;
- rc->persistent_reservation_type_mask = scsi_get_uint16(&task->datain.data[4]);
+ rc->persistent_reservation_type_mask = task_get_uint16(task, 4);
return rc;
default:
@@ -776,7 +818,7 @@ scsi_maintenancein_datain_getfullsize(struct scsi_task *task)
switch (scsi_maintenancein_sa(task)) {
case SCSI_REPORT_SUPPORTED_OP_CODES:
- return scsi_get_uint32(&task->datain.data[0]) + 4;
+ return task_get_uint32(task, 0) + 4;
default:
return -1;
}
@@ -799,7 +841,7 @@ scsi_maintenancein_datain_unmarshall(struct scsi_task *task)
return NULL;
}
- len = scsi_get_uint32(&task->datain.data[0]);
+ len = task_get_uint32(task, 0);
rsoc = scsi_malloc(task, sizeof(struct scsi_report_supported_op_codes) + len);
if (rsoc == NULL) {
return NULL;
@@ -900,8 +942,8 @@ scsi_readcapacity10_datain_unmarshall(struct scsi_task *task)
return NULL;
}
- rc10->lba = scsi_get_uint32(&task->datain.data[0]);
- rc10->block_size = scsi_get_uint32(&task->datain.data[4]);
+ rc10->lba = task_get_uint32(task, 0);
+ rc10->block_size = task_get_uint32(task, 4);
return rc10;
}
@@ -972,7 +1014,7 @@ scsi_inquiry_datain_getfullsize(struct scsi_task *task)
case SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION:
case SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS:
case SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING:
- return scsi_get_uint16(&task->datain.data[2]) + 4;
+ return task_get_uint16(task, 2) + 4;
default:
return -1;
}
@@ -1079,7 +1120,7 @@ scsi_inquiry_unmarshall_device_identification(struct scsi_task *task)
{
struct scsi_inquiry_device_identification *inq = scsi_malloc(task,
sizeof(*inq));
- int remaining = scsi_get_uint16(&task->datain.data[2]);
+ int remaining = task_get_uint16(task, 2);
unsigned char *dptr;
if (inq == NULL) {
@@ -1148,17 +1189,18 @@ scsi_inquiry_unmarshall_block_limits(struct scsi_task *task)
inq->wsnz = task->datain.data[4] & 0x01;
inq->max_cmp = task->datain.data[5];
- inq->opt_gran = scsi_get_uint16(&task->datain.data[6]);
- inq->max_xfer_len = scsi_get_uint32(&task->datain.data[8]);
- inq->opt_xfer_len = scsi_get_uint32(&task->datain.data[12]);
- inq->max_prefetch = scsi_get_uint32(&task->datain.data[16]);
- inq->max_unmap = scsi_get_uint32(&task->datain.data[20]);
- inq->max_unmap_bdc = scsi_get_uint32(&task->datain.data[24]);
- inq->opt_unmap_gran = scsi_get_uint32(&task->datain.data[28]);
+ inq->opt_gran = task_get_uint16(task, 6);
+ inq->max_xfer_len = task_get_uint32(task, 8);
+ inq->opt_xfer_len = task_get_uint32(task, 12);
+ inq->max_prefetch = task_get_uint32(task, 16);
+ inq->max_unmap = task_get_uint32(task, 20);
+ inq->max_unmap_bdc = task_get_uint32(task, 24);
+ inq->opt_unmap_gran = task_get_uint32(task, 28);
inq->ugavalid = !!(task->datain.data[32]&0x80);
- inq->unmap_gran_align = scsi_get_uint32(&task->datain.data[32]) & 0x7fffffff;
- inq->max_ws_len = scsi_get_uint32(&task->datain.data[36]);
- inq->max_ws_len = (inq->max_ws_len << 32) | scsi_get_uint32(&task->datain.data[40]);
+ inq->unmap_gran_align = task_get_uint32(task, 32) & 0x7fffffff;
+ inq->max_ws_len = task_get_uint32(task, 36);
+ inq->max_ws_len = (inq->max_ws_len << 32)
+ | task_get_uint32(task, 40);
return inq;
}
@@ -1175,7 +1217,7 @@ scsi_inquiry_unmarshall_block_device_characteristics(struct scsi_task *task)
inq->device_type = task->datain.data[0]&0x1f;
inq->pagecode = task->datain.data[1];
- inq->medium_rotation_rate = scsi_get_uint16(&task->datain.data[4]);
+ inq->medium_rotation_rate = task_get_uint16(task, 4);
return inq;
}
@@ -2040,10 +2082,10 @@ scsi_parse_mode_caching(struct scsi_task *task, int pos, struct scsi_mode_page *
mp->caching.demand_read_retention_priority = (task->datain.data[pos+1] >> 4) & 0x0f;
mp->caching.write_retention_priority = task->datain.data[pos+1] & 0x0f;
- mp->caching.disable_prefetch_transfer_length = scsi_get_uint16(&task->datain.data[pos+2]);
- mp->caching.minimum_prefetch = scsi_get_uint16(&task->datain.data[pos+4]);
- mp->caching.maximum_prefetch = scsi_get_uint16(&task->datain.data[pos+6]);
- mp->caching.maximum_prefetch_ceiling = scsi_get_uint16(&task->datain.data[pos+8]);
+ mp->caching.disable_prefetch_transfer_length = task_get_uint16(task, pos + 2);
+ mp->caching.minimum_prefetch = task_get_uint16(task, pos + 4);
+ mp->caching.maximum_prefetch = task_get_uint16(task, pos + 6);
+ mp->caching.maximum_prefetch_ceiling = task_get_uint16(task, pos + 8);
mp->caching.fsw = task->datain.data[pos+10] & 0x80;
mp->caching.lbcss = task->datain.data[pos+10] & 0x40;
@@ -2051,7 +2093,7 @@ scsi_parse_mode_caching(struct scsi_task *task, int pos, struct scsi_mode_page *
mp->caching.nv_dis = task->datain.data[pos+10] & 0x01;
mp->caching.number_of_cache_segments = task->datain.data[pos+11];
- mp->caching.cache_segment_size = scsi_get_uint16(&task->datain.data[pos+12]);
+ mp->caching.cache_segment_size = task_get_uint16(task, pos + 12);
}
static void
@@ -2059,15 +2101,15 @@ scsi_parse_mode_disconnect_reconnect(struct scsi_task *task, int pos, struct scs
{
mp->disconnect_reconnect.buffer_full_ratio = task->datain.data[pos];
mp->disconnect_reconnect.buffer_empty_ratio = task->datain.data[pos+1];
- mp->disconnect_reconnect.bus_inactivity_limit = scsi_get_uint16(&task->datain.data[pos+2]);
- mp->disconnect_reconnect.disconnect_time_limit = scsi_get_uint16(&task->datain.data[pos+4]);
- mp->disconnect_reconnect.connect_time_limit = scsi_get_uint16(&task->datain.data[pos+6]);
- mp->disconnect_reconnect.maximum_burst_size = scsi_get_uint16(&task->datain.data[pos+8]);
+ mp->disconnect_reconnect.bus_inactivity_limit = task_get_uint16(task, pos + 2);
+ mp->disconnect_reconnect.disconnect_time_limit = task_get_uint16(task, pos + 4);
+ mp->disconnect_reconnect.connect_time_limit = task_get_uint16(task, pos + 6);
+ mp->disconnect_reconnect.maximum_burst_size = task_get_uint16(task, pos + 8);
mp->disconnect_reconnect.emdp = task->datain.data[pos+10] & 0x80;
mp->disconnect_reconnect.fair_arbitration = (task->datain.data[pos+10]>>4) & 0x0f;
mp->disconnect_reconnect.dimm = task->datain.data[pos+10] & 0x08;
mp->disconnect_reconnect.dtdc = task->datain.data[pos+10] & 0x07;
- mp->disconnect_reconnect.first_burst_size = scsi_get_uint16(&task->datain.data[pos+12]);
+ mp->disconnect_reconnect.first_burst_size = task_get_uint16(task, pos + 12);
}
static void
@@ -2081,8 +2123,8 @@ scsi_parse_mode_informational_exceptions_control(struct scsi_task *task, int pos
mp->iec.ebackerr = task->datain.data[pos] & 0x02;
mp->iec.logerr = task->datain.data[pos] & 0x01;
mp->iec.mrie = task->datain.data[pos+1] & 0x0f;
- mp->iec.interval_timer = scsi_get_uint32(&task->datain.data[pos+2]);
- mp->iec.report_count = scsi_get_uint32(&task->datain.data[pos+6]);
+ mp->iec.interval_timer = task_get_uint32(task, pos + 2);
+ mp->iec.report_count = task_get_uint32(task, pos + 6);
}
@@ -2129,7 +2171,7 @@ scsi_modesense_datain_unmarshall(struct scsi_task *task)
if (mp->spf) {
mp->subpage_code = task->datain.data[pos++];
- mp->len = scsi_get_uint16(&task->datain.data[pos]);
+ mp->len = task_get_uint16(task, pos);
pos += 2;
} else {
mp->subpage_code = 0;
--
1.8.1.4

27
SOURCES/0005-fix-bug-in-md5-code.patch

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
From cc742279d0c83523f03a93882fce6bc820851750 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 3 May 2013 12:43:50 +0200
Subject: [RHEL7 libiscsi PATCH 05/18] fix bug in md5 code

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from upstream commit cc742279d0c83523f03a93882fce6bc820851750)
---
lib/md5.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/md5.c b/lib/md5.c
index daab76c..893956d 100644
--- a/lib/md5.c
+++ b/lib/md5.c
@@ -134,7 +134,7 @@ MD5Final(md5byte digest[16], struct MD5Context *ctx)
byteSwap(ctx->buf, 4);
memcpy(digest, ctx->buf, 16);
- memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
+ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
}
#ifndef ASM_MD5
--
1.8.1.4

163
SOURCES/0006-use-libgcrypt-for-MD5.patch

@ -0,0 +1,163 @@ @@ -0,0 +1,163 @@
From bcb2950d8ded9ec3a2e3ada8428aeaf725ea2171 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 3 May 2013 12:47:12 +0200
Subject: [RHEL7 libiscsi PATCH 06/18] use libgcrypt for MD5

This makes sure that CHAP authentication is disabled if the system
is running in FIPS 140-2 mode. MD5 is not a secure algorithm according
to the standard.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from upstream commit bcb2950d8ded9ec3a2e3ada8428aeaf725ea2171)
---
Makefile.am | 6 +++++-
configure.ac | 3 +++
lib/login.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------
3 files changed, 60 insertions(+), 9 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 5fea7c8..9a8b2b4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -34,10 +34,14 @@ dist_noinst_DATA = lib/libiscsi.syms
lib_LTLIBRARIES = lib/libiscsi.la
lib_libiscsi_la_SOURCES = \
lib/connect.c lib/crc32c.c lib/discovery.c lib/init.c \
- lib/login.c lib/md5.c lib/nop.c lib/pdu.c lib/iscsi-command.c \
+ lib/login.c lib/nop.c lib/pdu.c lib/iscsi-command.c \
lib/scsi-lowlevel.c lib/socket.c lib/sync.c lib/task_mgmt.c \
lib/logging.c
+if !HAVE_LIBGCRYPT
+lib_libiscsi_la_SOURCES += lib/md5.c
+endif
+
SONAME=$(firstword $(subst ., ,$(VERSION)))
SOREL=$(shell printf "%d%02d%02d" $(subst ., ,$(VERSION)))
lib_libiscsi_la_LDFLAGS = \
diff --git a/configure.ac b/configure.ac
index 0b45f91..9d06e3a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -18,6 +18,9 @@ AC_SUBST(WARN_CFLAGS)
AC_CONFIG_HEADER(config.h)
+AC_CHECK_LIB([gcrypt], [gcry_control])
+AM_CONDITIONAL([HAVE_LIBGCRYPT], [test $ac_cv_lib_gcrypt_gcry_control = yes])
+
AC_CACHE_CHECK([for sin_len in sock],libiscsi_cv_HAVE_SOCK_SIN_LEN,[
AC_TRY_COMPILE([#include <sys/types.h>
#include <sys/socket.h>
diff --git a/lib/login.c b/lib/login.c
index 07ca3dd..29fe4b3 100644
--- a/lib/login.c
+++ b/lib/login.c
@@ -35,13 +35,18 @@
#include <arpa/inet.h>
#endif
+#include "config.h"
#include <stdio.h>
+#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "iscsi.h"
#include "iscsi-private.h"
#include "scsi-lowlevel.h"
#include "md5.h"
+#ifdef HAVE_LIBGCRYPT
+#include <gcrypt.h>
+#endif
static int
iscsi_login_add_initiatorname(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
@@ -628,6 +632,41 @@ i2h(int i)
return i + '0';
}
+#ifndef HAVE_LIBGCRYPT
+typedef struct MD5Context *gcry_md_hd_t;
+#define gcry_md_write MD5Update
+#define GCRY_MD_MD5 1
+
+static inline void gcry_md_open(gcry_md_hd_t *hd, int algo, unsigned int flags)
+{
+ assert(algo == GCRY_MD_MD5 && flags == 0);
+ *hd = malloc(sizeof(struct MD5Context));
+ if (*hd) {
+ MD5Init(*hd);
+ }
+}
+
+static inline void gcry_md_putc(gcry_md_hd_t h, unsigned char c)
+{
+ MD5Update(h, &c, 1);
+}
+
+static inline char *gcry_md_read(gcry_md_hd_t h, int algo)
+{
+ unsigned char digest[16];
+ assert(algo == 0 || algo == GCRY_MD_MD5);
+
+ MD5Final(digest, h);
+ return memcpy(h->buf, digest, sizeof(digest));
+}
+
+static inline void gcry_md_close(gcry_md_hd_t h)
+{
+ memset(h, 0, sizeof(*h));
+ free(h);
+}
+#endif
+
static int
iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
{
@@ -635,7 +674,7 @@ iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu
char * strp;
unsigned char c, cc[2];
unsigned char digest[16];
- struct MD5Context ctx;
+ gcry_md_hd_t ctx;
int i;
if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_SECNEG
@@ -643,22 +682,27 @@ iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu
return 0;
}
+ gcry_md_open(&ctx, GCRY_MD_MD5, 0);
+ if (!ctx) {
+ iscsi_set_error(iscsi, "Cannot create MD5 algorithm");
+ return -1;
+ }
+
if (!iscsi->chap_c[0]) {
iscsi_set_error(iscsi, "No CHAP challenge found");
return -1;
}
- MD5Init(&ctx);
- c = iscsi->chap_i;
- MD5Update(&ctx, &c, 1);
- MD5Update(&ctx, (unsigned char *)iscsi->passwd, strlen(iscsi->passwd));
-
+ gcry_md_putc(ctx, iscsi->chap_i);
+ gcry_md_write(ctx, (unsigned char *)iscsi->passwd, strlen(iscsi->passwd));
+
strp = iscsi->chap_c;
while (*strp != 0) {
c = (h2i(strp[0]) << 4) | h2i(strp[1]);
strp += 2;
- MD5Update(&ctx, &c, 1);
+ gcry_md_putc(ctx, c);
}
- MD5Final(digest, &ctx);
+ memcpy(digest, gcry_md_read(ctx, 0), sizeof(digest));
+ gcry_md_close(ctx);
strncpy(str,"CHAP_R=0x",MAX_STRING_SIZE);
if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str))
--
1.8.1.4

235
SOURCES/0007-URL-encoded-Targetnames.patch

@ -0,0 +1,235 @@ @@ -0,0 +1,235 @@
From e061cba1b91650ab08ae8fa50e8cadb13ac3d97d Mon Sep 17 00:00:00 2001
From: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Date: Sun, 16 Jun 2013 11:35:14 -0700
Subject: [RHEL7 libiscsi PATCH 07/18] URL encoded Targetnames

Assume target names are URL encoded with '%' as the special character.

Any sequence of '%' followed by two bytes in the target name will be replaced
with the byte that the second two bytes represent in hexadecimal.

Example
iqn.ronnie.test%3A1234
will be translated to iqn.ronnie.test:1234

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from upstream commit e061cba1b91650ab08ae8fa50e8cadb13ac3d97d)

[The right thing to do here is probably to not use this simple-minded code
and use QEMU's URI parser. I need to find a testcase, then I will create
a bug. - Paolo]
---
include/iscsi.h | 12 ++++--
lib/init.c | 114 +++++++++++++++++++++++++++++++++++++++-----------------
lib/login.c | 1 +
3 files changed, 88 insertions(+), 39 deletions(-)

diff --git a/include/iscsi.h b/include/iscsi.h
index f14d404..a4ed932 100644
--- a/include/iscsi.h
+++ b/include/iscsi.h
@@ -125,6 +125,10 @@ iscsi_set_initial_r2t(struct iscsi_context *iscsi, enum iscsi_initial_r2t initia
* iSCSI URL format :
* iscsi://[<username>[%<password>]@]<host>[:<port>]/<target-iqn>/<lun>
*
+ * Target names are url encoded with '%' as a special character.
+ * Example:
+ * "iqn.ronnie.test%3A1234" will be translated to "iqn.ronnie.test:1234"
+ *
* Function will return a pointer to an iscsi url structure if successful,
* or it will return NULL and set iscsi_get_error() accrodingly if there was a problem
* with the URL.
diff --git a/lib/init.c b/lib/init.c
index 18f3fb2..60a1b6d 100644
--- a/lib/init.c
+++ b/lib/init.c
@@ -358,6 +358,45 @@ iscsi_is_logged_in(struct iscsi_context *iscsi)
return iscsi->is_loggedin;
}
+static int
+h2i(int h)
+{
+ if (h >= 'a' && h <= 'f') {
+ return h - 'a' + 10;
+ }
+ if (h >= 'A' && h <= 'F') {
+ return h - 'A' + 10;
+ }
+ return h - '0';
+}
+
+static void
+iscsi_decode_url_string(char *str)
+{
+ while (*str) {
+ char *tmp = str;
+ char c;
+
+ if (*str++ != '%') {
+ continue;
+ }
+
+ if (*str == 0) {
+ return;
+ }
+ c = h2i(*str++) << 4;
+
+ if (*str == 0) {
+ return;
+ }
+ c |= h2i(*str++);
+
+ *tmp++ = c;
+ memmove(tmp, str, strlen(str));
+ tmp[strlen(str)] = 0;
+ }
+}
+
struct iscsi_url *
iscsi_parse_url(struct iscsi_context *iscsi, const char *url, int full)
{
@@ -373,15 +412,18 @@ iscsi_parse_url(struct iscsi_context *iscsi, const char *url, int full)
if (strncmp(url, "iscsi://", 8)) {
if (full) {
- iscsi_set_error(iscsi, "Invalid URL %s\niSCSI URL must be of "
- "the form: %s",url,ISCSI_URL_SYNTAX); }
- else {
- iscsi_set_error(iscsi, "Invalid URL %s\niSCSI Portal URL must be of "
- "the form: %s",url,ISCSI_PORTAL_URL_SYNTAX); }
+ iscsi_set_error(iscsi, "Invalid URL %s\niSCSI URL must "
+ "be of the form: %s",
+ url, ISCSI_URL_SYNTAX);
+ } else {
+ iscsi_set_error(iscsi, "Invalid URL %s\niSCSI Portal "
+ "URL must be of the form: %s",
+ url, ISCSI_PORTAL_URL_SYNTAX);
+ }
return NULL;
}
- strncpy(str,url + 8,MAX_STRING_SIZE);
+ strncpy(str,url + 8, MAX_STRING_SIZE);
portal = str;
user = getenv("LIBISCSI_CHAP_USERNAME");
@@ -406,56 +448,56 @@ iscsi_parse_url(struct iscsi_context *iscsi, const char *url, int full)
if (full) {
target = strchr(portal, '/');
if (target == NULL) {
- iscsi_set_error(iscsi, "Invalid URL %s\nCould not parse "
- "'<target-iqn>'\niSCSI URL must be of the "
- "form: %s",
- url,
- ISCSI_URL_SYNTAX);
+ iscsi_set_error(iscsi, "Invalid URL %s\nCould not "
+ "parse '<target-iqn>'\niSCSI URL must be of "
+ "the form: %s",
+ url, ISCSI_URL_SYNTAX);
return NULL;
}
*target++ = 0;
if (*target == 0) {
- iscsi_set_error(iscsi, "Invalid URL %s\nCould not parse "
- "<target-iqn>\n"
- "iSCSI URL must be of the form: %s",
- url,
- ISCSI_URL_SYNTAX);
+ iscsi_set_error(iscsi, "Invalid URL %s\nCould not "
+ "parse <target-iqn>\niSCSI URL must be of the "
+ "form: %s",
+ url, ISCSI_URL_SYNTAX);
return NULL;
}
lun = strchr(target, '/');
if (lun == NULL) {
- iscsi_set_error(iscsi, "Invalid URL %s\nCould not parse <lun>\n"
- "iSCSI URL must be of the form: %s",
- url,
- ISCSI_URL_SYNTAX);
+ iscsi_set_error(iscsi, "Invalid URL %s\nCould not "
+ "parse <lun>\niSCSI URL must be of the form: "
+ "%s",
+ url, ISCSI_URL_SYNTAX);
return NULL;
}
*lun++ = 0;
l = strtol(lun, &tmp, 10);
if (*lun == 0 || *tmp != 0) {
- iscsi_set_error(iscsi, "Invalid URL %s\nCould not parse <lun>\n"
- "iSCSI URL must be of the form: %s",
- url,
- ISCSI_URL_SYNTAX);
+ iscsi_set_error(iscsi, "Invalid URL %s\nCould not "
+ "parse <lun>\niSCSI URL must be of the form: "
+ "%s",
+ url, ISCSI_URL_SYNTAX);
return NULL;
}
- }
- else
- {
+ } else {
tmp=strchr(portal,'/');
- if (tmp) *tmp=0;
+ if (tmp) {
+ *tmp=0;
+ }
}
- if (iscsi != NULL)
+ if (iscsi != NULL) {
iscsi_url = iscsi_malloc(iscsi, sizeof(struct iscsi_url));
- else
+ } else {
iscsi_url = malloc(sizeof(struct iscsi_url));
-
+ }
+
if (iscsi_url == NULL) {
- iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate iscsi_url structure");
+ iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate "
+ "iscsi_url structure");
return NULL;
}
memset(iscsi_url, 0, sizeof(struct iscsi_url));
@@ -464,15 +506,17 @@ iscsi_parse_url(struct iscsi_context *iscsi, const char *url, int full)
strncpy(iscsi_url->portal,portal,MAX_STRING_SIZE);
if (user != NULL && passwd != NULL) {
- strncpy(iscsi_url->user,user,MAX_STRING_SIZE);
- strncpy(iscsi_url->passwd,passwd,MAX_STRING_SIZE);
+ strncpy(iscsi_url->user, user, MAX_STRING_SIZE);
+ strncpy(iscsi_url->passwd, passwd, MAX_STRING_SIZE);
}
if (full) {
- strncpy(iscsi_url->target,target,MAX_STRING_SIZE);
+ strncpy(iscsi_url->target, target, MAX_STRING_SIZE);
iscsi_url->lun = l;
}
+ iscsi_decode_url_string(&iscsi_url->target[0]);
+
return iscsi_url;
}
diff --git a/lib/login.c b/lib/login.c
index 29fe4b3..0448ce2 100644
--- a/lib/login.c
+++ b/lib/login.c
@@ -622,6 +622,7 @@ h2i(int h)
}
return h - '0';
}
+
static int
i2h(int i)
{
--
1.8.1.4

539
SOURCES/0008-SCSI-add-a-safe-function-to-read-a-byte-from-the-dat.patch

@ -0,0 +1,539 @@ @@ -0,0 +1,539 @@
From 704e0f6448f4a9ce0c4c9a030679ab97a37850e8 Mon Sep 17 00:00:00 2001
From: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Date: Sun, 12 May 2013 13:57:15 -0700
Subject: [RHEL7 libiscsi PATCH 08/18] SCSI: add a safe function to read a byte from the datain
buffer and use it throughout the unmarshalling code

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from upstream commit 704e0f6448f4a9ce0c4c9a030679ab97a37850e8)
---
lib/scsi-lowlevel.c | 302 ++++++++++++++++++++++++++++------------------------
1 file changed, 163 insertions(+), 139 deletions(-)

diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c
index 85f7b1d..1f51f32 100644
--- a/lib/scsi-lowlevel.c
+++ b/lib/scsi-lowlevel.c
@@ -274,6 +274,16 @@ task_get_uint16(struct scsi_task *task, int offset)
}
}
+static inline uint8_t
+task_get_uint8(struct scsi_task *task, int offset)
+{
+ if (offset <= task->datain.size - 1) {
+ return task->datain.data[offset];
+ } else {
+ return 0;
+ }
+}
+
inline void
scsi_set_uint64(unsigned char *c, uint64_t v)
{
@@ -501,49 +511,49 @@ scsi_readtoc_desc_unmarshall(struct scsi_task *task, struct scsi_readtoc_list *l
switch(scsi_readtoc_format(task)) {
case SCSI_READ_TOC:
list->desc[i].desc.toc.adr
- = task->datain.data[4+8*i+1] & 0xf0;
+ = task_get_uint8(task, 4 + 8 * i + 1) & 0xf0;
list->desc[i].desc.toc.control
- = task->datain.data[4+8*i+1] & 0x0f;
+ = task_get_uint8(task, 4 + 8 * i + 1) & 0x0f;
list->desc[i].desc.toc.track
- = task->datain.data[4+8*i+2];
+ = task_get_uint8(task, 4 + 8 * i + 2);
list->desc[i].desc.toc.lba
= task_get_uint32(task, 4 + 8 * i + 4);
break;
case SCSI_READ_SESSION_INFO:
list->desc[i].desc.ses.adr
- = task->datain.data[4+8*i+1] & 0xf0;
+ = task_get_uint8(task, 4 + 8 * i + 1) & 0xf0;
list->desc[i].desc.ses.control
- = task->datain.data[4+8*i+1] & 0x0f;
+ = task_get_uint8(task, 4 + 8 * i + 1) & 0x0f;
list->desc[i].desc.ses.first_in_last
- = task->datain.data[4+8*i+2];
+ = task_get_uint8(task, 4 + 8 * i + 2);
list->desc[i].desc.ses.lba
= task_get_uint32(task, 4 + 8 * i + 4);
break;
case SCSI_READ_FULL_TOC:
list->desc[i].desc.full.session
- = task->datain.data[4+11*i+0] & 0xf0;
+ = task_get_uint8(task, 4 + 11 * i + 0) & 0xf0;
list->desc[i].desc.full.adr
- = task->datain.data[4+11*i+1] & 0xf0;
+ = task_get_uint8(task, 4 + 11 * i + 1) & 0xf0;
list->desc[i].desc.full.control
- = task->datain.data[4+11*i+1] & 0x0f;
+ = task_get_uint8(task, 4 + 11 * i + 1) & 0x0f;
list->desc[i].desc.full.tno
- = task->datain.data[4+11*i+2];
+ = task_get_uint8(task, 4 + 11 * i + 2);
list->desc[i].desc.full.point
- = task->datain.data[4+11*i+3];
+ = task_get_uint8(task, 4 + 11 * i + 3);
list->desc[i].desc.full.min
- = task->datain.data[4+11*i+4];
+ = task_get_uint8(task, 4 + 11 * i + 4);
list->desc[i].desc.full.sec
- = task->datain.data[4+11*i+5];
+ = task_get_uint8(task, 4 + 11 * i + 5);
list->desc[i].desc.full.frame
- = task->datain.data[4+11*i+6];
+ = task_get_uint8(task, 4 + 11 * i + 6);
list->desc[i].desc.full.zero
- = task->datain.data[4+11*i+7];
+ = task_get_uint8(task, 4 + 11 * i + 7);
list->desc[i].desc.full.pmin
- = task->datain.data[4+11*i+8];
+ = task_get_uint8(task, 4 + 11 * i + 8);
list->desc[i].desc.full.psec
- = task->datain.data[4+11*i+9];
+ = task_get_uint8(task, 4 + 11 * i + 9);
list->desc[i].desc.full.pframe
- = task->datain.data[4+11*i+10];
+ = task_get_uint8(task, 4 + 11 * i + 10);
break;
default:
break;
@@ -580,8 +590,8 @@ scsi_readtoc_datain_unmarshall(struct scsi_task *task)
}
list->num = num_desc;
- list->first = task->datain.data[2];
- list->last = task->datain.data[3];
+ list->first = task_get_uint8(task, 2);
+ list->last = task_get_uint8(task, 3);
for (i = 0; i < num_desc; i++) {
scsi_readtoc_desc_unmarshall(task, list, i);
@@ -655,12 +665,12 @@ scsi_serviceactionin_datain_unmarshall(struct scsi_task *task)
rc16->returned_lba = task_get_uint32(task, 0);
rc16->returned_lba = (rc16->returned_lba << 32) | task_get_uint32(task, 4);
rc16->block_length = task_get_uint32(task, 8);
- rc16->p_type = (task->datain.data[12] >> 1) & 0x07;
- rc16->prot_en = task->datain.data[12] & 0x01;
- rc16->p_i_exp = (task->datain.data[13] >> 4) & 0x0f;
- rc16->lbppbe = task->datain.data[13] & 0x0f;
- rc16->lbpme = !!(task->datain.data[14] & 0x80);
- rc16->lbprz = !!(task->datain.data[14] & 0x40);
+ rc16->p_type = (task_get_uint8(task, 12) >> 1) & 0x07;
+ rc16->prot_en = task_get_uint8(task, 12) & 0x01;
+ rc16->p_i_exp = (task_get_uint8(task, 13) >> 4) & 0x0f;
+ rc16->lbppbe = task_get_uint8(task, 13) & 0x0f;
+ rc16->lbpme = !!(task_get_uint8(task, 14) & 0x80);
+ rc16->lbprz = !!(task_get_uint8(task, 14) & 0x40);
rc16->lalba = task_get_uint16(task, 14) & 0x3fff;
return rc16;
}
@@ -694,7 +704,7 @@ scsi_serviceactionin_datain_unmarshall(struct scsi_task *task)
gls->descriptors[i].num_blocks = task_get_uint32(task, 8 + i * sizeof(struct scsi_lba_status_descriptor) + 8);
- gls->descriptors[i].provisioning = task->datain.data[8 + i * sizeof(struct scsi_lba_status_descriptor) + 12] & 0x0f;
+ gls->descriptors[i].provisioning = task_get_uint8(task, 8 + i * sizeof(struct scsi_lba_status_descriptor) + 12) & 0x0f;
}
return gls;
@@ -771,7 +781,7 @@ scsi_persistentreservein_datain_unmarshall(struct scsi_task *task)
rr->reserved = 1;
rr->reservation_key =
task_get_uint64(task, 8);
- rr->pr_type = task->datain.data[21] & 0xff;
+ rr->pr_type = task_get_uint8(task, 21) & 0xff;
}
return rr;
@@ -782,12 +792,12 @@ scsi_persistentreservein_datain_unmarshall(struct scsi_task *task)
return NULL;
}
rc->length = task_get_uint16(task, 0);
- rc->crh = !!(task->datain.data[2] & 0x10);
- rc->sip_c = !!(task->datain.data[2] & 0x08);
- rc->atp_c = !!(task->datain.data[2] & 0x04);
- rc->ptpl_c = !!(task->datain.data[2] & 0x01);
- rc->tmv = !!(task->datain.data[3] & 0x80);
- rc->allow_commands = task->datain.data[3] >> 4;
+ rc->crh = !!(task_get_uint8(task, 2) & 0x10);
+ rc->sip_c = !!(task_get_uint8(task, 2) & 0x08);
+ rc->atp_c = !!(task_get_uint8(task, 2) & 0x04);
+ rc->ptpl_c = !!(task_get_uint8(task, 2) & 0x01);
+ rc->tmv = !!(task_get_uint8(task, 3) & 0x80);
+ rc->allow_commands = task_get_uint8(task, 3) >> 4;
rc->persistent_reservation_type_mask = task_get_uint16(task, 4);
return rc;
@@ -1003,14 +1013,14 @@ static int
scsi_inquiry_datain_getfullsize(struct scsi_task *task)
{
if (scsi_inquiry_evpd_set(task) == 0) {
- return task->datain.data[4] + 5;
+ return task_get_uint8(task, 4) + 5;
}
switch (scsi_inquiry_page_code(task)) {
case SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES:
case SCSI_INQUIRY_PAGECODE_BLOCK_DEVICE_CHARACTERISTICS:
case SCSI_INQUIRY_PAGECODE_UNIT_SERIAL_NUMBER:
- return task->datain.data[3] + 4;
+ return task_get_uint8(task, 3) + 4;
case SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION:
case SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS:
case SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING:
@@ -1030,28 +1040,28 @@ scsi_inquiry_unmarshall_standard(struct scsi_task *task)
return NULL;
}
- inq->qualifier = (task->datain.data[0]>>5)&0x07;
- inq->device_type = task->datain.data[0]&0x1f;
- inq->rmb = !!(task->datain.data[1]&0x80);
- inq->version = task->datain.data[2];
- inq->normaca = !!(task->datain.data[3]&0x20);
- inq->hisup = !!(task->datain.data[3]&0x10);
- inq->response_data_format = task->datain.data[3]&0x0f;
+ inq->qualifier = (task_get_uint8(task, 0) >> 5) & 0x07;
+ inq->device_type = task_get_uint8(task, 0) & 0x1f;
+ inq->rmb = !!(task_get_uint8(task, 1) & 0x80);
+ inq->version = task_get_uint8(task, 2);
+ inq->normaca = !!(task_get_uint8(task, 3) & 0x20);
+ inq->hisup = !!(task_get_uint8(task, 3) & 0x10);
+ inq->response_data_format = task_get_uint8(task, 3) & 0x0f;
- inq->additional_length = task->datain.data[4];
+ inq->additional_length = task_get_uint8(task, 4);
- inq->sccs = !!(task->datain.data[5]&0x80);
- inq->acc = !!(task->datain.data[5]&0x40);
- inq->tpgs = (task->datain.data[5]>>4)&0x03;
- inq->threepc = !!(task->datain.data[5]&0x08);
- inq->protect = !!(task->datain.data[5]&0x01);
+ inq->sccs = !!(task_get_uint8(task, 5) & 0x80);
+ inq->acc = !!(task_get_uint8(task, 5) & 0x40);
+ inq->tpgs = (task_get_uint8(task, 5) >> 4) & 0x03;
+ inq->threepc = !!(task_get_uint8(task, 5) & 0x08);
+ inq->protect = !!(task_get_uint8(task, 5) & 0x01);
- inq->encserv = !!(task->datain.data[6]&0x40);
- inq->multip = !!(task->datain.data[6]&0x10);
- inq->addr16 = !!(task->datain.data[6]&0x01);
- inq->wbus16 = !!(task->datain.data[7]&0x20);
- inq->sync = !!(task->datain.data[7]&0x10);
- inq->cmdque = !!(task->datain.data[7]&0x02);
+ inq->encserv = !!(task_get_uint8(task, 6) & 0x40);
+ inq->multip = !!(task_get_uint8(task, 6) & 0x10);
+ inq->addr16 = !!(task_get_uint8(task, 6) & 0x01);
+ inq->wbus16 = !!(task_get_uint8(task, 7) & 0x20);
+ inq->sync = !!(task_get_uint8(task, 7) & 0x10);
+ inq->cmdque = !!(task_get_uint8(task, 7) & 0x02);
memcpy(&inq->vendor_identification[0],
&task->datain.data[8], 8);
@@ -1060,9 +1070,9 @@ scsi_inquiry_unmarshall_standard(struct scsi_task *task)
memcpy(&inq->product_revision_level[0],
&task->datain.data[32], 4);
- inq->clocking = (task->datain.data[56]>>2)&0x03;
- inq->qas = !!(task->datain.data[56]&0x02);
- inq->ius = !!(task->datain.data[56]&0x01);
+ inq->clocking = (task_get_uint8(task, 56) >> 2) & 0x03;
+ inq->qas = !!(task_get_uint8(task, 56) & 0x02);
+ inq->ius = !!(task_get_uint8(task, 56) & 0x01);
return inq;
}
@@ -1079,11 +1089,11 @@ scsi_inquiry_unmarshall_supported_pages(struct scsi_task *task)
if (inq == NULL) {
return NULL;
}
- inq->qualifier = (task->datain.data[0]>>5)&0x07;
- inq->device_type = task->datain.data[0]&0x1f;
- inq->pagecode = task->datain.data[1];
+ inq->qualifier = (task_get_uint8(task, 0) >> 5) & 0x07;
+ inq->device_type = task_get_uint8(task, 0) & 0x1f;
+ inq->pagecode = task_get_uint8(task, 1);
- inq->num_pages = task->datain.data[3];
+ inq->num_pages = task_get_uint8(task, 3);
inq->pages = scsi_malloc(task, inq->num_pages);
if (inq->pages == NULL) {
free (inq);
@@ -1101,17 +1111,17 @@ scsi_inquiry_unmarshall_unit_serial_number(struct scsi_task* task)
if (inq == NULL) {
return NULL;
}
- inq->qualifier = (task->datain.data[0]>>5)&0x07;
- inq->device_type = task->datain.data[0]&0x1f;
- inq->pagecode = task->datain.data[1];
+ inq->qualifier = (task_get_uint8(task, 0) >> 5) & 0x07;
+ inq->device_type = task_get_uint8(task, 0) & 0x1f;
+ inq->pagecode = task_get_uint8(task, 1);
- inq->usn = scsi_malloc(task, task->datain.data[3]+1);
+ inq->usn = scsi_malloc(task, task_get_uint8(task, 3) + 1);
if (inq->usn == NULL) {
free(inq);
return NULL;
}
- memcpy(inq->usn, &task->datain.data[4], task->datain.data[3]);
- inq->usn[task->datain.data[3]] = 0;
+ memcpy(inq->usn, &task->datain.data[4], task_get_uint8(task, 3));
+ inq->usn[task_get_uint8(task, 3)] = 0;
return inq;
}
@@ -1119,16 +1129,16 @@ static struct scsi_inquiry_device_identification *
scsi_inquiry_unmarshall_device_identification(struct scsi_task *task)
{
struct scsi_inquiry_device_identification *inq = scsi_malloc(task,
- sizeof(*inq));
+ sizeof(*inq));
int remaining = task_get_uint16(task, 2);
unsigned char *dptr;
if (inq == NULL) {
return NULL;
}
- inq->qualifier = (task->datain.data[0]>>5)&0x07;
- inq->device_type = task->datain.data[0]&0x1f;
- inq->pagecode = task->datain.data[1];
+ inq->qualifier = (task_get_uint8(task, 0) >> 5) & 0x07;
+ inq->device_type = task_get_uint8(task, 0) & 0x1f;
+ inq->pagecode = task_get_uint8(task, 1);
dptr = &task->datain.data[4];
while (remaining > 0) {
@@ -1183,12 +1193,12 @@ scsi_inquiry_unmarshall_block_limits(struct scsi_task *task)
if (inq == NULL) {
return NULL;
}
- inq->qualifier = (task->datain.data[0]>>5)&0x07;
- inq->device_type = task->datain.data[0]&0x1f;
- inq->pagecode = task->datain.data[1];
+ inq->qualifier = (task_get_uint8(task, 0) >> 5) & 0x07;
+ inq->device_type = task_get_uint8(task, 0) & 0x1f;
+ inq->pagecode = task_get_uint8(task, 1);
- inq->wsnz = task->datain.data[4] & 0x01;
- inq->max_cmp = task->datain.data[5];
+ inq->wsnz = task_get_uint8(task, 4) & 0x01;
+ inq->max_cmp = task_get_uint8(task, 5);
inq->opt_gran = task_get_uint16(task, 6);
inq->max_xfer_len = task_get_uint32(task, 8);
inq->opt_xfer_len = task_get_uint32(task, 12);
@@ -1196,7 +1206,7 @@ scsi_inquiry_unmarshall_block_limits(struct scsi_task *task)
inq->max_unmap = task_get_uint32(task, 20);
inq->max_unmap_bdc = task_get_uint32(task, 24);
inq->opt_unmap_gran = task_get_uint32(task, 28);
- inq->ugavalid = !!(task->datain.data[32]&0x80);
+ inq->ugavalid = !!(task_get_uint8(task, 32)&0x80);
inq->unmap_gran_align = task_get_uint32(task, 32) & 0x7fffffff;
inq->max_ws_len = task_get_uint32(task, 36);
inq->max_ws_len = (inq->max_ws_len << 32)
@@ -1213,9 +1223,9 @@ scsi_inquiry_unmarshall_block_device_characteristics(struct scsi_task *task)
if (inq == NULL) {
return NULL;
}
- inq->qualifier = (task->datain.data[0]>>5)&0x07;
- inq->device_type = task->datain.data[0]&0x1f;
- inq->pagecode = task->datain.data[1];
+ inq->qualifier = (task_get_uint8(task, 0) >> 5) & 0x07;
+ inq->device_type = task_get_uint8(task, 0) & 0x1f;
+ inq->pagecode = task_get_uint8(task, 1);
inq->medium_rotation_rate = task_get_uint16(task, 4);
return inq;
@@ -1229,18 +1239,18 @@ scsi_inquiry_unmarshall_logical_block_provisioning(struct scsi_task *task)
if (inq == NULL) {
return NULL;
}
- inq->qualifier = (task->datain.data[0]>>5)&0x07;
- inq->device_type = task->datain.data[0]&0x1f;
- inq->pagecode = task->datain.data[1];
+ inq->qualifier = (task_get_uint8(task, 0) >> 5) & 0x07;
+ inq->device_type = task_get_uint8(task, 0) & 0x1f;
+ inq->pagecode = task_get_uint8(task, 1);
- inq->threshold_exponent = task->datain.data[4];
- inq->lbpu = !!(task->datain.data[5] & 0x80);
- inq->lbpws = !!(task->datain.data[5] & 0x40);
- inq->lbpws10 = !!(task->datain.data[5] & 0x20);
- inq->lbprz = !!(task->datain.data[5] & 0x04);
- inq->anc_sup = !!(task->datain.data[5] & 0x02);
- inq->dp = !!(task->datain.data[5] & 0x01);
- inq->provisioning_type = task->datain.data[6] & 0x07;
+ inq->threshold_exponent = task_get_uint8(task, 4);
+ inq->lbpu = !!(task_get_uint8(task, 5) & 0x80);
+ inq->lbpws = !!(task_get_uint8(task, 5) & 0x40);
+ inq->lbpws10 = !!(task_get_uint8(task, 5) & 0x20);
+ inq->lbprz = !!(task_get_uint8(task, 5) & 0x04);
+ inq->anc_sup = !!(task_get_uint8(task, 5) & 0x02);
+ inq->dp = !!(task_get_uint8(task, 5) & 0x01);
+ inq->provisioning_type = task_get_uint8(task, 6) & 0x07;
return inq;
}
@@ -2062,7 +2072,7 @@ scsi_modesense6_datain_getfullsize(struct scsi_task *task)
{
int len;
- len = task->datain.data[0] + 1;
+ len = task_get_uint8(task, 0) + 1;
return len;
}
@@ -2070,59 +2080,73 @@ scsi_modesense6_datain_getfullsize(struct scsi_task *task)
static void
scsi_parse_mode_caching(struct scsi_task *task, int pos, struct scsi_mode_page *mp)
{
- mp->caching.ic = task->datain.data[pos] & 0x80;
- mp->caching.abpf = task->datain.data[pos] & 0x40;
- mp->caching.cap = task->datain.data[pos] & 0x20;
- mp->caching.disc = task->datain.data[pos] & 0x10;
- mp->caching.size = task->datain.data[pos] & 0x08;
- mp->caching.wce = task->datain.data[pos] & 0x04;
- mp->caching.mf = task->datain.data[pos] & 0x02;
- mp->caching.rcd = task->datain.data[pos] & 0x01;
-
- mp->caching.demand_read_retention_priority = (task->datain.data[pos+1] >> 4) & 0x0f;
- mp->caching.write_retention_priority = task->datain.data[pos+1] & 0x0f;
-
- mp->caching.disable_prefetch_transfer_length = task_get_uint16(task, pos + 2);
+ mp->caching.ic = task_get_uint8(task, pos) & 0x80;
+ mp->caching.abpf = task_get_uint8(task, pos) & 0x40;
+ mp->caching.cap = task_get_uint8(task, pos) & 0x20;
+ mp->caching.disc = task_get_uint8(task, pos) & 0x10;
+ mp->caching.size = task_get_uint8(task, pos) & 0x08;
+ mp->caching.wce = task_get_uint8(task, pos) & 0x04;
+ mp->caching.mf = task_get_uint8(task, pos) & 0x02;
+ mp->caching.rcd = task_get_uint8(task, pos) & 0x01;
+
+ mp->caching.demand_read_retention_priority =
+ (task_get_uint8(task, pos + 1) >> 4) & 0x0f;
+ mp->caching.write_retention_priority =
+ task_get_uint8(task, pos + 1) & 0x0f;
+
+ mp->caching.disable_prefetch_transfer_length =
+ task_get_uint16(task, pos + 2);
mp->caching.minimum_prefetch = task_get_uint16(task, pos + 4);
mp->caching.maximum_prefetch = task_get_uint16(task, pos + 6);
mp->caching.maximum_prefetch_ceiling = task_get_uint16(task, pos + 8);
- mp->caching.fsw = task->datain.data[pos+10] & 0x80;
- mp->caching.lbcss = task->datain.data[pos+10] & 0x40;
- mp->caching.dra = task->datain.data[pos+10] & 0x20;
- mp->caching.nv_dis = task->datain.data[pos+10] & 0x01;
+ mp->caching.fsw = task_get_uint8(task, pos + 10) & 0x80;
+ mp->caching.lbcss = task_get_uint8(task, pos + 10) & 0x40;
+ mp->caching.dra = task_get_uint8(task, pos + 10) & 0x20;
+ mp->caching.nv_dis = task_get_uint8(task, pos + 10) & 0x01;
- mp->caching.number_of_cache_segments = task->datain.data[pos+11];
+ mp->caching.number_of_cache_segments = task_get_uint8(task, pos + 11);
mp->caching.cache_segment_size = task_get_uint16(task, pos + 12);
}
static void
scsi_parse_mode_disconnect_reconnect(struct scsi_task *task, int pos, struct scsi_mode_page *mp)
{
- mp->disconnect_reconnect.buffer_full_ratio = task->datain.data[pos];
- mp->disconnect_reconnect.buffer_empty_ratio = task->datain.data[pos+1];
- mp->disconnect_reconnect.bus_inactivity_limit = task_get_uint16(task, pos + 2);
- mp->disconnect_reconnect.disconnect_time_limit = task_get_uint16(task, pos + 4);
- mp->disconnect_reconnect.connect_time_limit = task_get_uint16(task, pos + 6);
- mp->disconnect_reconnect.maximum_burst_size = task_get_uint16(task, pos + 8);
- mp->disconnect_reconnect.emdp = task->datain.data[pos+10] & 0x80;
- mp->disconnect_reconnect.fair_arbitration = (task->datain.data[pos+10]>>4) & 0x0f;
- mp->disconnect_reconnect.dimm = task->datain.data[pos+10] & 0x08;
- mp->disconnect_reconnect.dtdc = task->datain.data[pos+10] & 0x07;
- mp->disconnect_reconnect.first_burst_size = task_get_uint16(task, pos + 12);
+ mp->disconnect_reconnect.buffer_full_ratio =
+ task_get_uint8(task, pos);
+ mp->disconnect_reconnect.buffer_empty_ratio =
+ task_get_uint8(task, pos + 1);
+ mp->disconnect_reconnect.bus_inactivity_limit =
+ task_get_uint16(task, pos + 2);
+ mp->disconnect_reconnect.disconnect_time_limit =
+ task_get_uint16(task, pos + 4);
+ mp->disconnect_reconnect.connect_time_limit =
+ task_get_uint16(task, pos + 6);
+ mp->disconnect_reconnect.maximum_burst_size =
+ task_get_uint16(task, pos + 8);
+ mp->disconnect_reconnect.emdp =
+ task_get_uint8(task, pos + 10) & 0x80;
+ mp->disconnect_reconnect.fair_arbitration =
+ (task_get_uint8(task, pos + 10) >> 4) & 0x0f;
+ mp->disconnect_reconnect.dimm =
+ task_get_uint8(task, pos + 10) & 0x08;
+ mp->disconnect_reconnect.dtdc =
+ task_get_uint8(task, pos + 10) & 0x07;
+ mp->disconnect_reconnect.first_burst_size =
+ task_get_uint16(task, pos + 12);
}
static void
scsi_parse_mode_informational_exceptions_control(struct scsi_task *task, int pos, struct scsi_mode_page *mp)
{
- mp->iec.perf = task->datain.data[pos] & 0x80;
- mp->iec.ebf = task->datain.data[pos] & 0x20;
- mp->iec.ewasc = task->datain.data[pos] & 0x10;
- mp->iec.dexcpt = task->datain.data[pos] & 0x08;
- mp->iec.test = task->datain.data[pos] & 0x04;
- mp->iec.ebackerr = task->datain.data[pos] & 0x02;
- mp->iec.logerr = task->datain.data[pos] & 0x01;
- mp->iec.mrie = task->datain.data[pos+1] & 0x0f;
+ mp->iec.perf = task_get_uint8(task, pos) & 0x80;
+ mp->iec.ebf = task_get_uint8(task, pos) & 0x20;
+ mp->iec.ewasc = task_get_uint8(task, pos) & 0x10;
+ mp->iec.dexcpt = task_get_uint8(task, pos) & 0x08;
+ mp->iec.test = task_get_uint8(task, pos) & 0x04;
+ mp->iec.ebackerr = task_get_uint8(task, pos) & 0x02;
+ mp->iec.logerr = task_get_uint8(task, pos) & 0x01;
+ mp->iec.mrie = task_get_uint8(task, pos + 1) & 0x0f;
mp->iec.interval_timer = task_get_uint32(task, pos + 2);
mp->iec.report_count = task_get_uint32(task, pos + 6);
}
@@ -2146,10 +2170,10 @@ scsi_modesense_datain_unmarshall(struct scsi_task *task)
return NULL;
}
- ms->mode_data_length = task->datain.data[0];
- ms->medium_type = task->datain.data[1];
- ms->device_specific_parameter = task->datain.data[2];
- ms->block_descriptor_length = task->datain.data[3];
+ ms->mode_data_length = task_get_uint8(task, 0);
+ ms->medium_type = task_get_uint8(task, 1);
+ ms->device_specific_parameter = task_get_uint8(task, 2);
+ ms->block_descriptor_length = task_get_uint8(task, 3);
ms->pages = NULL;
if (ms->mode_data_length + 1 > task->datain.size) {
@@ -2164,18 +2188,18 @@ scsi_modesense_datain_unmarshall(struct scsi_task *task)
if (mp == NULL) {
return ms;
}
- mp->ps = task->datain.data[pos] & 0x80;
- mp->spf = task->datain.data[pos] & 0x40;
- mp->page_code = task->datain.data[pos] & 0x3f;
+ mp->ps = task_get_uint8(task, pos) & 0x80;
+ mp->spf = task_get_uint8(task, pos) & 0x40;
+ mp->page_code = task_get_uint8(task, pos) & 0x3f;
pos++;
if (mp->spf) {
- mp->subpage_code = task->datain.data[pos++];
+ mp->subpage_code = task_get_uint8(task, pos++);
mp->len = task_get_uint16(task, pos);
pos += 2;
} else {
mp->subpage_code = 0;
- mp->len = task->datain.data[pos++];
+ mp->len = task_get_uint8(task, pos++);
}
switch (mp->page_code) {
--
1.8.1.4

114
SOURCES/0009-scsi-lowlevel-do-not-use-unsafe-pointer-casts.patch

@ -0,0 +1,114 @@ @@ -0,0 +1,114 @@
From 0a7c084603663a1e63b01bd677429a20bc7d4c62 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Mon, 1 Jul 2013 15:57:44 +0200
Subject: [RHEL7 libiscsi PATCH 09/18] scsi-lowlevel: do not use unsafe pointer casts

Casting unsigned char * pointers to uint32_t * may cause wrong
results if the pointers are not correctly aligned. Instead,
build up the big-endian values from each byte with multiple
dereferences of the original pointer.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from upstream commit 0a7c084603663a1e63b01bd677429a20bc7d4c62)
---
lib/scsi-lowlevel.c | 36 +++++++++++++++++++++---------------
1 file changed, 21 insertions(+), 15 deletions(-)

diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c
index ad94eef..37f41d5 100644
--- a/lib/scsi-lowlevel.c
+++ b/lib/scsi-lowlevel.c
@@ -212,10 +212,10 @@ scsi_get_uint64(const unsigned char *c)
{
uint64_t val;
- val = ntohl(*(uint32_t *)c);
+ val = scsi_get_uint32(c);
val <<= 32;
c += 4;
- val |= ntohl(*(uint32_t *)c);
+ val |= scsi_get_uint32(c);
return val;
}
@@ -223,13 +223,21 @@ scsi_get_uint64(const unsigned char *c)
inline uint32_t
scsi_get_uint32(const unsigned char *c)
{
- return ntohl(*(uint32_t *)c);
+ uint32_t val;
+ val = c[0];
+ val = (val << 8) | c[1];
+ val = (val << 8) | c[2];
+ val = (val << 8) | c[3];
+ return val;
}
inline uint16_t
scsi_get_uint16(const unsigned char *c)
{
- return ntohs(*(uint16_t *)c);
+ uint16_t val;
+ val = c[0];
+ val = (val << 8) | c[1];
+ return val;
}
static inline uint64_t
@@ -237,14 +245,8 @@ task_get_uint64(struct scsi_task *task, int offset)
{
if (offset <= task->datain.size - 8) {
const unsigned char *c = &task->datain.data[offset];
- uint64_t val;
- val = ntohl(*(uint32_t *)c);
- val <<= 32;
- c += 4;
- val |= ntohl(*(uint32_t *)c);
-
- return val;
+ return scsi_get_uint64(c);
} else {
return 0;
}
@@ -256,7 +258,7 @@ task_get_uint32(struct scsi_task *task, int offset)
if (offset <= task->datain.size - 4) {
const unsigned char *c = &task->datain.data[offset];
- return ntohl(*(uint32_t *)c);
+ return scsi_get_uint32(c);
} else {
return 0;
}
@@ -268,7 +270,7 @@ task_get_uint16(struct scsi_task *task, int offset)
if (offset <= task->datain.size - 2) {
const unsigned char *c = &task->datain.data[offset];
- return ntohs(*(uint16_t *)c);
+ return scsi_get_uint16(c);
} else {
return 0;
}
@@ -300,13 +302,17 @@ scsi_set_uint64(unsigned char *c, uint64_t v)
inline void
scsi_set_uint32(unsigned char *c, uint32_t val)
{
- *(uint32_t *)c = htonl(val);
+ c[0] = val >> 24;
+ c[1] = val >> 16;
+ c[2] = val >> 8;
+ c[3] = val;
}
inline void
scsi_set_uint16(unsigned char *c, uint16_t val)
{
- *(uint16_t *)c = htons(val);
+ c[0] = val >> 8;
+ c[1] = val;
}
/*
--
1.8.1.4

27
SOURCES/0010-Add-a-cast-to-ssize_t.patch

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
From b555bbebdd1c92b025a44955a988cc2eed646c2b Mon Sep 17 00:00:00 2001
From: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Date: Sat, 29 Jun 2013 11:12:41 -0700
Subject: [RHEL7 libiscsi PATCH 10/18] Add a cast to ssize_t

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from upstream commit b555bbebdd1c92b025a44955a988cc2eed646c2b)
---
lib/socket.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/socket.c b/lib/socket.c
index a855f92..6fc3b41 100644
--- a/lib/socket.c
+++ b/lib/socket.c
@@ -517,7 +517,7 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
}
data_size = iscsi_get_pdu_data_size(&in->hdr[0]);
- if (data_size < 0 || data_size > iscsi->initiator_max_recv_data_segment_length) {
+ if (data_size < 0 || data_size > (ssize_t)iscsi->initiator_max_recv_data_segment_length) {
iscsi_set_error(iscsi, "Invalid data size received from target (%d)", (int)data_size);
return -1;
}
--
1.8.1.4

26
SOURCES/0011-do-not-build-test-tool.patch

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
From b036ca4d5b414f269a0c00da2624129858e5bf3e Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 30 Aug 2013 15:55:13 +0200
Subject: [RHEL7 libiscsi PATCH 11/18] do not build test tool

The test tool is not needed in RHEL. Do not build it nor
install it.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

diff --git a/Makefile.am b/Makefile.am
index 114dd09..d5acf30 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -59,7 +59,7 @@ bin_iscsi_dd_SOURCES = examples/iscsi-dd.c
# libiscsi test tool
-noinst_PROGRAMS += bin/iscsi-test
+EXTRA_PROGRAMS += bin/iscsi-test
dist_noinst_HEADERS += test-tool/iscsi-support.h \
test-tool/iscsi-test.h \
test-tool/iscsi-test-cu.h
--
1.8.3.1

25
SOURCES/0012-bump-soname.patch

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
From d4a6e4b3e3c6becf507158b8ae7cea70521753e9 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Sat, 29 Jun 2013 11:12:41 -0700
Subject: [RHEL7 libiscsi PATCH 12/18] bump ABI version

ABI was not preserved between 1.7.0 and 1.9.0. It was also bumped
further after 1.9.0, so I made the upstream patch go to 3 and
reserved 2 for Fedora/RHEL.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(see upstream commit d4a6e4b3e3c6becf507158b8ae7cea70521753e9)
---
diff --git a/Makefile.am b/Makefile.am
index 50dfe11..4ccb52c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -37,7 +37,7 @@ if !HAVE_LIBGCRYPT
lib_libiscsi_la_SOURCES += lib/md5.c
endif
-SONAME=$(firstword $(subst ., ,$(VERSION)))
+SONAME=2
SOREL=$(shell printf "%d%02d%02d" $(subst ., ,$(VERSION)))
lib_libiscsi_la_LDFLAGS = \
-version-info $(SONAME):$(SOREL):0 -bindir $(bindir) -no-undefined \

23
SOURCES/0013-disable-ld_iscsi.patch

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
From dfb8fb325b5a3b28c08e3699575441d437ec1863 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Sat, 29 Jun 2013 11:12:41 -0700
Subject: [RHEL7 libiscsi PATCH 13/18] disable ld_iscsi.so

This is a LD_PRELOAD trick that we don't want to support, disable it.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(not upstream)
---
diff --git a/Makefile.am b/Makefile.am
index 50dfe11..1a76d12 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -320,7 +320,7 @@ bin/ld_iscsi.o: src/bin_ld_iscsi-ld_iscsi.o lib/libiscsi_convenience.la
$(LIBTOOL) --mode=link $(CC) -o $@ $^
# 3) Manually create the .so file.
-bin_SCRIPTS = bin/ld_iscsi.so
+#bin_SCRIPTS = bin/ld_iscsi.so
bin/ld_iscsi.so: bin/ld_iscsi.o
$(CC) -shared -o bin/ld_iscsi.so bin/ld_iscsi.o -ldl
endif

30
SOURCES/0014-fix-another-aliasing-problem.patch

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
From dfb8fb325b5a3b28c08e3699575441d437ec1863 Mon Sep 17 00:00:00 2001
Author: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri Aug 2 14:07:42 2013 +0200
Subject: [RHEL7 libiscsi PATCH 14/18] fix another aliasing problem

scsi_set_uint64 should just use scsi_set_uint32, similar to
what scsi_get_uint64 does. This avoids problems on architectures
where "uint32_t" requires more alignment than "char", e.g. ARM.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from upstream commit 31a3aeb0e0167401a7c10f4cba95a72697f907c0)

diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c
index 0989f0f..1bb03af 100644
--- a/lib/scsi-lowlevel.c
+++ b/lib/scsi-lowlevel.c
@@ -300,11 +300,11 @@ scsi_set_uint64(unsigned char *c, uint64_t v)
uint32_t val;
val = (v >> 32) & 0xffffffff;
- *(uint32_t *)c = htonl(val);
+ scsi_set_uint32(c, val);
c += 4;
val = v & 0xffffffff;
- *(uint32_t *)c = htonl(val);
+ scsi_set_uint32(c, val);
}
inline void

174
SOURCES/0015-fix-arm-aliasing-problem.patch

@ -0,0 +1,174 @@ @@ -0,0 +1,174 @@
From 709410b1d7f3d0b2b4e342cc46de2b45453d6c5c Mon Sep 17 00:00:00 2001
From: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Date: Sat, 18 May 2013 13:56:02 -0700
Subject: [RHEL7 libiscsi PATCH 15/18] TESTS: Add some REPORT SUPPORTED OPCODES tests

Add a simple test that it works or is not implemented.

Add a RCTD test to verify that with this flag clear we get command descriptors without CTDP set and with it set we get command descriptors with CTDP set and a timeout descriptor

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from upstream commit 709410b1d7f3d0b2b4e342cc46de2b45453d6c5c)

Fixes these errors in ARM compilation:

lib/scsi-lowlevel.c: In function 'scsi_maintenancein_datain_unmarshall':
lib/scsi-lowlevel.c:862:12: error: cast increases required alignment of target type [-Werror=cast-align]
datain = (struct scsi_command_descriptor *)&task->datain.data[4];
^
lib/scsi-lowlevel.c:876:11: error: cast increases required alignment of target type [-Werror=cast-align]
desc = (struct scsi_command_descriptor *)((char *)desc + desc_size);
^
lib/scsi-lowlevel.c:877:13: error: cast increases required alignment of target type [-Werror=cast-align]
datain = (struct scsi_command_descriptor *)((char *)datain + desc_size);
^
---
include/scsi-lowlevel.h | 60 +++++++-------
lib/scsi-lowlevel.c | 77 +++++++++---------

diff --git a/include/scsi-lowlevel.h b/include/scsi-lowlevel.h
index 5693129..acdc936 100644
--- a/include/scsi-lowlevel.h
+++ b/include/scsi-lowlevel.h
@@ -739,24 +739,24 @@ struct scsi_get_lba_status {
struct scsi_op_timeout_descriptor {
uint16_t descriptor_length;
- uint8_t reserved;
uint8_t command_specific;
uint32_t nominal_processing_timeout;
uint32_t recommended_timeout;
};
struct scsi_command_descriptor {
- uint8_t op_code;
- uint8_t reserved1;
- uint16_t service_action;
- uint8_t reserved2;
- uint8_t reserved3;
- uint16_t cdb_length;
- struct scsi_op_timeout_descriptor to[0];
+ uint8_t opcode;
+ uint16_t sa;
+ uint8_t ctdp;
+ uint8_t servactv;
+ uint16_t cdb_len;
+
+ /* only present if CTDP==1 */
+ struct scsi_op_timeout_descriptor to;
};
struct scsi_report_supported_op_codes {
- uint32_t num_descriptors;
+ int num_descriptors;
struct scsi_command_descriptor descriptors[0];
};
diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c
index 3c02ace..c091539 100644
--- a/lib/scsi-lowlevel.c
+++ b/lib/scsi-lowlevel.c
@@ -806,12 +806,6 @@ scsi_persistentreservein_datain_unmarshall(struct scsi_task *task)
}
}
-static inline int
-scsi_maintenancein_return_timeouts(const struct scsi_task *task)
-{
- return task->cdb[2] & 0x80;
-}
-
static inline uint8_t
scsi_maintenancein_sa(const struct scsi_task *task)
{
@@ -841,9 +835,7 @@ static void *
scsi_maintenancein_datain_unmarshall(struct scsi_task *task)
{
struct scsi_report_supported_op_codes *rsoc;
- struct scsi_command_descriptor *desc, *datain;
- uint32_t len, i;
- int return_timeouts, desc_size;
+ int len, i;
switch (scsi_maintenancein_sa(task)) {
case SCSI_REPORT_SUPPORTED_OP_CODES:
@@ -852,37 +844,52 @@ scsi_maintenancein_datain_unmarshall(struct scsi_task *task)
}
len = task_get_uint32(task, 0);
- rsoc = scsi_malloc(task, sizeof(struct scsi_report_supported_op_codes) + len);
+ /* len / 8 is not always correct since if CTDP==1 then the
+ * descriptor is 20 bytes in size intead of 8.
+ * It doesnt matter here though since it just means we would
+ * allocate more descriptors at the end of the structure than
+ * we strictly need. This avoids having to traverse the
+ * datain buffer twice.
+ */
+ rsoc = scsi_malloc(task,
+ offsetof(struct scsi_report_supported_op_codes,
+ descriptors) +
+ len / 8 * sizeof(struct scsi_command_descriptor));
if (rsoc == NULL) {
return NULL;
}
- /* Does the descriptor include command timeout info? */
- return_timeouts = scsi_maintenancein_return_timeouts(task);
- /* Size of descriptor depends on whether timeout included. */
- desc_size = sizeof (struct scsi_command_descriptor);
- if (return_timeouts) {
- desc_size += sizeof (struct scsi_op_timeout_descriptor);
- }
- rsoc->num_descriptors = len / desc_size;
-
- desc = &rsoc->descriptors[0];
- datain = (struct scsi_command_descriptor *)&task->datain.data[4];
-
- for (i=0; i < rsoc->num_descriptors; i++) {
- desc->op_code = datain->op_code;
- desc->service_action = ntohs(datain->service_action);
- desc->cdb_length = ntohs(datain->cdb_length);
- if (return_timeouts) {
- desc->to[0].descriptor_length = ntohs(datain->to[0].descriptor_length);
- desc->to[0].command_specific = datain->to[0].command_specific;
- desc->to[0].nominal_processing_timeout
- = ntohl(datain->to[0].nominal_processing_timeout);
- desc->to[0].recommended_timeout
- = ntohl(datain->to[0].recommended_timeout);
+ rsoc->num_descriptors = 0;
+ i = 4;
+ while (len >= 8) {
+ struct scsi_command_descriptor *desc;
+
+ desc = &rsoc->descriptors[rsoc->num_descriptors++];
+ desc->opcode = task_get_uint8(task, i);
+ desc->sa = task_get_uint16(task, i + 2);
+ desc->ctdp = !!(task_get_uint8(task, i + 5) & 0x02);
+ desc->servactv = !!(task_get_uint8(task, i + 5) & 0x01);
+ desc->cdb_len = task_get_uint16(task, i + 6);
+
+ len -= 8;
+ i += 8;
+
+ /* No tiemout description */
+ if (!desc->ctdp) {
+ continue;
}
- desc = (struct scsi_command_descriptor *)((char *)desc + desc_size);
- datain = (struct scsi_command_descriptor *)((char *)datain + desc_size);
+
+ desc->to.descriptor_length =
+ task_get_uint16(task, i);
+ desc->to.command_specific =
+ task_get_uint8(task, i + 3);
+ desc->to.nominal_processing_timeout =
+ task_get_uint32(task, i + 4);
+ desc->to.recommended_timeout =
+ task_get_uint32(task, i + 8);
+
+ len -= desc->to.descriptor_length + 2;
+ i += desc->to.descriptor_length + 2;
}
return rsoc;

78
SOURCES/0016-avoid-casting-struct-sockaddr.patch

@ -0,0 +1,78 @@ @@ -0,0 +1,78 @@
From 73ce7f40c81f7ef2647abe18df8f14c35c086c7e Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 2 Aug 2013 14:19:29 +0200
Subject: [RHEL7 libiscsi PATCH 16/18] avoid casting struct sockaddr

On ARM, this produces a warning. Use a union instead.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from upstream commit 73ce7f40c81f7ef2647abe18df8f14c35c086c7e)
---
lib/socket.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/lib/socket.c b/lib/socket.c
index 5d98783..2c65a4a 100644
--- a/lib/socket.c
+++ b/lib/socket.c
@@ -171,6 +171,12 @@ int set_tcp_syncnt(struct iscsi_context *iscsi)
return 0;
}
+union socket_address {
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ struct sockaddr sa;
+};
+
int
iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
iscsi_command_cb cb, void *private_data)
@@ -179,6 +185,7 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
char *str;
char *addr, *host;
struct addrinfo *ai = NULL;
+ union socket_address sa;
int socksize;
ISCSI_LOG(iscsi, 2, "connecting to portal %s",portal);
@@ -238,19 +245,22 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
}
iscsi_free(iscsi, addr);
+ memset(&sa, 0, sizeof(sa));
switch (ai->ai_family) {
case AF_INET:
socksize = sizeof(struct sockaddr_in);
- ((struct sockaddr_in *)(ai->ai_addr))->sin_port = htons(port);
+ memcpy(&sa.sin, ai->ai_addr, socksize);
+ sa.sin.sin_port = htons(port);
#ifdef HAVE_SOCK_SIN_LEN
- ((struct sockaddr_in *)(ai->ai_addr))->sin_len = socksize;
+ sa.sin.sin_len = socksize;
#endif
break;
case AF_INET6:
socksize = sizeof(struct sockaddr_in6);
- ((struct sockaddr_in6 *)(ai->ai_addr))->sin6_port = htons(port);
+ memcpy(&sa.sin6, ai->ai_addr, socksize);
+ sa.sin6.sin6_port = htons(port);
#ifdef HAVE_SOCK_SIN_LEN
- ((struct sockaddr_in6 *)(ai->ai_addr))->sin6_len = socksize;
+ sa.sin6.sin6_len = socksize;
#endif
break;
default:
@@ -316,7 +325,7 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
ISCSI_LOG(iscsi,3,"TCP_NODELAY set to 1");
}
- if (connect(iscsi->fd, ai->ai_addr, socksize) != 0
+ if (connect(iscsi->fd, &sa.sa, socksize) != 0
&& errno != EINPROGRESS) {
iscsi_set_error(iscsi, "Connect failed with errno : "
"%s(%d)", strerror(errno), errno);
--
1.8.1.4

91
SOURCES/0018-cleanup-rename-pdu-written.patch

@ -0,0 +1,91 @@ @@ -0,0 +1,91 @@
From 6cb88eb0ce8faa4b417c3abd1a9b09d4f707037c Mon Sep 17 00:00:00 2001
From: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Date: Sun, 4 Aug 2013 17:27:29 -0700
Subject: [RHEL7 libiscsi PATCH 17/18] Cleanup: rename pdu->written -> pdu->outdata_written

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from upstream commit 6cb88eb0ce8faa4b417c3abd1a9b09d4f707037c)
---
include/iscsi-private.h | 4 ++--
lib/connect.c | 2 +-
lib/socket.c | 16 ++++++----------
3 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/include/iscsi-private.h b/include/iscsi-private.h
index df20702..d386988 100644
--- a/include/iscsi-private.h
+++ b/include/iscsi-private.h
@@ -221,9 +221,9 @@ struct iscsi_pdu {
iscsi_command_cb callback;
void *private_data;
- int written;
-
struct iscsi_data outdata; /* Header for PDU to send */
+ size_t outdata_written; /* How much of the header we have written */
+
uint32_t out_offset; /* Offset into data-out iovector */
uint32_t out_len; /* Amount of data to sent starting at out_offset */
uint32_t out_written; /* Number of bytes written to socket */
diff --git a/lib/connect.c b/lib/connect.c
index 7790253..732e0cf 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -343,7 +343,7 @@ try_again:
iscsi_pdu_set_expstatsn(pdu, iscsi->statsn);
iscsi->statsn++;
- pdu->written = 0;
+ pdu->outdata_written = 0;
pdu->out_written = 0;
iscsi_add_to_outqueue(iscsi, pdu);
}
diff --git a/lib/socket.c b/lib/socket.c
index 375cfd2..f94bb1c 100644
--- a/lib/socket.c
+++ b/lib/socket.c
@@ -596,8 +596,6 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
}
while (iscsi->outqueue != NULL || iscsi->outqueue_current != NULL) {
- ssize_t total;
-
if (iscsi->outqueue_current == NULL) {
if (iscsi_serial32_compare(iscsi->outqueue->cmdsn, iscsi->maxcmdsn) > 0) {
/* stop sending. maxcmdsn is reached */
@@ -616,15 +614,13 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
}
pdu = iscsi->outqueue_current;
-
- total = pdu->outdata.size;
- total = (total + 3) & 0xfffffffc;
+ pdu->outdata.size = (pdu->outdata.size + 3) & 0xfffffffc;
/* Write header and any immediate data */
- if (pdu->written < total) {
+ if (pdu->outdata_written < pdu->outdata.size) {
count = send(iscsi->fd,
- pdu->outdata.data + pdu->written,
- total - pdu->written,
+ pdu->outdata.data + pdu->outdata_written,
+ pdu->outdata.size - pdu->outdata_written,
0);
if (count == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
@@ -634,10 +630,10 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
"socket :%d", errno);
return -1;
}
- pdu->written += count;
+ pdu->outdata_written += count;
}
/* if we havent written the full header yet. */
- if (pdu->written != total) {
+ if (pdu->outdata_written != pdu->outdata.size) {
return 0;
}
--
1.8.3.1

155
SOURCES/0019-fix-iovec-short-reads.patch

@ -0,0 +1,155 @@ @@ -0,0 +1,155 @@
From 73b0d4777f90ec6e1f0a81f9e4c21830fb58c9b7 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Subject: [RHEL7 libiscsi PATCH 18/18] Ignore padding when an iovector is supplied

The iSCSI protocol adds padding to a data packet if the data size is not
a multiple of four. The iovector provided by QEMU does not include such
padding, and libiscsi then complains that there was a protocol error.
This patch fixes this by reading the padding in a separate "recv"
system call. These packets anyway do not happen in the data path,
where the packet size is a multiple of 512.

Similarly, we need to write padding after an outgoing data packet.

This fixes QEMU's scsi-generic backend, which triggered the problem when
the target sent a 66-byte INQUIRY response.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from upstream commit 73b0d4777f90ec6e1f0a81f9e4c21830fb58c9b7)
---
diff --git a/include/iscsi-private.h b/include/iscsi-private.h
index e9b9e7e..6cc8a20 100644
--- a/include/iscsi-private.h
+++ b/include/iscsi-private.h
@@ -261,6 +261,7 @@ struct scsi_task;
void iscsi_pdu_set_cdb(struct iscsi_pdu *pdu, struct scsi_task *task);
int iscsi_get_pdu_data_size(const unsigned char *hdr);
+int iscsi_get_pdu_padding_size(const unsigned char *hdr);
int iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in);
int iscsi_process_login_reply(struct iscsi_context *iscsi,
diff --git a/lib/pdu.c b/lib/pdu.c
index f53490a..043a986 100644
--- a/lib/pdu.c
+++ b/lib/pdu.c
@@ -217,11 +217,22 @@ iscsi_get_pdu_data_size(const unsigned char *hdr)
int size;
size = scsi_get_uint32(&hdr[4]) & 0x00ffffff;
- size = (size+3) & 0xfffffffc;
return size;
}
+
+int
+iscsi_get_pdu_padding_size(const unsigned char *hdr)
+{
+ int data_size, padded_size;
+
+ data_size = scsi_get_uint32(&hdr[4]) & 0x00ffffff;
+ padded_size = (data_size+3) & 0xfffffffc;
+
+ return padded_size - data_size;
+}
+
enum iscsi_reject_reason {
ISCSI_REJECT_RESERVED = 0x01,
ISCSI_REJECT_DATA_DIGEST_ERROR = 0x02,
diff --git a/lib/socket.c b/lib/socket.c
index 13020ee..7a668c2 100644
--- a/lib/socket.c
+++ b/lib/socket.c
@@ -479,7 +479,7 @@ static int
iscsi_read_from_socket(struct iscsi_context *iscsi)
{
struct iscsi_in_pdu *in;
- ssize_t data_size, count;
+ ssize_t data_size, count, padding_size;
if (iscsi->incoming == NULL) {
iscsi->incoming = iscsi_zmalloc(iscsi, sizeof(struct iscsi_in_pdu));
@@ -516,31 +516,36 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
return 0;
}
- data_size = iscsi_get_pdu_data_size(&in->hdr[0]);
+ padding_size = iscsi_get_pdu_padding_size(&in->hdr[0]);
+ data_size = iscsi_get_pdu_data_size(&in->hdr[0]) + padding_size;
+
if (data_size < 0 || data_size > (ssize_t)iscsi->initiator_max_recv_data_segment_length) {
iscsi_set_error(iscsi, "Invalid data size received from target (%d)", (int)data_size);
return -1;
}
if (data_size != 0) {
- unsigned char *buf = NULL;
+ unsigned char padding_buf[3];
+ unsigned char *buf = padding_buf;
struct scsi_iovector * iovector_in;
count = data_size - in->data_pos;
/* first try to see if we already have a user buffer */
iovector_in = iscsi_get_scsi_task_iovector_in(iscsi, in);
- if (iovector_in != NULL) {
+ if (iovector_in != NULL && count > padding_size) {
uint32_t offset = scsi_get_uint32(&in->hdr[40]);
- count = iscsi_iovector_readv_writev(iscsi, iovector_in, in->data_pos + offset, count, 0);
+ count = iscsi_iovector_readv_writev(iscsi, iovector_in, in->data_pos + offset, count - padding_size, 0);
} else {
- if (in->data == NULL) {
- in->data = iscsi_malloc(iscsi, data_size);
+ if (iovector_in == NULL) {
if (in->data == NULL) {
- iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu->data(%d)", (int)data_size);
- return -1;
+ in->data = iscsi_malloc(iscsi, data_size);
+ if (in->data == NULL) {
+ iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu->data(%d)", (int)data_size);
+ return -1;
+ }
}
+ buf = &in->data[in->data_pos];
}
- buf = &in->data[in->data_pos];
count = recv(iscsi->fd, buf, count, 0);
}
@@ -586,6 +591,8 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
{
ssize_t count;
struct iscsi_pdu *pdu;
+ static char padding_buf[3];
+ size_t total;
if (iscsi->fd == -1) {
iscsi_set_error(iscsi, "trying to write but not connected");
@@ -663,6 +669,27 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
pdu->out_written += count;
}
+ total = pdu->out_len;
+ total = (total + 3) & 0xfffffffc;
+
+ /* Write padding */
+ if (pdu->out_written < total) {
+ count = send(iscsi->fd, padding_buf, total - pdu->out_written, 0);
+ if (count == -1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ return 0;
+ }
+ iscsi_set_error(iscsi, "Error when writing to "
+ "socket :%d", errno);
+ return -1;
+ }
+ pdu->out_written += count;
+ }
+ /* if we havent written the full padding yet. */
+ if (pdu->out_written != total) {
+ return 0;
+ }
+
if (pdu->flags & ISCSI_PDU_DELETE_WHEN_SENT) {
iscsi_free_pdu(iscsi, pdu);
}

63
SOURCES/0020-iscsi_reconnect-Fix-a-use-after-free.patch

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
iscsi_reconnect: Fix a use-after-free

Message-id: <1383729402-27559-2-git-send-email-pbonzini@redhat.com>
Patchwork-id: 55496
O-Subject: [PATCH 01/11] iscsi_reconnect: Fix a use-after-free
Bugzilla: 1026820
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>

From: Bart Van Assche <bvanassche@acm.org>

This patch fixes the following Valgrind complaint:

Invalid read of size 4
at 0x524A858: iscsi_reconnect (connect.c:378)
by 0x5258794: iscsi_service (socket.c:707)
by 0x52599C4: event_loop (sync.c:67)
by 0x525AFD7: iscsi_reserve6_sync (sync.c:1096)
by 0x40A40A: reserve6 (iscsi-support.c:3291)
by 0x422C95: test_reserve6_target_warm_reset (test_reserve6_target_warm_reset.c:39)
by 0x503B05F: ??? (in /usr/lib/libcunit.so.1.0.1)
by 0x503B375: ??? (in /usr/lib/libcunit.so.1.0.1)
by 0x503B69F: CU_run_all_tests (in /usr/lib/libcunit.so.1.0.1)
by 0x403171: main (iscsi-test-cu.c:1258)
Address 0x6443958 is 3,032 bytes inside a block of size 4,120 free'd
at 0x4C2B83A: free (vg_replace_malloc.c:468)
by 0x524A846: iscsi_reconnect (connect.c:374)
by 0x5258794: iscsi_service (socket.c:707)
by 0x52599C4: event_loop (sync.c:67)
by 0x525AFD7: iscsi_reserve6_sync (sync.c:1096)
by 0x40A40A: reserve6 (iscsi-support.c:3291)
by 0x422C95: test_reserve6_target_warm_reset (test_reserve6_target_warm_reset.c:39)
by 0x503B05F: ??? (in /usr/lib/libcunit.so.1.0.1)
by 0x503B375: ??? (in /usr/lib/libcunit.so.1.0.1)
by 0x503B69F: CU_run_all_tests (in /usr/lib/libcunit.so.1.0.1)
by 0x403171: main (iscsi-test-cu.c:1258)

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
(cherry picked from commit 4653cd8df4c14f4eea37b6ce66277330774dd3d5)
---
lib/connect.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/connect.c b/lib/connect.c
index bcb9d3b..0d4c957 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -356,13 +356,13 @@ try_again:
iscsi->mallocs+=old_iscsi->mallocs;
iscsi->frees+=old_iscsi->frees;
+ ISCSI_LOG(iscsi, 2, "reconnect was successful");
+
memcpy(old_iscsi, iscsi, sizeof(struct iscsi_context));
- memset(iscsi, 0, sizeof(struct iscsi_context));
free(iscsi);
old_iscsi->is_reconnecting = 0;
old_iscsi->last_reconnect = time(NULL);
- ISCSI_LOG(iscsi, 2, "reconnect was successful");
return 0;
}

38
SOURCES/0021-Dont-reference-pdu-after-it-has-been-freed.patch

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
Dont reference *pdu after it has been freed

Message-id: <1383729402-27559-3-git-send-email-pbonzini@redhat.com>
Patchwork-id: 55497
O-Subject: [PATCH 02/11] Dont reference *pdu after it has been freed
Bugzilla: 1026820
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>

From: Ronnie Sahlberg <ronniesahlberg@gmail.com>

(cherry picked from commit 804c5b02112d84c79460e7b2a01fe42f0ca5e687)
---
lib/iscsi-command.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/iscsi-command.c b/lib/iscsi-command.c
index e52612d..95127a5 100644
--- a/lib/iscsi-command.c
+++ b/lib/iscsi-command.c
@@ -1636,7 +1636,7 @@ iscsi_scsi_cancel_all_tasks(struct iscsi_context *iscsi)
{
struct iscsi_pdu *pdu;
- for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) {
+ while ((pdu = iscsi->waitpdu)) {
SLIST_REMOVE(&iscsi->waitpdu, pdu);
if ( !(pdu->flags & ISCSI_PDU_NO_CALLBACK)) {
pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL,
@@ -1644,7 +1644,7 @@ iscsi_scsi_cancel_all_tasks(struct iscsi_context *iscsi)
}
iscsi_free_pdu(iscsi, pdu);
}
- for (pdu = iscsi->outqueue; pdu; pdu = pdu->next) {
+ while ((pdu = iscsi->outqueue)) {
SLIST_REMOVE(&iscsi->outqueue, pdu);
if ( !(pdu->flags & ISCSI_PDU_NO_CALLBACK)) {
pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL,

35
SOURCES/0022-lib-Make-scsi_free_scsi_task-accept-a-NULL-task-pointer.patch

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
lib: Make scsi_free_scsi_task() accept a NULL task pointer

Message-id: <1383729402-27559-4-git-send-email-pbonzini@redhat.com>
Patchwork-id: 55498
O-Subject: [PATCH 03/11] lib: Make scsi_free_scsi_task() accept a NULL task pointer
Bugzilla: 1026820
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>

From: Bart Van Assche <bvanassche@acm.org>

Several cleanup paths can be simplified if it is allowed to pass a
NULL pointer to scsi_free_scsi_task(). Hence modify this function
such that it returns immediately if passed a NULL task pointer.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
(cherry picked from commit afa076b5377cff7e1b4096965849e7939c399af1)
---
lib/scsi-lowlevel.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c
index ce9f904..0f97a79 100644
--- a/lib/scsi-lowlevel.c
+++ b/lib/scsi-lowlevel.c
@@ -50,6 +50,9 @@ scsi_free_scsi_task(struct scsi_task *task)
{
struct scsi_allocated_memory *mem;
+ if (!task)
+ return;
+
while ((mem = task->mem)) {
SLIST_REMOVE(&task->mem, mem);
free(mem);

103
SOURCES/0023-lib-Fix-a-memory-leak-in-scsi_cdb_persistent_reserve_out.patch

@ -0,0 +1,103 @@ @@ -0,0 +1,103 @@
lib: Fix a memory leak in scsi_cdb_persistent_reserve_out()

Message-id: <1383729402-27559-5-git-send-email-pbonzini@redhat.com>
Patchwork-id: 55499
O-Subject: [PATCH 04/11] lib: Fix a memory leak in scsi_cdb_persistent_reserve_out()
Bugzilla: 1026820
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>

From: Bart Van Assche <bvanassche@acm.org>

If scsi_cdb_persistent_reserve_out() succeeds a call to
scsi_free_scsi_task() won't free any memory allocated with scsi_malloc()
in this function because the memset() call in this function overwrites
the task->mem pointer. Move the memset() call up such that it doesn't
clear task->mem. This makes it possible for the caller of this function
to free the memory allocated by this function by calling
scsi_free_scsi_task(). Merge the error handling code such that the code
for freeing memory only occurs once.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
(cherry picked from commit 3fdc3f2327939174b1691eca6a55915cc3e08b8b)
---
The problem reported by Coverity is that scsi_malloc accesses
task->mem, which is uninitialized.

lib/scsi-lowlevel.c | 37 +++++++++++++++----------------------
1 file changed, 15 insertions(+), 22 deletions(-)
diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c
index 0f97a79..28d0a08 100644
--- a/lib/scsi-lowlevel.c
+++ b/lib/scsi-lowlevel.c
@@ -1874,15 +1874,14 @@ scsi_cdb_persistent_reserve_out(enum scsi_persistent_out_sa sa, enum scsi_persis
int xferlen;
task = malloc(sizeof(struct scsi_task));
- if (task == NULL) {
- return NULL;
- }
+ if (task == NULL)
+ goto err;
+
+ memset(task, 0, sizeof(struct scsi_task));
iov = scsi_malloc(task, sizeof(struct scsi_iovec));
- if (iov == NULL) {
- free(task);
- return NULL;
- }
+ if (iov == NULL)
+ goto err;
switch(sa) {
case SCSI_PERSISTENT_RESERVE_REGISTER:
@@ -1896,11 +1895,8 @@ scsi_cdb_persistent_reserve_out(enum scsi_persistent_out_sa sa, enum scsi_persis
xferlen = 24;
buf = scsi_malloc(task, xferlen);
- if (buf == NULL) {
- free(task);
- free(iov);
- return NULL;
- }
+ if (buf == NULL)
+ goto err;
memset(buf, 0, xferlen);
scsi_set_uint64(&buf[0], basic->reservation_key);
@@ -1917,19 +1913,12 @@ scsi_cdb_persistent_reserve_out(enum scsi_persistent_out_sa sa, enum scsi_persis
break;
case SCSI_PERSISTENT_RESERVE_REGISTER_AND_MOVE:
/* XXX FIXME */
- free(task);
- free(iov);
- return NULL;
+ goto err;
default:
- free(task);
- free(iov);
- return NULL;
+ goto err;
}
-
- memset(task, 0, sizeof(struct scsi_task));
- task->cdb[0] = SCSI_OPCODE_PERSISTENT_RESERVE_OUT;
-
+ task->cdb[0] = SCSI_OPCODE_PERSISTENT_RESERVE_OUT;
task->cdb[1] |= sa & 0x1f;
task->cdb[2] = ((scope << 4) & 0xf0) | (type & 0x0f);
@@ -1944,6 +1933,10 @@ scsi_cdb_persistent_reserve_out(enum scsi_persistent_out_sa sa, enum scsi_persis
scsi_task_set_iov_out(task, iov, 1);
return task;
+
+err:
+ scsi_free_scsi_task(task);
+ return NULL;
}
/*

77
SOURCES/0024-reconnect-do-not-initialize-iscsi-to-old_iscsi-use-old_iscsi-if-appropriate.patch

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
reconnect: do not initialize iscsi to old_iscsi, use old_iscsi if appropriate

Message-id: <1383729402-27559-6-git-send-email-pbonzini@redhat.com>
Patchwork-id: 55500
O-Subject: [PATCH 05/11] reconnect: do not initialize iscsi to old_iscsi, use old_iscsi if appropriate
Bugzilla: 1026820
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>

Makes it clearer that logging has to be done on the existing context,
since the "iscsi" pointer will not survive iscsi_reconnect.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit c3e8d0c9454835074ebcc6971618b2e71bb948c4)

Conflicts:
lib/connect.c
---
lib/connect.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/lib/connect.c b/lib/connect.c
index 0d4c957..d6a8759 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -217,22 +217,22 @@ void iscsi_defer_reconnect(struct iscsi_context *iscsi)
int iscsi_reconnect(struct iscsi_context *old_iscsi)
{
- struct iscsi_context *iscsi = old_iscsi;
+ struct iscsi_context *iscsi;
/* if there is already a deferred reconnect do not try again */
- if (iscsi->reconnect_deferred) {
- ISCSI_LOG(iscsi, 2, "reconnect initiated, but reconnect is already deferred");
+ if (old_iscsi->reconnect_deferred) {
+ ISCSI_LOG(old_iscsi, 2, "reconnect initiated, but reconnect is already deferred");
return -1;
}
- ISCSI_LOG(iscsi, 2, "reconnect initiated");
+ ISCSI_LOG(old_iscsi, 2, "reconnect initiated");
/* This is mainly for tests, where we do not want to automatically
reconnect but rather want the commands to fail with an error
if the target drops the session.
*/
- if (iscsi->no_auto_reconnect) {
- iscsi_defer_reconnect(iscsi);
+ if (old_iscsi->no_auto_reconnect) {
+ iscsi_defer_reconnect(old_iscsi);
return 0;
}
@@ -288,7 +288,7 @@ try_again:
if (backoff > 30) {
backoff=30;
}
- ISCSI_LOG(iscsi, 1, "reconnect try %d failed, waiting %d seconds",retry,backoff);
+ ISCSI_LOG(old_iscsi, 1, "reconnect try %d failed, waiting %d seconds", retry, backoff);
iscsi_destroy_context(iscsi);
sleep(backoff);
retry++;
@@ -356,11 +356,11 @@ try_again:
iscsi->mallocs+=old_iscsi->mallocs;
iscsi->frees+=old_iscsi->frees;
- ISCSI_LOG(iscsi, 2, "reconnect was successful");
-
memcpy(old_iscsi, iscsi, sizeof(struct iscsi_context));
free(iscsi);
+ ISCSI_LOG(old_iscsi, 2, "reconnect was successful");
+
old_iscsi->is_reconnecting = 0;
old_iscsi->last_reconnect = time(NULL);

31
SOURCES/0025-log-failures-typically-malloc-of-iscsi_create_context-during-reconnect.patch

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
log failures (typically malloc) of iscsi_create_context during reconnect

Message-id: <1383729402-27559-7-git-send-email-pbonzini@redhat.com>
Patchwork-id: 55501
O-Subject: [PATCH 06/11] log failures (typically malloc) of iscsi_create_context during reconnect
Bugzilla: 1026820
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 1acce4a94892ffc8fb75945fc2d2ee691b66a524)
---
lib/connect.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lib/connect.c b/lib/connect.c
index d6a8759..cd3f336 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -245,6 +245,11 @@ int iscsi_reconnect(struct iscsi_context *old_iscsi)
try_again:
iscsi = iscsi_create_context(old_iscsi->initiator_name);
+ if (!iscsi) {
+ ISCSI_LOG(old_iscsi, 2, "failed to create new context for reconnection");
+ return -1;
+ }
+
iscsi->is_reconnecting = 1;
iscsi_set_targetname(iscsi, old_iscsi->target_name);

27
SOURCES/0026-exit-after-malloc-failure-when-allocating-sense-data-blob.patch

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
exit after malloc failure when allocating sense data blob

Message-id: <1383729402-27559-8-git-send-email-pbonzini@redhat.com>
Patchwork-id: 55502
O-Subject: [PATCH 07/11] exit after malloc failure when allocating sense data blob
Bugzilla: 1026820
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit dbaa0b4ea6a4ca11d279a4264457ccb1ad4f67ad)
---
lib/iscsi-command.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/iscsi-command.c b/lib/iscsi-command.c
index 95127a5..1191cd6 100644
--- a/lib/iscsi-command.c
+++ b/lib/iscsi-command.c
@@ -365,6 +365,7 @@ iscsi_process_scsi_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
if (task->datain.data == NULL) {
iscsi_set_error(iscsi, "failed to allocate blob for "
"sense data");
+ break;
}
memcpy(task->datain.data, in->data, task->datain.size);

79
SOURCES/0027-do-not-test-arrays-against-NULL.patch

@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
do not test arrays against NULL

Message-id: <1383729402-27559-9-git-send-email-pbonzini@redhat.com>
Patchwork-id: 55503
O-Subject: [PATCH 08/11] do not test arrays against NULL
Bugzilla: 1026820
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit fce94c81a3191a2ba884dcc7a5822b5776004b4f)
---
lib/login.c | 4 ++--
src/iscsi-inq.c | 2 +-
src/iscsi-ls.c | 2 +-
src/iscsi-readcapacity16.c | 2 +-
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/lib/login.c b/lib/login.c
index 7a6b092..22a7408 100644
--- a/lib/login.c
+++ b/lib/login.c
@@ -802,7 +802,7 @@ iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
}
/* optional alias */
- if (iscsi->alias) {
+ if (iscsi->alias[0]) {
if (iscsi_login_add_alias(iscsi, pdu) != 0) {
iscsi_free_pdu(iscsi, pdu);
return -1;
@@ -1097,7 +1097,7 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
size -= len + 1;
}
- if (status == SCSI_STATUS_REDIRECT && iscsi->target_address) {
+ if (status == SCSI_STATUS_REDIRECT && iscsi->target_address[0]) {
ISCSI_LOG(iscsi, 2, "target requests redirect to %s",iscsi->target_address);
pdu->callback(iscsi, SCSI_STATUS_REDIRECT, NULL,
pdu->private_data);
diff --git a/src/iscsi-inq.c b/src/iscsi-inq.c
index d694dad..a12b044 100644
--- a/src/iscsi-inq.c
+++ b/src/iscsi-inq.c
@@ -294,7 +294,7 @@ int main(int argc, const char *argv[])
iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL);
iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
- if (iscsi_url->user != NULL) {
+ if (iscsi_url->user[0]) {
if (iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user, iscsi_url->passwd) != 0) {
fprintf(stderr, "Failed to set initiator username and password\n");
exit(10);
diff --git a/src/iscsi-ls.c b/src/iscsi-ls.c
index 3ffc9bc..10b0e8d 100644
--- a/src/iscsi-ls.c
+++ b/src/iscsi-ls.c
@@ -390,7 +390,7 @@ int main(int argc, const char *argv[])
iscsi_set_session_type(iscsi, ISCSI_SESSION_DISCOVERY);
- if (iscsi_url->user != NULL) {
+ if (iscsi_url->user[0]) {
state.username = iscsi_url->user;
state.password = iscsi_url->passwd;
if (iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user, iscsi_url->passwd) != 0) {
diff --git a/src/iscsi-readcapacity16.c b/src/iscsi-readcapacity16.c
index d286d70..79966ca 100644
--- a/src/iscsi-readcapacity16.c
+++ b/src/iscsi-readcapacity16.c
@@ -137,7 +137,7 @@ int main(int argc, const char *argv[])
iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL);
iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
- if (iscsi_url->user != NULL) {
+ if (iscsi_url->user[0]) {
if (iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user, iscsi_url->passwd) != 0) {
fprintf(stderr, "Failed to set initiator username and password\n");
exit(10);

40
SOURCES/0028-handle-bad-iscsi--fd-in-iscsi_service.patch

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
handle bad iscsi->fd in iscsi_service

Message-id: <1383729402-27559-10-git-send-email-pbonzini@redhat.com>
Patchwork-id: 55504
O-Subject: [PATCH 09/11] handle bad iscsi->fd in iscsi_service
Bugzilla: 1026820
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>

Just do nothing if the file descriptor is invalid.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit bb0e59055aeb69b0b035e2c2f848d8e82c96eade)
---
lib/socket.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/lib/socket.c b/lib/socket.c
index 8f7ebb2..78dfbfe 100644
--- a/lib/socket.c
+++ b/lib/socket.c
@@ -691,6 +691,9 @@ iscsi_service_reconnect_if_loggedin(struct iscsi_context *iscsi)
int
iscsi_service(struct iscsi_context *iscsi, int revents)
{
+ if (iscsi->fd < 0)
+ return 0;
+
if (revents & POLLERR) {
int err = 0;
socklen_t err_size = sizeof(err);
@@ -725,7 +728,7 @@ iscsi_service(struct iscsi_context *iscsi, int revents)
return iscsi_service_reconnect_if_loggedin(iscsi);
}
- if (iscsi->is_connected == 0 && iscsi->fd != -1 && revents&POLLOUT) {
+ if (iscsi->is_connected == 0 && revents&POLLOUT) {
int err = 0;
socklen_t err_size = sizeof(err);
if (getsockopt(iscsi->fd, SOL_SOCKET, SO_ERROR,

145
SOURCES/0029-rework-login-and-discovery-code-to-avoid-strlen-beyond-end-of-data.patch

@ -0,0 +1,145 @@ @@ -0,0 +1,145 @@
rework login and discovery code to avoid strlen beyond end of data

Message-id: <1383729402-27559-11-git-send-email-pbonzini@redhat.com>
Patchwork-id: 55505
O-Subject: [PATCH 10/11] rework login and discovery code to avoid strlen beyond end of data
Bugzilla: 1026820
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>

Checking for the presence of the NUL character should be done
without accessing beyond the PDU datain. Use memchr instead
of strlen, and compute the length only if a NUL character is
actually there.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit bfde49756524bd3748234dc6dfa8015e37176e9b)

Conflicts:
lib/login.c
---
lib/discovery.c | 31 ++++++++++++++++++++-----------
lib/login.c | 32 +++++++++++++++++++++-----------
2 files changed, 41 insertions(+), 22 deletions(-)
diff --git a/lib/discovery.c b/lib/discovery.c
index 1ddf8ef..7396e71 100644
--- a/lib/discovery.c
+++ b/lib/discovery.c
@@ -112,25 +112,34 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
pdu->private_data);
return -1;
}
+ if (size == 0) {
+ iscsi_set_error(iscsi, "size == 0 when parsing "
+ "discovery data");
+ pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
+ pdu->private_data);
+ return -1;
+ }
- while (size > 0) {
+ do {
+ unsigned char *end;
int len;
- len = strlen((char *)ptr);
-
- if (len == 0) {
- break;
- }
-
- if (len > size) {
- iscsi_set_error(iscsi, "len > size when parsing "
- "discovery data %d>%d", len, size);
+ end = memchr(ptr, 0, size);
+ if (end == NULL) {
+ iscsi_set_error(iscsi, "NUL not found after offset %td "
+ "when parsing discovery data",
+ ptr - in->data);
pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
pdu->private_data);
iscsi_free_discovery_addresses(iscsi, targets);
return -1;
}
+ len = end - ptr;
+ if (len == 0) {
+ break;
+ }
+
/* parse the strings */
if (!strncmp((char *)ptr, "TargetName=", 11)) {
struct iscsi_discovery_address *target;
@@ -181,7 +190,7 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
ptr += len + 1;
size -= len + 1;
- }
+ } while (size > 0);
pdu->callback(iscsi, SCSI_STATUS_GOOD, targets, pdu->private_data);
iscsi_free_discovery_addresses(iscsi, targets);
diff --git a/lib/login.c b/lib/login.c
index 22a7408..8b696b0 100644
--- a/lib/login.c
+++ b/lib/login.c
@@ -1000,29 +1000,39 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
iscsi->maxcmdsn = maxcmdsn;
}
+ if (size == 0) {
+ iscsi_set_error(iscsi, "size == 0 when parsing "
+ "login data");
+ pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
+ pdu->private_data);
+ return -1;
+ }
+
/* XXX here we should parse the data returned in case the target
* renegotiated some some parameters.
* we should also do proper handshaking if the target is not yet
* prepared to transition to the next stage
*/
- while (size > 0) {
+ do {
+ char *end;
int len;
- len = strlen(ptr);
-
- if (len == 0) {
- break;
- }
-
- if (len > size) {
- iscsi_set_error(iscsi, "len > size when parsing "
- "login data %d>%d", len, size);
+ end = memchr(ptr, 0, size);
+ if (end == NULL) {
+ iscsi_set_error(iscsi, "NUL not found after offset %td "
+ "when parsing login data",
+ (unsigned char *)ptr - in->data);
pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
pdu->private_data);
return -1;
}
+ len = end - ptr;
+ if (len == 0) {
+ break;
+ }
+
/* parse the strings */
if (!strncmp(ptr, "TargetAddress=", 14)) {
strncpy(iscsi->target_address,ptr+14,MAX_STRING_SIZE);
@@ -1095,7 +1105,7 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
ptr += len + 1;
size -= len + 1;
- }
+ } while (size > 0);
if (status == SCSI_STATUS_REDIRECT && iscsi->target_address[0]) {
ISCSI_LOG(iscsi, 2, "target requests redirect to %s",iscsi->target_address);

36
SOURCES/0030-check-for-a-target-being-there-before-processing-TargetAddress.patch

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
check for a target being there before processing TargetAddress

Message-id: <1383729402-27559-12-git-send-email-pbonzini@redhat.com>
Patchwork-id: 55506
O-Subject: [PATCH 11/11] check for a target being there before processing TargetAddress
Bugzilla: 1026820
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>

Otherwise we access a NULL pointer.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 87ee6456217debfbb9a0180933ed84281e45a705)
---
lib/discovery.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/lib/discovery.c b/lib/discovery.c
index 7396e71..178faef 100644
--- a/lib/discovery.c
+++ b/lib/discovery.c
@@ -169,6 +169,14 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
target->next = targets;
targets = target;
} else if (!strncmp((char *)ptr, "TargetAddress=", 14)) {
+ if (targets == NULL || targets->target_address != NULL) {
+ iscsi_set_error(iscsi, "Invalid discovery "
+ "reply");
+ pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
+ pdu->private_data);
+ iscsi_free_discovery_addresses(iscsi, targets);
+ return -1;
+ }
targets->target_address = iscsi_strdup(iscsi, (char *)ptr+14);
if (targets->target_address == NULL) {
iscsi_set_error(iscsi, "Failed to allocate "

89
SOURCES/0031-fix-CHAP-authentication.patch

@ -0,0 +1,89 @@ @@ -0,0 +1,89 @@
fix CHAP authentication

Message-id: <1386865659-20686-1-git-send-email-pbonzini@redhat.com>
Patchwork-id: 56264
O-Subject: [RHEL7.0 libiscsi PATCH] fix CHAP authentication
Bugzilla: 1032358
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Bandan Das <bsd@redhat.com>
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>

Empty discovery and login packets are legal, and have the same behavior
as packets with a single NUL in them. Introduced by commit 94d73fc
(Merge pull request #83 from bonzini/coverity, 2013-11-05).

Reported-by: John Ferlan <jferlan@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
See the rhvirt-patches message with ID
<1383729402-27559-11-git-send-email-pbonzini@redhat.com>

lib/discovery.c | 11 ++---------
lib/login.c | 12 ++----------
2 files changed, 4 insertions(+), 19 deletions(-)
diff --git a/lib/discovery.c b/lib/discovery.c
index 8301bea..2870bd6 100644
--- a/lib/discovery.c
+++ b/lib/discovery.c
@@ -118,15 +118,8 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
pdu->private_data);
return -1;
}
- if (size == 0) {
- iscsi_set_error(iscsi, "size == 0 when parsing "
- "discovery data");
- pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
- pdu->private_data);
- return -1;
- }
- do {
+ while (size > 0) {
unsigned char *end;
int len;
@@ -204,7 +197,7 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
ptr += len + 1;
size -= len + 1;
- } while (size > 0);
+ }
pdu->callback(iscsi, SCSI_STATUS_GOOD, targets, pdu->private_data);
iscsi_free_discovery_addresses(iscsi, targets);
diff --git a/lib/login.c b/lib/login.c
index 9a7347f..c524108 100644
--- a/lib/login.c
+++ b/lib/login.c
@@ -982,21 +982,13 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
iscsi->maxcmdsn = maxcmdsn;
}
- if (size == 0) {
- iscsi_set_error(iscsi, "size == 0 when parsing "
- "login data");
- pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
- pdu->private_data);
- return -1;
- }
-
/* XXX here we should parse the data returned in case the target
* renegotiated some some parameters.
* we should also do proper handshaking if the target is not yet
* prepared to transition to the next stage
*/
- do {
+ while (size > 0) {
char *end;
int len;
@@ -1087,7 +1079,7 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
ptr += len + 1;
size -= len + 1;
- } while (size > 0);
+ }
if (status == SCSI_STATUS_REDIRECT && iscsi->target_address[0]) {
ISCSI_LOG(iscsi, 2, "target requests redirect to %s",iscsi->target_address);

81
SOURCES/libiscsi-Discovery-return-multiple-portals-for-the-same-disco.patch

@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
From 3f8029f837ef6680e280eb700d5930c1b38dbc27 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Thu, 7 Apr 2016 13:33:14 +0200
Subject: [PATCH 1/2] Discovery: return multiple portals for the same
discovered target

RH-Author: Paolo Bonzini <pbonzini@redhat.com>
Message-id: <1460035995-9887-2-git-send-email-pbonzini@redhat.com>
Patchwork-id: 69977
O-Subject: [RHEL7.3 libiscsi PATCH 1/2] Discovery: return multiple portals for the same discovered target
Bugzilla: 1266523
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Thomas Huth <thuth@redhat.com>
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>

Some targets return multiple TargetAddress for individual targets.
Upstream added a list of addresses for each target, here we do not
want to break the ABI and thus return the same target name multiple
times. Either way, failing the discovery is wrong.

The patch is very different from upstream commit
354f00fd4f63abec86ed0b9b64db1933936283b0, but the effect on
the operation of iscsi-ls is the same.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
lib/discovery.c | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/lib/discovery.c b/lib/discovery.c
index b5d918b..e504cf8 100644
--- a/lib/discovery.c
+++ b/lib/discovery.c
@@ -162,7 +162,7 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
target->next = targets;
targets = target;
} else if (!strncmp((char *)ptr, "TargetAddress=", 14)) {
- if (targets == NULL || targets->target_address != NULL) {
+ if (targets == NULL) {
iscsi_set_error(iscsi, "Invalid discovery "
"reply");
pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
@@ -170,6 +170,34 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
iscsi_free_discovery_addresses(iscsi, targets);
return -1;
}
+ if (targets->target_address != NULL) {
+ struct iscsi_discovery_address *target;
+
+ target = iscsi_zmalloc(iscsi, sizeof(struct iscsi_discovery_address));
+ if (target == NULL) {
+ iscsi_set_error(iscsi, "Failed to allocate "
+ "data for new discovered "
+ "target");
+ pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
+ pdu->private_data);
+ iscsi_free_discovery_addresses(iscsi, targets);
+ return -1;
+ }
+ target->target_name = iscsi_strdup(iscsi, targets->target_name);
+ if (target->target_name == NULL) {
+ iscsi_set_error(iscsi, "Failed to allocate "
+ "data for new discovered "
+ "target name");
+ pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
+ pdu->private_data);
+ iscsi_free(iscsi, target);
+ target = NULL;
+ iscsi_free_discovery_addresses(iscsi, targets);
+ return -1;
+ }
+ target->next = targets;
+ targets = target;
+ }
targets->target_address = iscsi_strdup(iscsi, (char *)ptr+14);
if (targets->target_address == NULL) {
iscsi_set_error(iscsi, "Failed to allocate "
--
1.8.3.1

45
SOURCES/libiscsi-iscsi-ls-skip-link-local-IPv6-addresses.patch

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
From ef6a90973cae8b047bdcbc3fcf14206efc98955a Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Thu, 7 Apr 2016 13:33:15 +0200
Subject: [PATCH 2/2] iscsi-ls: skip link-local IPv6 addresses

RH-Author: Paolo Bonzini <pbonzini@redhat.com>
Message-id: <1460035995-9887-3-git-send-email-pbonzini@redhat.com>
Patchwork-id: 69978
O-Subject: [RHEL7.3 libiscsi PATCH 2/2] iscsi-ls: skip link-local IPv6 addresses
Bugzilla: 1266523
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Thomas Huth <thuth@redhat.com>
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>

Some iSCSI targets provide a link-local IPv6 address as a portal, but that
is unusable without knowing the interface (aka scope-id) to use for the
connection. This causes iscsi-ls to report an EINVAL and exit. Just
skip the error.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit d84ee65eaad902bb41fa6bae1f8127e03cb63506)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
src/iscsi-ls.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/src/iscsi-ls.c b/src/iscsi-ls.c
index 10b0e8d..d11806c 100644
--- a/src/iscsi-ls.c
+++ b/src/iscsi-ls.c
@@ -156,6 +156,11 @@ void list_luns(struct client_state *clnt, const char *target, const char *portal
int full_report_size;
int i;
+ if (strncasecmp(portal, "[fe80:", 6) == 0) {
+ fprintf(stderr, "skipping link-local address\n");
+ return;
+ }
+
iscsi = iscsi_create_context(initiator);
if (iscsi == NULL) {
printf("Failed to create context\n");
--
1.8.3.1

206
SPECS/libiscsi.spec

@ -0,0 +1,206 @@ @@ -0,0 +1,206 @@
Name: libiscsi
Summary: iSCSI client library
Version: 1.9.0
Release: 7%{?dist}
License: LGPLv2+
Group: System Environment/Libraries
URL: https://github.com/sahlberg/%{name}

Source: https://github.com/downloads/sahlberg/%{name}/%{name}-%{version}.tar.gz
Patch1: 0001-do-not-reconnect-if-reconnect-is-already-defered.patch
Patch2: 0002-fix-leak-of-iscsi_context-in-iscsi_reconnect.patch
Patch3: 0003-Add-ASCQ-codes-related-to-thin-provisioning.patch
Patch4: 0004-Create-safe-16-32-64-bit-accessors-for-reading-from-.patch
Patch5: 0005-fix-bug-in-md5-code.patch
Patch6: 0006-use-libgcrypt-for-MD5.patch
Patch7: 0007-URL-encoded-Targetnames.patch
Patch8: 0008-SCSI-add-a-safe-function-to-read-a-byte-from-the-dat.patch
Patch9: 0009-scsi-lowlevel-do-not-use-unsafe-pointer-casts.patch
Patch10: 0010-Add-a-cast-to-ssize_t.patch
Patch11: 0011-do-not-build-test-tool.patch
Patch12: 0012-bump-soname.patch
Patch13: 0013-disable-ld_iscsi.patch
Patch14: 0014-fix-another-aliasing-problem.patch
Patch15: 0015-fix-arm-aliasing-problem.patch
Patch16: 0016-avoid-casting-struct-sockaddr.patch
Patch18: 0018-cleanup-rename-pdu-written.patch
Patch19: 0019-fix-iovec-short-reads.patch
Patch20: 0020-iscsi_reconnect-Fix-a-use-after-free.patch
Patch21: 0021-Dont-reference-pdu-after-it-has-been-freed.patch
Patch22: 0022-lib-Make-scsi_free_scsi_task-accept-a-NULL-task-pointer.patch
Patch23: 0023-lib-Fix-a-memory-leak-in-scsi_cdb_persistent_reserve_out.patch
Patch24: 0024-reconnect-do-not-initialize-iscsi-to-old_iscsi-use-old_iscsi-if-appropriate.patch
Patch25: 0025-log-failures-typically-malloc-of-iscsi_create_context-during-reconnect.patch
Patch26: 0026-exit-after-malloc-failure-when-allocating-sense-data-blob.patch
Patch27: 0027-do-not-test-arrays-against-NULL.patch
Patch28: 0028-handle-bad-iscsi--fd-in-iscsi_service.patch
Patch29: 0029-rework-login-and-discovery-code-to-avoid-strlen-beyond-end-of-data.patch
Patch30: 0030-check-for-a-target-being-there-before-processing-TargetAddress.patch
Patch31: 0031-fix-CHAP-authentication.patch
# For bz#1266523 - iscsi-ls doesn't work if target has more than one portal
Patch32: libiscsi-Discovery-return-multiple-portals-for-the-same-disco.patch
# For bz#1266523 - iscsi-ls doesn't work if target has more than one portal
Patch33: libiscsi-iscsi-ls-skip-link-local-IPv6-addresses.patch

BuildRequires: autoconf
BuildRequires: automake
BuildRequires: libtool
BuildRequires: popt-devel
BuildRequires: libgcrypt-devel

%description
libiscsi is a library for attaching to iSCSI resources across
a network.


#######################################################################

# Conflict with iscsi-initiator-utils.

%global libiscsi_includedir %{_includedir}/iscsi
%global libiscsi_libdir %{_libdir}/iscsi

%prep
%setup -q
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
%patch24 -p1
%patch25 -p1
%patch26 -p1
%patch27 -p1
%patch28 -p1
%patch29 -p1
%patch30 -p1
%patch31 -p1
%patch32 -p1
%patch33 -p1

%build
sh autogen.sh
%configure --libdir=%{libiscsi_libdir}
make %{?_smp_mflags}

%install
make DESTDIR=$RPM_BUILD_ROOT install pkgconfigdir=%{_libdir}/pkgconfig %{?_smp_mflags}
mkdir -p $RPM_BUILD_ROOT/etc/ld.so.conf.d
echo %{libiscsi_libdir} > $RPM_BUILD_ROOT/etc/ld.so.conf.d/%{name}-%{_arch}.conf
rm $RPM_BUILD_ROOT/%{libiscsi_libdir}/libiscsi.a
rm $RPM_BUILD_ROOT/%{libiscsi_libdir}/libiscsi.la

# Remove "*.old" files
find $RPM_BUILD_ROOT -name "*.old" -exec rm -f {} \;

%post -p /sbin/ldconfig

%postun -p /sbin/ldconfig

%files
%defattr(-,root,root)
%doc COPYING LICENCE-LGPL-2.1.txt README TODO
%{libiscsi_libdir}/libiscsi.so.*
/etc/ld.so.conf.d/*

%package utils
Summary: iSCSI Client Utilities
Group: Applications/System
License: GPLv2+
Requires: %{name}%{?_isa} = %{version}-%{release}

%description utils
The libiscsi-utils package provides a set of assorted utilities to connect
to iSCSI servers without having to set up the Linux iSCSI initiator.

%files utils
%doc COPYING LICENCE-GPL-2.txt LICENCE-LGPL-2.1.txt README TODO
%{_bindir}/iscsi-ls
%{_bindir}/iscsi-inq
%{_bindir}/iscsi-readcapacity16

%package devel
Summary: iSCSI client development libraries
Group: Development/Libraries
Requires: %{name}%{?_isa} = %{version}-%{release}

%description devel
The libiscsi-devel package includes the header files for libiscsi.

%files devel
%defattr(-,root,root)
%doc COPYING LICENCE-LGPL-2.1.txt README TODO
%{libiscsi_includedir}/iscsi.h
%{libiscsi_includedir}/scsi-lowlevel.h
%{libiscsi_libdir}/libiscsi.so
%{_libdir}/pkgconfig/libiscsi.pc

%changelog
* Thu May 26 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.9.0-7.el7
- libiscsi-Discovery-return-multiple-portals-for-the-same-disco.patch [bz#1266523]
- libiscsi-iscsi-ls-skip-link-local-IPv6-addresses.patch [bz#1266523]
- Resolves: bz#1266523
(iscsi-ls doesn't work if target has more than one portal)

* Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 1.9.0-6
- Mass rebuild 2014-01-24

* Thu Jan 16 2014 Miroslav Rezanina <mrezanin@redhat.com> - 1.9.0-5
- fix CHAP authentication (bz #1032358)
- Resolves: #1032358

* Fri Dec 27 2013 Daniel Mach <dmach@redhat.com> - 1.9.0-4
- Mass rebuild 2013-12-27

* Thu Nov 07 2013 Miroslav Rezanina <mrezanin@redhat.com> - 1.9.0-3
- Fixed issues reported by coverity (bz #1026820)
- Do not mark /etc/ld.so.conf.d/ as config (bz #1011126)
- Resolves: #1026820
- Resolves: #1011126

* Tue Aug 27 2013 Paolo Bonzini <pbonzini@redhat.com> - 1.9.0-2
- Add missing patch 11
- Resolves: #979953

* Tue Aug 27 2013 Paolo Bonzini <pbonzini@redhat.com> - 1.9.0-1
- Rebase to 1.9.0
- Cherry-pick selected patches from upstream
- Resolves: #979953

* Thu Aug 1 2013 Paolo Bonzini <pbonzini@redhat.com> - 1.7.0-6
- Add patch 6 to properly support escaped URIs produced by libvirt

* Mon Jul 1 2013 Paolo Bonzini <pbonzini@redhat.com> - 1.7.0-5
- Add patch 5 to silence strict aliasing warnings

* Fri May 3 2013 Paolo Bonzini <pbonzini@redhat.com> - 1.7.0-4
- Add patch 2 for FIPS mode
- Add patch 3 to avoid segmentation fault on iscsi-tools

* Thu Mar 7 2013 Paolo Bonzini <pbonzini@redhat.com> - 1.7.0-3
- Correct license for libiscsi-utils, prefer %%global to %%define
- Add Requires
- Remove %clean section

* Fri Feb 22 2013 Paolo Bonzini <pbonzini@redhat.com> - 1.7.0-2
- Use %config for ld.so.conf.d file.

* Fri Feb 22 2013 Paolo Bonzini <pbonzini@redhat.com> - 1.7.0-1
- Initial version (bug 914752)
Loading…
Cancel
Save