aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/cam/ctl/ctl.c82
1 files changed, 78 insertions, 4 deletions
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);