diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index 96f598a8c740..a772c0fd92e1 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -1101,7 +1101,14 @@ static void ctl_isc_ua(struct ctl_softc *softc, union ctl_ha_msg *msg, int len) { struct ctl_lun *lun; - uint32_t iid = ctl_get_initindex(&msg->hdr.nexus); + uint32_t iid; + + if (len < sizeof(msg->ua)) { + printf("%s: Received truncated message %d < %lu\n", + __func__, len, sizeof(msg->ua)); + ctl_ha_msg_abort(CTL_HA_CHAN_CTL); + return; + } mtx_lock(&softc->ctl_lock); if (msg->hdr.nexus.targ_mapped_lun >= ctl_max_luns || @@ -1113,6 +1120,7 @@ ctl_isc_ua(struct ctl_softc *softc, union ctl_ha_msg *msg, int len) mtx_unlock(&softc->ctl_lock); if (msg->ua.ua_type == CTL_UA_THIN_PROV_THRES && msg->ua.ua_set) memcpy(lun->ua_tpt_info, msg->ua.ua_info, 8); + iid = ctl_get_initindex(&msg->hdr.nexus); if (msg->ua.ua_all) { if (msg->ua.ua_set) ctl_est_ua_all(lun, iid, msg->ua.ua_type); @@ -1136,6 +1144,20 @@ ctl_isc_lun_sync(struct ctl_softc *softc, union ctl_ha_msg *msg, int len) ctl_lun_flags oflags; uint32_t targ_lun; + if (len < offsetof(struct ctl_ha_msg_lun, data[0])) { + printf("%s: Received truncated message %d < %lu\n", + __func__, len, offsetof(struct ctl_ha_msg_lun, data[0])); + ctl_ha_msg_abort(CTL_HA_CHAN_CTL); + return; + } + i = msg->lun.lun_devid_len + msg->lun.pr_key_count * sizeof(pr_key); + if (len < offsetof(struct ctl_ha_msg_lun, data[i])) { + printf("%s: Received truncated message data %d < %lu\n", + __func__, len, offsetof(struct ctl_ha_msg_lun, data[i])); + ctl_ha_msg_abort(CTL_HA_CHAN_CTL); + return; + } + targ_lun = msg->hdr.nexus.targ_mapped_lun; mtx_lock(&softc->ctl_lock); if (targ_lun >= ctl_max_luns || @@ -1206,6 +1228,22 @@ ctl_isc_port_sync(struct ctl_softc *softc, union ctl_ha_msg *msg, int len) struct ctl_lun *lun; int i, new; + if (len < offsetof(struct ctl_ha_msg_port, data[0])) { + printf("%s: Received truncated message %d < %lu\n", + __func__, len, offsetof(struct ctl_ha_msg_port, data[0])); + ctl_ha_msg_abort(CTL_HA_CHAN_CTL); + return; + } + i = msg->port.name_len + msg->port.lun_map_len + + msg->port.port_devid_len + msg->port.target_devid_len + + msg->port.init_devid_len; + if (len < offsetof(struct ctl_ha_msg_port, data[i])) { + printf("%s: Received truncated message data %d < %lu\n", + __func__, len, offsetof(struct ctl_ha_msg_port, data[i])); + ctl_ha_msg_abort(CTL_HA_CHAN_CTL); + return; + } + port = softc->ctl_ports[msg->hdr.nexus.targ_port]; if (port == NULL) { CTL_DEBUG_PRINT(("%s: New port %d\n", __func__, @@ -1317,7 +1355,21 @@ static void ctl_isc_iid_sync(struct ctl_softc *softc, union ctl_ha_msg *msg, int len) { struct ctl_port *port; - int iid; + int i, iid; + + if (len < offsetof(struct ctl_ha_msg_iid, data[0])) { + printf("%s: Received truncated message %d < %lu\n", + __func__, len, offsetof(struct ctl_ha_msg_iid, data[0])); + ctl_ha_msg_abort(CTL_HA_CHAN_CTL); + return; + } + i = msg->iid.name_len; + if (len < offsetof(struct ctl_ha_msg_iid, data[i])) { + printf("%s: Received truncated message data %d < %lu\n", + __func__, len, offsetof(struct ctl_ha_msg_iid, data[i])); + ctl_ha_msg_abort(CTL_HA_CHAN_CTL); + return; + } port = softc->ctl_ports[msg->hdr.nexus.targ_port]; if (port == NULL) { @@ -1343,6 +1395,13 @@ static void ctl_isc_login(struct ctl_softc *softc, union ctl_ha_msg *msg, int len) { + if (len < sizeof(msg->login)) { + printf("%s: Received truncated message %d < %lu\n", + __func__, len, sizeof(msg->login)); + ctl_ha_msg_abort(CTL_HA_CHAN_CTL); + return; + } + if (msg->login.version != CTL_HA_VERSION) { printf("CTL HA peers have different versions %d != %d\n", msg->login.version, CTL_HA_VERSION); @@ -1376,6 +1435,20 @@ ctl_isc_mode_sync(struct ctl_softc *softc, union ctl_ha_msg *msg, int len) u_int i; uint32_t initidx, targ_lun; + if (len < offsetof(struct ctl_ha_msg_mode, data[0])) { + printf("%s: Received truncated message %d < %lu\n", + __func__, len, offsetof(struct ctl_ha_msg_mode, data[0])); + ctl_ha_msg_abort(CTL_HA_CHAN_CTL); + return; + } + i = msg->mode.page_len; + if (len < offsetof(struct ctl_ha_msg_mode, data[i])) { + printf("%s: Received truncated message data %d < %lu\n", + __func__, len, offsetof(struct ctl_ha_msg_mode, data[i])); + ctl_ha_msg_abort(CTL_HA_CHAN_CTL); + return; + } + targ_lun = msg->hdr.nexus.targ_mapped_lun; mtx_lock(&softc->ctl_lock); if (targ_lun >= ctl_max_luns || @@ -1400,7 +1473,7 @@ ctl_isc_mode_sync(struct ctl_softc *softc, union ctl_ha_msg *msg, int len) return; } memcpy(lun->mode_pages.index[i].page_data, msg->mode.data, - lun->mode_pages.index[i].page_len); + min(lun->mode_pages.index[i].page_len, msg->mode.page_len)); initidx = ctl_get_initindex(&msg->hdr.nexus); if (initidx != -1) ctl_est_ua_all(lun, initidx, CTL_UA_MODE_CHANGE); @@ -1437,7 +1510,8 @@ ctl_isc_event_handler(ctl_ha_channel channel, ctl_ha_event event, int param) return; } - CTL_DEBUG_PRINT(("CTL: msg_type %d\n", msg->hdr.msg_type)); + CTL_DEBUG_PRINT(("CTL: msg_type %d len %d\n", + msg->hdr.msg_type, param)); switch (msg->hdr.msg_type) { case CTL_MSG_SERIALIZE: io = ctl_alloc_io(softc->othersc_pool);