From: Ben Pfaff Date: Fri, 13 Mar 2009 20:17:01 +0000 (-0700) Subject: secchan: Validate subrules before attempting to dereference their super-rules. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=03389e550a4bbdb76ff5a908ac5c7401508ff1d8;p=openvswitch secchan: Validate subrules before attempting to dereference their super-rules. rule_make_actions() is supposed to compose the datapath actions for an exact-match rule, and to do so it needs to look up the super-rule (if the rule is a subrule). The "super" pointer might be set to UNKNOWN_SUPER, though, and before this commit that would cause a segfault. This commit modifies the callers of rule_make_actions() to ensure that the rule passed in can never have a "super" of UNKNOWN_SUPER. In most cases, this was already impossible (e.g. we're passing in a new rule that we just added to the table), but in two cases where the rule was obtained from a bare classifier lookup we needed to validate the rule before attempting to use it. Fixes a crash reported by Keith. --- diff --git a/secchan/ofproto.c b/secchan/ofproto.c index 532f8377..a4f68b01 100644 --- a/secchan/ofproto.c +++ b/secchan/ofproto.c @@ -1255,6 +1255,7 @@ rule_has_out_port(const struct rule *rule, uint16_t out_port) return false; } +/* The caller must ensure that rule->super != UNKNOWN_SUPER. */ static void rule_make_actions(struct ofproto *p, struct rule *rule, bool revalidating, struct odp_actions *actions) @@ -1459,41 +1460,45 @@ struct action_xlate_ctx { static void do_xlate_actions(const union ofp_action *in, size_t n_in, struct action_xlate_ctx *ctx); -static void -xlate_table_action(struct action_xlate_ctx *ctx, uint16_t in_port) +static struct rule * +lookup_valid_rule(struct ofproto *ofproto, const flow_t *flow) { - struct ofproto *p = ctx->ofproto; struct rule *rule; - flow_t flow; - - if (ctx->recurse) { - return; + rule = rule_from_cls_rule(classifier_lookup(&ofproto->cls, flow)); + + /* The rule we found might not be valid, since we could be in need of + * revalidation. If it is not valid, don't return it. */ + if (rule + && rule->super + && (ofproto->need_revalidate || rule->super == UNKNOWN_SUPER) + && !revalidate_rule(ofproto, rule)) { + return NULL; } - flow = *ctx->flow; - flow.in_port = in_port; + return rule; +} - rule = rule_from_cls_rule(classifier_lookup(&p->cls, &flow)); - if (!rule) { - return; - } else if (rule->super && p->need_revalidate) { - /* This might be a subrule that is now invalid. Revalidate it. */ - if (!revalidate_rule(p, rule)) { - /* The subrule got deleted so we can optimize slightly by only - * looking through the wildcarded rules. */ - rule = rule_from_cls_rule(classifier_lookup_wild(&p->cls, &flow)); - if (!rule) { - return; +static void +xlate_table_action(struct action_xlate_ctx *ctx, uint16_t in_port) +{ + if (!ctx->recurse) { + struct rule *rule; + flow_t flow; + + flow = *ctx->flow; + flow.in_port = in_port; + + rule = lookup_valid_rule(ctx->ofproto, &flow); + if (rule) { + if (rule->super) { + rule = rule->super; } + + ctx->recurse++; + do_xlate_actions(rule->actions, rule->n_actions, ctx); + ctx->recurse--; } } - if (rule->super) { - rule = rule->super; - } - - ctx->recurse++; - do_xlate_actions(rule->actions, rule->n_actions, ctx); - ctx->recurse--; } static void @@ -2569,7 +2574,7 @@ handle_odp_msg(struct ofproto *p, struct ofpbuf *packet) payload.size = msg->length - sizeof *msg; flow_extract(&payload, msg->port, &flow); - rule = rule_from_cls_rule(classifier_lookup(&p->cls, &flow)); + rule = lookup_valid_rule(p, &flow); if (!rule) { struct ofport *port;