This diff is a part of the bigger diff to add more input validations to
the switch(4) OpenFlow protocol parser.

In this diff we reworked the swofp_flow_entry_put_instructions() function
with the following changes:
- Avoid leaking memory on repeated instructions. It is not possible to
  use the same instruction more than once, however the spec doesn't
  specify any errors for this ocasion. (OpenFlow 1.3.5 spec page 26);
- Apply the same error return tecnique for this function;
- Remove old goto label;
- Fix some whitespace/tab issue;

ok?

Index: net/switchofp.c
===================================================================
RCS file: /cvs/src/sys/net/switchofp.c,v
retrieving revision 1.23
diff -u -p -r1.23 switchofp.c
--- net/switchofp.c     31 Oct 2016 08:06:27 -0000      1.23
+++ net/switchofp.c     31 Oct 2016 08:24:43 -0000
@@ -195,7 +195,7 @@ int  swofp_validate_buckets(struct switc
  * Flow entry
  */
 int     swofp_flow_entry_put_instructions(struct mbuf *,
-           struct swofp_flow_entry *);
+           struct swofp_flow_entry *, int *error);
 void    swofp_flow_entry_instruction_free(struct swofp_flow_entry *);
 void    swofp_flow_entry_free(struct swofp_flow_entry **);
 void    swofp_flow_entry_add(struct switch_softc *, struct swofp_flow_table *,
@@ -4570,12 +4570,12 @@ swofp_send_flow_removed(struct switch_so
  */
 int
 swofp_flow_entry_put_instructions(struct mbuf *m,
-    struct swofp_flow_entry *swfe)
+    struct swofp_flow_entry *swfe, int *error)
 {
        struct ofp_flow_mod     *ofm;
        struct ofp_instruction  *oi;
        caddr_t                  inst;
-       int                      start, len, off, error;
+       int                      start, len, off;
 
        ofm = mtod(m, struct ofp_flow_mod *);
 
@@ -4591,41 +4591,69 @@ swofp_flow_entry_put_instructions(struct
        for (off = start; off < start + len; off += ntohs(oi->i_len)) {
                oi = (struct ofp_instruction *)(mtod(m, caddr_t) + off);
 
-               if (swofp_validate_flow_instruction(oi, &error))
-                       goto failed;
+               if (swofp_validate_flow_instruction(oi, error))
+                       return (-1);
 
                if ((inst = malloc(ntohs(oi->i_len), M_DEVBUF,
-                           M_DONTWAIT|M_ZERO)) == NULL) {
-                               error = OFP_ERRFLOWMOD_UNKNOWN;
-                               goto failed;
+                   M_DONTWAIT|M_ZERO)) == NULL) {
+                       *error = OFP_ERRFLOWMOD_UNKNOWN;
+                       return (-1);
                }
                memcpy(inst, oi, ntohs(oi->i_len));
 
                switch (ntohs(oi->i_type)) {
                case OFP_INSTRUCTION_T_GOTO_TABLE:
+                       if (swfe->swfe_goto_table)
+                               free(swfe->swfe_goto_table, M_DEVBUF,
+                                   ntohs(oi->i_len));
+
                        swfe->swfe_goto_table =
                            (struct ofp_instruction_goto_table *)inst;
                        break;
                case OFP_INSTRUCTION_T_WRITE_META:
+                       if (swfe->swfe_write_metadata)
+                               free(swfe->swfe_write_metadata, M_DEVBUF,
+                                   ntohs(oi->i_len));
+
                        swfe->swfe_write_metadata =
                            (struct ofp_instruction_write_metadata *)inst;
                        break;
                case OFP_INSTRUCTION_T_WRITE_ACTIONS:
+                       if (swfe->swfe_write_actions)
+                               free(swfe->swfe_write_actions, M_DEVBUF,
+                                   ntohs(oi->i_len));
+
                        swfe->swfe_write_actions =
                            (struct ofp_instruction_actions *)inst;
                        break;
                case OFP_INSTRUCTION_T_APPLY_ACTIONS:
+                       if (swfe->swfe_apply_actions)
+                               free(swfe->swfe_apply_actions, M_DEVBUF,
+                                   ntohs(oi->i_len));
+
                        swfe->swfe_apply_actions =
                            (struct ofp_instruction_actions *)inst;
                        break;
                case OFP_INSTRUCTION_T_CLEAR_ACTIONS:
+                       if (swfe->swfe_clear_actions)
+                               free(swfe->swfe_clear_actions, M_DEVBUF,
+                                   ntohs(oi->i_len));
+
                        swfe->swfe_clear_actions =
                            (struct ofp_instruction_actions *)inst;
                        break;
                case OFP_INSTRUCTION_T_METER:
+                       if (swfe->swfe_meter)
+                               free(swfe->swfe_meter, M_DEVBUF,
+                                   ntohs(oi->i_len));
+
                        swfe->swfe_meter = (struct ofp_instruction_meter *)inst;
                        break;
                case OFP_INSTRUCTION_T_EXPERIMENTER:
+                       if (swfe->swfe_experimenter)
+                               free(swfe->swfe_experimenter, M_DEVBUF,
+                                   ntohs(oi->i_len));
+
                        swfe->swfe_experimenter =
                            (struct ofp_instruction_experimenter *)inst;
                        break;
@@ -4636,9 +4664,6 @@ swofp_flow_entry_put_instructions(struct
        }
 
        return (0);
-
- failed:
-       return (error);
 }
 
 int
@@ -4712,7 +4737,7 @@ swofp_flow_mod_cmd_add(struct switch_sof
        if (ntohs(om->om_length) == sizeof(*om) && swfe->swfe_priority == 0)
                swfe->swfe_tablemiss = 1;
 
-       if ((error = swofp_flow_entry_put_instructions(m, swfe))) {
+       if (swofp_flow_entry_put_instructions(m, swfe, &error)) {
                etype = OFP_ERRTYPE_BAD_INSTRUCTION;
                goto ofp_error_free_flow;
        }
@@ -4787,7 +4812,7 @@ swofp_flow_mod_cmd_common_modify(struct 
                    ntohl(ofm->fm_out_group)))
                        continue;
 
-               if ((error = swofp_flow_entry_put_instructions(m, swfe))) {
+               if (swofp_flow_entry_put_instructions(m, swfe, &error)) {
                        /*
                         * If error occurs in swofp_flow_entry_put_instructions,
                         * the flow entry might be half-way modified. So the

Reply via email to