2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-05 00:35:33 +00:00

ofp-port: Fix buffer overread parsing Intel custom statistics.

CC: Michal Weglicki <michalx.weglicki@intel.com>
Fixes: 971f4b394c ("netdev: Custom statistics.")
Reported-at: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9445
Signed-off-by: Ben Pfaff <blp@ovn.org>
Signed-off-by: Ian Stokes <ian.stokes@intel.com>
This commit is contained in:
Ben Pfaff
2018-07-27 11:14:43 -07:00
committed by Ian Stokes
parent 51c6a5a3c8
commit 7333c3b1ce

View File

@@ -1597,57 +1597,47 @@ parse_intel_port_stats_rfc2819_property(const struct ofpbuf *payload,
}
static enum ofperr
parse_intel_port_custom_property(const struct ofpbuf *payload,
parse_intel_port_custom_property(struct ofpbuf *payload,
struct ofputil_port_stats *ops)
{
const struct intel_port_custom_stats *custom_stats = payload->data;
const struct intel_port_custom_stats *custom_stats
= ofpbuf_try_pull(payload, sizeof *custom_stats);
if (!custom_stats) {
return OFPERR_OFPBPC_BAD_LEN;
}
ops->custom_stats.size = ntohs(custom_stats->stats_array_size);
ops->custom_stats.counters = xcalloc(ops->custom_stats.size,
sizeof *ops->custom_stats.counters);
uint16_t msg_size = ntohs(custom_stats->length);
uint16_t current_len = sizeof *custom_stats;
uint8_t *current = (uint8_t *)payload->data + current_len;
uint8_t string_size = 0;
uint8_t value_size = 0;
ovs_be64 counter_value = 0;
for (int i = 0; i < ops->custom_stats.size; i++) {
current_len += string_size + value_size;
current += string_size + value_size;
value_size = sizeof(uint64_t);
/* Counter name size */
string_size = *current;
/* Buffer overrun check */
if (current_len + string_size + value_size > msg_size) {
VLOG_WARN_RL(&rl, "Custom statistics buffer overrun! "
"Further message parsing is aborted.");
break;
}
current++;
current_len++;
struct netdev_custom_counter *c = &ops->custom_stats.counters[i];
/* Counter name. */
struct netdev_custom_counter *c = &ops->custom_stats.counters[i];
size_t len = MIN(string_size, sizeof c->name - 1);
memcpy(c->name, current, len);
uint8_t *name_len = ofpbuf_try_pull(payload, sizeof *name_len);
char *name = ofpbuf_try_pull(payload, *name_len);
if (!name_len || !name) {
return OFPERR_OFPBPC_BAD_LEN;
}
size_t len = MIN(*name_len, sizeof c->name - 1);
memcpy(c->name, name, len);
c->name[len] = '\0';
memcpy(&counter_value, current + string_size, value_size);
/* Counter value. */
c->value = ntohll(counter_value);
ovs_be64 *value = ofpbuf_try_pull(payload, sizeof *value);
if (!value) {
return OFPERR_OFPBPC_BAD_LEN;
}
c->value = ntohll(get_unaligned_be64(value));
}
return 0;
}
static enum ofperr
parse_intel_port_stats_property(const struct ofpbuf *payload,
parse_intel_port_stats_property(struct ofpbuf *payload,
uint32_t exp_type,
struct ofputil_port_stats *ops)
{