diff mbox series

[ovs-dev] ofp-actions: Avoid assertion failure for clone(ct(...bad actions...)).

Message ID 20180815215713.21435-1-blp@ovn.org
State Accepted
Headers show
Series [ovs-dev] ofp-actions: Avoid assertion failure for clone(ct(...bad actions...)). | expand

Commit Message

Ben Pfaff Aug. 15, 2018, 9:57 p.m. UTC
decode_NXAST_RAW_CT() temporarily pulls data off the beginning of its
ofpacts output ofpbuf and, on its error path, fails to push it back on.
At a higher layer, decode_NXAST_RAW_CLONE() asserts, via
ofpact_finish_CLONE(), that the ofpact_clone that it put is still in the
place where it put it, which causes an assertion failure.

The root cause here is the failure to re-push the clone header.  One could
fix that, but it would be pretty easy for that to go wrong again on some
other obscure error path.  Instead, this commit just makes the problem go
away by always saving and restoring 'ofpact->data' if a decode fails.

Reported-at: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9862
Signed-off-by: Ben Pfaff <blp@ovn.org>
---
 lib/ofp-actions.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

Comments

Justin Pettit Aug. 17, 2018, 11:10 p.m. UTC | #1
> On Aug 15, 2018, at 2:57 PM, Ben Pfaff <blp@ovn.org> wrote:
> 
> decode_NXAST_RAW_CT() temporarily pulls data off the beginning of its
> ofpacts output ofpbuf and, on its error path, fails to push it back on.
> At a higher layer, decode_NXAST_RAW_CLONE() asserts, via
> ofpact_finish_CLONE(), that the ofpact_clone that it put is still in the
> place where it put it, which causes an assertion failure.
> 
> The root cause here is the failure to re-push the clone header.  One could
> fix that, but it would be pretty easy for that to go wrong again on some
> other obscure error path.  Instead, this commit just makes the problem go
> away by always saving and restoring 'ofpact->data' if a decode fails.
> 
> Reported-at: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9862
> Signed-off-by: Ben Pfaff <blp@ovn.org>

Acked-by: Justin Pettit <jpettit@ovn.org>

--Justin
Ben Pfaff Aug. 17, 2018, 11:40 p.m. UTC | #2
On Fri, Aug 17, 2018 at 04:10:00PM -0700, Justin Pettit wrote:
> 
> > On Aug 15, 2018, at 2:57 PM, Ben Pfaff <blp@ovn.org> wrote:
> > 
> > decode_NXAST_RAW_CT() temporarily pulls data off the beginning of its
> > ofpacts output ofpbuf and, on its error path, fails to push it back on.
> > At a higher layer, decode_NXAST_RAW_CLONE() asserts, via
> > ofpact_finish_CLONE(), that the ofpact_clone that it put is still in the
> > place where it put it, which causes an assertion failure.
> > 
> > The root cause here is the failure to re-push the clone header.  One could
> > fix that, but it would be pretty easy for that to go wrong again on some
> > other obscure error path.  Instead, this commit just makes the problem go
> > away by always saving and restoring 'ofpact->data' if a decode fails.
> > 
> > Reported-at: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9862
> > Signed-off-by: Ben Pfaff <blp@ovn.org>
> 
> Acked-by: Justin Pettit <jpettit@ovn.org>

Thanks.  Applied to master, backported as far as branch-2.7.
diff mbox series

Patch

diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index 93e212f07196..6adb55d23b02 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -7500,6 +7500,7 @@  ofpacts_pull_openflow_actions__(struct ofpbuf *openflow,
                                 uint64_t *ofpacts_tlv_bitmap)
 {
     const struct ofp_action_header *actions;
+    void *orig_data = ofpacts->data;
     size_t orig_size = ofpacts->size;
     enum ofperr error;
 
@@ -7519,14 +7520,17 @@  ofpacts_pull_openflow_actions__(struct ofpbuf *openflow,
 
     error = ofpacts_decode(actions, actions_len, version, vl_mff_map,
                            ofpacts_tlv_bitmap, ofpacts);
-    if (error) {
-        ofpacts->size = orig_size;
-        return error;
+    if (!error) {
+        error = ofpacts_verify(ofpacts->data, ofpacts->size, allowed_ovsinsts,
+                               outer_action);
     }
-
-    error = ofpacts_verify(ofpacts->data, ofpacts->size, allowed_ovsinsts,
-                           outer_action);
     if (error) {
+        /* Back out changes to 'ofpacts'.  (Normally, decoding would only
+         * append to 'ofpacts', so that one would expect only to need to
+         * restore 'ofpacts->size', but some action parsing temporarily pulls
+         * off data from the start of 'ofpacts' and may not properly re-push it
+         * on error paths.) */
+        ofpacts->data = orig_data;
         ofpacts->size = orig_size;
     }
     return error;