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