summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Pfaff <blp@ovn.org>2017-11-29 17:15:29 +0000
committerBen Pfaff <blp@ovn.org>2017-11-29 09:38:04 -0800
commit21fc1550db3f261d27b6283d92da25ca0266bfb9 (patch)
treebc292f0f101d9ed4ed94c9e14de08161804274b1
parent68a1a88e86f535ae6bf9a08f21f7a10bf99e0fe6 (diff)
downloadopenvswitch-21fc1550db3f261d27b6283d92da25ca0266bfb9.tar.gz
ofp-util: Fix memory leaks on error cases in ofputil_decode_group_mod().
Found by libFuzzer. Reported-by: Bhargava Shastry <bshastry@sec.t-labs.tu-berlin.de> Signed-off-by: Ben Pfaff <blp@ovn.org> Acked-by: Justin Pettit <jpettit@ovn.org> Signed-off-by: Markos Chandras <mchandras@suse.de> Signed-off-by: Ben Pfaff <blp@ovn.org>
-rw-r--r--lib/ofp-util.c88
1 files changed, 51 insertions, 37 deletions
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 7b4d62b99..a29c47370 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -8039,6 +8039,7 @@ ofputil_pull_ofp11_buckets(struct ofpbuf *msg, size_t buckets_length,
if (!ob) {
VLOG_WARN_RL(&bad_ofmsg_rl, "buckets end with %"PRIuSIZE" leftover bytes",
buckets_length);
+ ofputil_bucket_list_destroy(buckets);
return OFPERR_OFPGMFC_BAD_BUCKET;
}
@@ -8046,11 +8047,13 @@ ofputil_pull_ofp11_buckets(struct ofpbuf *msg, size_t buckets_length,
if (ob_len < sizeof *ob) {
VLOG_WARN_RL(&bad_ofmsg_rl, "OpenFlow message bucket length "
"%"PRIuSIZE" is not valid", ob_len);
+ ofputil_bucket_list_destroy(buckets);
return OFPERR_OFPGMFC_BAD_BUCKET;
} else if (ob_len > buckets_length) {
VLOG_WARN_RL(&bad_ofmsg_rl, "OpenFlow message bucket length "
"%"PRIuSIZE" exceeds remaining buckets data size %"PRIuSIZE,
ob_len, buckets_length);
+ ofputil_bucket_list_destroy(buckets);
return OFPERR_OFPGMFC_BAD_BUCKET;
}
buckets_length -= ob_len;
@@ -8769,6 +8772,7 @@ ofputil_pull_ofp11_group_mod(struct ofpbuf *msg, enum ofp_version ofp_version,
&& gm->command == OFPGC11_DELETE
&& !list_is_empty(&gm->buckets)) {
error = OFPERR_OFPGMFC_INVALID_GROUP;
+ ofputil_bucket_list_destroy(&gm->buckets);
}
return error;
@@ -8836,44 +8840,9 @@ ofputil_pull_ofp15_group_mod(struct ofpbuf *msg, enum ofp_version ofp_version,
return error;
}
-/* Converts OpenFlow group mod message 'oh' into an abstract group mod in
- * 'gm'. Returns 0 if successful, otherwise an OpenFlow error code. */
-enum ofperr
-ofputil_decode_group_mod(const struct ofp_header *oh,
- struct ofputil_group_mod *gm)
+static enum ofperr
+ofputil_check_group_mod(const struct ofputil_group_mod *gm)
{
- enum ofp_version ofp_version = oh->version;
- struct ofpbuf msg;
- struct ofputil_bucket *bucket;
- enum ofperr err;
-
- ofpbuf_use_const(&msg, oh, ntohs(oh->length));
- ofpraw_pull_assert(&msg);
-
- ofputil_init_group_properties(&gm->props);
-
- switch (ofp_version)
- {
- case OFP11_VERSION:
- case OFP12_VERSION:
- case OFP13_VERSION:
- case OFP14_VERSION:
- err = ofputil_pull_ofp11_group_mod(&msg, ofp_version, gm);
- break;
-
- case OFP15_VERSION:
- err = ofputil_pull_ofp15_group_mod(&msg, ofp_version, gm);
- break;
-
- case OFP10_VERSION:
- default:
- OVS_NOT_REACHED();
- }
-
- if (err) {
- return err;
- }
-
switch (gm->type) {
case OFPGT11_INDIRECT:
if (!list_is_singleton(&gm->buckets)) {
@@ -8903,6 +8872,7 @@ ofputil_decode_group_mod(const struct ofp_header *oh,
return OFPERR_OFPGMFC_BAD_COMMAND;
}
+ struct ofputil_bucket *bucket;
LIST_FOR_EACH (bucket, list_node, &gm->buckets) {
if (bucket->weight && gm->type != OFPGT11_SELECT) {
return OFPERR_OFPGMFC_INVALID_GROUP;
@@ -8930,6 +8900,50 @@ ofputil_decode_group_mod(const struct ofp_header *oh,
return 0;
}
+/* Converts OpenFlow group mod message 'oh' into an abstract group mod in
+ * 'gm'. Returns 0 if successful, otherwise an OpenFlow error code. */
+enum ofperr
+ofputil_decode_group_mod(const struct ofp_header *oh,
+ struct ofputil_group_mod *gm)
+{
+ enum ofp_version ofp_version = oh->version;
+ struct ofpbuf msg;
+ enum ofperr err;
+
+ ofpbuf_use_const(&msg, oh, ntohs(oh->length));
+ ofpraw_pull_assert(&msg);
+
+ ofputil_init_group_properties(&gm->props);
+
+ switch (ofp_version)
+ {
+ case OFP11_VERSION:
+ case OFP12_VERSION:
+ case OFP13_VERSION:
+ case OFP14_VERSION:
+ err = ofputil_pull_ofp11_group_mod(&msg, ofp_version, gm);
+ break;
+
+ case OFP15_VERSION:
+ err = ofputil_pull_ofp15_group_mod(&msg, ofp_version, gm);
+ break;
+
+ case OFP10_VERSION:
+ default:
+ OVS_NOT_REACHED();
+ }
+
+ if (err) {
+ return err;
+ }
+
+ err = ofputil_check_group_mod(gm);
+ if (err) {
+ ofputil_uninit_group_mod(gm);
+ }
+ return err;
+}
+
/* Parse a queue status request message into 'oqsr'.
* Returns 0 if successful, otherwise an OFPERR_* number. */
enum ofperr