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:
@@ -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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user