And now branch-1.3.

On Fri, Dec 16, 2011 at 10:14:56AM -0800, Ben Pfaff wrote:
> Thank you.  I pushed this to master and branch-1.4.
> 
> On Thu, Dec 15, 2011 at 05:31:35PM -0800, Ethan Jackson wrote:
> > Looks good.
> > 
> > I'm planning to get rid of this function entirely in the fairly near future.
> > 
> > Ethan
> > 
> > On Thu, Dec 15, 2011 at 16:24, Ben Pfaff <b...@nicira.com> wrote:
> > > When a flow consists solely of an output to OFPP_CONTROLLER, we avoid a
> > > round trip to the kernel and back by calling execute_controller_action()
> > > from handle_flow_miss(). ?However, execute_controller_action() frees the
> > > packet passed in. ?This is dangerous, because the packet and the upcall
> > > key are in the same block of malloc()'d memory, as the comment on struct
> > > dpif_upcall says:
> > >
> > > /* A packet passed up from the datapath to userspace.
> > > ?*
> > > ?* If 'key' or 'actions' is nonnull, then it points into data owned by
> > > ?* 'packet', so their memory cannot be freed separately. ?(This is hardly 
> > > a
> > > ?* great way to do things but it works out OK for the dpif providers and
> > > ?* clients that exist so far.)
> > > ?*/
> > >
> > > Thus, we get a use-after-free later on in handle_flow_miss() and 
> > > eventually
> > > a double free.
> > >
> > > This fixes the problem by making execute_controller_action() clone the
> > > packet in this case.
> > > ---
> > > ?ofproto/ofproto-dpif.c | ? 16 +++++++++++-----
> > > ?1 files changed, 11 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> > > index e68bec3..1043a5d 100644
> > > --- a/ofproto/ofproto-dpif.c
> > > +++ b/ofproto/ofproto-dpif.c
> > > @@ -318,7 +318,7 @@ static bool execute_controller_action(struct 
> > > ofproto_dpif *,
> > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const struct flow *,
> > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const struct nlattr *odp_actions,
> > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? size_t actions_len,
> > > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct ofpbuf *packet);
> > > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct ofpbuf *packet, bool clone);
> > >
> > > ?static void facet_flush_stats(struct ofproto_dpif *, struct facet *);
> > >
> > > @@ -2533,7 +2533,7 @@ handle_flow_miss(struct ofproto_dpif *ofproto, 
> > > struct flow_miss *miss,
> > > ? ? ? ? }
> > > ? ? ? ? if (!execute_controller_action(ofproto, &facet->flow,
> > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?subfacet->actions,
> > > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? subfacet->actions_len, packet)) {
> > > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? subfacet->actions_len, packet, 
> > > true)) {
> > > ? ? ? ? ? ? struct flow_miss_op *op = &ops[(*n_ops)++];
> > > ? ? ? ? ? ? struct dpif_execute *execute = &op->dpif_op.execute;
> > >
> > > @@ -3059,11 +3059,17 @@ facet_free(struct facet *facet)
> > > ? ? free(facet);
> > > ?}
> > >
> > > +/* If the 'actions_len' bytes of actions in 'odp_actions' are just a 
> > > single
> > > + * OVS_ACTION_ATTR_USERSPACE action, executes it internally and returns 
> > > true.
> > > + * Otherwise, returns false without doing anything.
> > > + *
> > > + * If 'clone' is true, the caller always retains ownership of 'packet'.
> > > + * Otherwise, ownership is transferred to this function if it returns 
> > > true. */
> > > ?static bool
> > > ?execute_controller_action(struct ofproto_dpif *ofproto,
> > > ? ? ? ? ? ? ? ? ? ? ? ? ? const struct flow *flow,
> > > ? ? ? ? ? ? ? ? ? ? ? ? ? const struct nlattr *odp_actions, size_t 
> > > actions_len,
> > > - ? ? ? ? ? ? ? ? ? ? ? ? ?struct ofpbuf *packet)
> > > + ? ? ? ? ? ? ? ? ? ? ? ? ?struct ofpbuf *packet, bool clone)
> > > ?{
> > > ? ? if (actions_len
> > > ? ? ? ? && odp_actions->nla_type == OVS_ACTION_ATTR_USERSPACE
> > > @@ -3079,7 +3085,7 @@ execute_controller_action(struct ofproto_dpif 
> > > *ofproto,
> > >
> > > ? ? ? ? nla = nl_attr_find_nested(odp_actions, 
> > > OVS_USERSPACE_ATTR_USERDATA);
> > > ? ? ? ? send_packet_in_action(ofproto, packet, nl_attr_get_u64(nla), flow,
> > > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?false);
> > > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?clone);
> > > ? ? ? ? return true;
> > > ? ? } else {
> > > ? ? ? ? return false;
> > > @@ -3100,7 +3106,7 @@ execute_odp_actions(struct ofproto_dpif *ofproto, 
> > > const struct flow *flow,
> > > ? ? int error;
> > >
> > > ? ? if (execute_controller_action(ofproto, flow, odp_actions, actions_len,
> > > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?packet)) {
> > > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?packet, false)) {
> > > ? ? ? ? return true;
> > > ? ? }
> > >
> > > --
> > > 1.7.2.5
> > >
> > > _______________________________________________
> > > dev mailing list
> > > dev@openvswitch.org
> > > http://openvswitch.org/mailman/listinfo/dev
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to