[ovs-dev] [PATCH] ofp-actions: Fix use-after-free with ofpact_finish().

Joe Stringer joe at ovn.org
Mon Mar 7 23:36:37 UTC 2016


ofpact_finish() may now reallocate the buffer it is passed, but not all
callers updated their local pointers to the current action in the
buffer. This could potentially lead to several use-after-free bugs.

Update ofpact_finish() to return the new pointer to the ofpact which is
provided, and update the calling points to ensure that their local
pointers are pointing into the correct (potentially reallocated) buffer.

Fixes: 2bd318dec242 ("ofp-actions: Make composing actions harder to screw up.")
Reported-by: William Tu <u9012063 at gmail.com>
Signed-off-by: Joe Stringer <joe at ovn.org>
---
 lib/bundle.c           |  4 +---
 lib/ofp-actions.c      | 14 +++++++++-----
 lib/ofp-actions.h      |  2 +-
 ofproto/ofproto-dpif.c |  2 +-
 4 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/lib/bundle.c b/lib/bundle.c
index 1451e928fec6..07dc9f4919b2 100644
--- a/lib/bundle.c
+++ b/lib/bundle.c
@@ -178,9 +178,7 @@ bundle_parse__(const char *s, char **save_ptr,
         bundle = ofpacts->header;
         bundle->n_slaves++;
     }
-    ofpact_finish(ofpacts, &bundle->ofpact);
-
-    bundle = ofpacts->header;
+    bundle = ofpact_finish(ofpacts, &bundle->ofpact);
     bundle->basis = atoi(basis);
 
     if (!strcasecmp(fields, "eth_src")) {
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index 905469b6bbf9..a7c0388adeaa 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -1256,8 +1256,7 @@ decode_bundle(bool load, const struct nx_action_bundle *nab,
         bundle = ofpacts->header;
     }
 
-    ofpact_finish(ofpacts, &bundle->ofpact);
-
+    bundle = ofpact_finish(ofpacts, &bundle->ofpact);
     if (!error) {
         error = bundle_check(bundle, OFPP_MAX, NULL);
     }
@@ -4956,7 +4955,7 @@ decode_NXAST_RAW_CT(const struct nx_action_conntrack *nac,
 
     conntrack = ofpbuf_push_uninit(out, sizeof(*conntrack));
     out->header = &conntrack->ofpact;
-    ofpact_finish(out, &conntrack->ofpact);
+    conntrack = ofpact_finish(out, &conntrack->ofpact);
 
     if (conntrack->ofpact.len > sizeof(*conntrack)
         && !(conntrack->flags & NX_CT_F_COMMIT)) {
@@ -7397,8 +7396,11 @@ ofpact_init(struct ofpact *ofpact, enum ofpact_type type, size_t len)
 /* Finishes composing a variable-length action (begun using
  * ofpact_put_<NAME>()), by padding the action to a multiple of OFPACT_ALIGNTO
  * bytes and updating its embedded length field.  See the large comment near
- * the end of ofp-actions.h for more information. */
-void
+ * the end of ofp-actions.h for more information.
+ *
+ * May reallocate 'ofpacts'. Callers should consider updating their 'ofpact'
+ * pointer to the return value of this function. */
+void *
 ofpact_finish(struct ofpbuf *ofpacts, struct ofpact *ofpact)
 {
     ptrdiff_t len;
@@ -7408,6 +7410,8 @@ ofpact_finish(struct ofpbuf *ofpacts, struct ofpact *ofpact)
     ovs_assert(len <= UINT16_MAX);
     ofpact->len = len;
     ofpbuf_padto(ofpacts, OFPACT_ALIGN(ofpacts->size));
+
+    return ofpacts->header;
 }
 
 static char * OVS_WARN_UNUSED_RESULT
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index 24143d324323..ec8b36981a56 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -968,7 +968,7 @@ OFPACTS
 #undef OFPACT
 
 /* Call after adding the variable-length part to a variable-length action. */
-void ofpact_finish(struct ofpbuf *, struct ofpact *);
+void *ofpact_finish(struct ofpbuf *, struct ofpact *);
 
 /* Additional functions for composing ofpacts. */
 struct ofpact_set_field *ofpact_put_reg_load(struct ofpbuf *ofpacts);
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index b963ff201782..69521a63a448 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -1411,7 +1411,7 @@ add_internal_flows(struct ofproto_dpif *ofproto)
     controller->max_len = UINT16_MAX;
     controller->controller_id = 0;
     controller->reason = OFPR_IMPLICIT_MISS;
-    ofpact_finish(&ofpacts, &controller->ofpact);
+    controller = ofpact_finish(&ofpacts, &controller->ofpact);
 
     error = add_internal_miss_flow(ofproto, id++, &ofpacts,
                                    &ofproto->miss_rule);
-- 
2.1.4




More information about the dev mailing list