diff options
author | trasz <trasz@FreeBSD.org> | 2013-09-24 13:46:13 +0000 |
---|---|---|
committer | trasz <trasz@FreeBSD.org> | 2013-09-24 13:46:13 +0000 |
commit | 02a8f348b2807034c78dfee797d2e3a2c775d7d8 (patch) | |
tree | 7609dc490e0006fd04faf0f5878885bf7080fb56 /sys/cam | |
parent | 28393634c52c62351cee5193ebe7cb3b9a86117f (diff) | |
download | FreeBSD-src-02a8f348b2807034c78dfee797d2e3a2c775d7d8.zip FreeBSD-src-02a8f348b2807034c78dfee797d2e3a2c775d7d8.tar.gz |
Properly ignore PDUs with CmdSN outside of allowed range.
Approved by: re (glebius)
Sponsored by: FreeBSD Foundation
Diffstat (limited to 'sys/cam')
-rw-r--r-- | sys/cam/ctl/ctl_frontend_iscsi.c | 35 |
1 files changed, 18 insertions, 17 deletions
diff --git a/sys/cam/ctl/ctl_frontend_iscsi.c b/sys/cam/ctl/ctl_frontend_iscsi.c index 064285d..299186c 100644 --- a/sys/cam/ctl/ctl_frontend_iscsi.c +++ b/sys/cam/ctl/ctl_frontend_iscsi.c @@ -147,7 +147,7 @@ static int cfiscsi_devid(struct ctl_scsiio *ctsio, int alloc_len); static void cfiscsi_datamove(union ctl_io *io); static void cfiscsi_done(union ctl_io *io); static uint32_t cfiscsi_map_lun(void *arg, uint32_t lun); -static void cfiscsi_pdu_update_cmdsn(const struct icl_pdu *request); +static bool cfiscsi_pdu_update_cmdsn(const struct icl_pdu *request); static void cfiscsi_pdu_handle_nop_out(struct icl_pdu *request); static void cfiscsi_pdu_handle_scsi_command(struct icl_pdu *request); static void cfiscsi_pdu_handle_task_request(struct icl_pdu *request); @@ -182,7 +182,7 @@ cfiscsi_pdu_new_response(struct icl_pdu *request, int flags) return (icl_pdu_new_bhs(request->ip_conn, flags)); } -static void +static bool cfiscsi_pdu_update_cmdsn(const struct icl_pdu *request) { const struct iscsi_bhs_scsi_command *bhssc; @@ -206,7 +206,7 @@ cfiscsi_pdu_update_cmdsn(const struct icl_pdu *request) */ if ((request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) == ISCSI_BHS_OPCODE_SCSI_DATA_OUT) - return; + return (false); /* * We're only using fields common for all the request @@ -226,38 +226,39 @@ cfiscsi_pdu_update_cmdsn(const struct icl_pdu *request) #endif /* - * XXX: The target MUST silently ignore any non-immediate command - * outside of this range or non-immediate duplicates within - * the range. + * The target MUST silently ignore any non-immediate command outside + * of this range. + * + * XXX: ... or non-immediate duplicates within the range. */ - if (cmdsn != cs->cs_cmdsn) { + if (cmdsn < cs->cs_cmdsn || cmdsn > cs->cs_cmdsn + maxcmdsn_delta) { + CFISCSI_SESSION_UNLOCK(cs); CFISCSI_SESSION_WARN(cs, "received PDU with CmdSN %d, " "while expected CmdSN was %d", cmdsn, cs->cs_cmdsn); - cs->cs_cmdsn = cmdsn + 1; - CFISCSI_SESSION_UNLOCK(cs); - return; + return (true); } - /* - * XXX: The CmdSN of the rejected command PDU (if it is a non-immediate - * command) MUST NOT be considered received by the target - * (i.e., a command sequence gap must be assumed for the CmdSN) - */ - if ((request->ip_bhs->bhs_opcode & ISCSI_BHS_OPCODE_IMMEDIATE) == 0) cs->cs_cmdsn++; CFISCSI_SESSION_UNLOCK(cs); + + return (false); } static void cfiscsi_pdu_handle(struct icl_pdu *request) { struct cfiscsi_session *cs; + bool ignore; cs = PDU_SESSION(request); - cfiscsi_pdu_update_cmdsn(request); + ignore = cfiscsi_pdu_update_cmdsn(request); + if (ignore) { + icl_pdu_free(request); + return; + } /* * Handle the PDU; this includes e.g. receiving the remaining |