diff mbox series

[ovs-dev,1/3] OVN: Use offset instead of pointer into ofpbuf

Message ID 20190325212956.22093-2-mmichels@redhat.com
State Accepted
Commit 6e5f4942df949985ee2b67a11af03f2ebb7814ce
Headers show
Series OVN: Fixes regarding RA prefixes | expand

Commit Message

Mark Michelson March 25, 2019, 9:29 p.m. UTC
In general, maintaining a pointer into an ofpbuf is risky. As the ofpbuf
grows, it can reallocate its data. If this happens, then pointers into
the data will become invalid.

A safer practice is to track an offset into the ofpbuf's data where a
structure you are interested in is kept. This way, if the ofpbuf data is
reallocated, you can find your structure again by using the offset.

In practice, this patch is not fixing any issues with OVN. Even though
the ra pointer is pointing to ofpbuf data that can be reallocated, it
will never actually happen. ovn-northd and all test cases always encode
the address mode first, meaning we will only ever read from the ra
pointer before the ofpbuf has a chance to expand.

However, this base work is essential for an upcoming patch in this series.

Signed-off-by: Mark Michelson <mmichels@redhat.com>
---
 ovn/lib/actions.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c
index 7b7a89478..56e1ab2ae 100644
--- a/ovn/lib/actions.c
+++ b/ovn/lib/actions.c
@@ -1978,18 +1978,21 @@  format_PUT_ND_RA_OPTS(const struct ovnact_put_opts *po,
 
 static void
 encode_put_nd_ra_option(const struct ovnact_gen_option *o,
-                        struct ofpbuf *ofpacts, struct ovs_ra_msg *ra)
+                        struct ofpbuf *ofpacts, ptrdiff_t ra_offset)
 {
     const union expr_constant *c = o->value.values;
 
     switch (o->option->code) {
     case ND_RA_FLAG_ADDR_MODE:
+    {
+        struct ovs_ra_msg *ra = ofpbuf_at(ofpacts, ra_offset, sizeof *ra);
         if (!strcmp(c->string, "dhcpv6_stateful")) {
             ra->mo_flags = IPV6_ND_RA_FLAG_MANAGED_ADDR_CONFIG;
         } else if (!strcmp(c->string, "dhcpv6_stateless")) {
             ra->mo_flags = IPV6_ND_RA_FLAG_OTHER_ADDR_CONFIG;
         }
         break;
+    }
 
     case ND_OPT_SOURCE_LINKADDR:
     {
@@ -2051,6 +2054,7 @@  encode_PUT_ND_RA_OPTS(const struct ovnact_put_opts *po,
      * pinctrl module receives the ICMPv6 Router Solicitation packet
      * it can copy the userdata field AS IS and resume the packet.
      */
+    size_t ra_offset = ofpacts->size;
     struct ovs_ra_msg *ra = ofpbuf_put_zeros(ofpacts, sizeof *ra);
     ra->icmph.icmp6_type = ND_ROUTER_ADVERT;
     ra->cur_hop_limit = IPV6_ND_RA_CUR_HOP_LIMIT;
@@ -2059,7 +2063,7 @@  encode_PUT_ND_RA_OPTS(const struct ovnact_put_opts *po,
 
     for (const struct ovnact_gen_option *o = po->options;
          o < &po->options[po->n_options]; o++) {
-        encode_put_nd_ra_option(o, ofpacts, ra);
+        encode_put_nd_ra_option(o, ofpacts, ra_offset);
     }
 
     encode_finish_controller_op(oc_offset, ofpacts);