diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2017-08-11 13:55:10 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2017-08-11 13:55:10 +0000 |
commit | c866e474a36777a21e01a563648ca4c22e0775e5 (patch) | |
tree | a53e211f111cdc60d68f5e222403b51243e32650 /sys/net | |
parent | e1e5afd4d2e05619c8d5df9ca3e6e325cbce32b6 (diff) |
Set free'd tables to NULL in swofp_flow_entry_instruction_free().
swofp_flow_entry_instruction_free is used to "reset" the tables. It
called free on each table but didn't set them to NULL, causing
potential double-frees in swofp_flow_entry_put_instructions().
Instead of complicating the code and adding a X = NULL for each table,
restructure it by introducing a generic function to free tables as
they're all derived from struct ofp_instruction.
Reported by Coverity as various "Read from pointer after free" errors:
Coverity CIDs 1452955 1453345 1452858 1453031 1453179 1453216 1453093
OK millert@ goda@
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/switchofp.c | 47 |
1 files changed, 25 insertions, 22 deletions
diff --git a/sys/net/switchofp.c b/sys/net/switchofp.c index dc37307b49a..e6321a517b2 100644 --- a/sys/net/switchofp.c +++ b/sys/net/switchofp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: switchofp.c,v 1.67 2017/08/11 13:54:14 reyk Exp $ */ +/* $OpenBSD: switchofp.c,v 1.68 2017/08/11 13:55:09 reyk Exp $ */ /* * Copyright (c) 2016 Kazuya GODA <goda@openbsd.org> @@ -212,6 +212,7 @@ int swofp_validate_buckets(struct switch_softc *, struct mbuf *, uint8_t, */ int swofp_flow_entry_put_instructions(struct switch_softc *, struct mbuf *, struct swofp_flow_entry *, uint16_t *, uint16_t *); +void swofp_flow_entry_table_free(struct ofp_instruction **); 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 *, @@ -1523,29 +1524,31 @@ swofp_validate_buckets(struct switch_softc *sc, struct mbuf *m, uint8_t type, } void +swofp_flow_entry_table_free(struct ofp_instruction **table) +{ + if (*table) { + free(*table, M_DEVBUF, ntohs((*table)->i_len)); + *table = NULL; + } +} + +void swofp_flow_entry_instruction_free(struct swofp_flow_entry *swfe) { - if (swfe->swfe_goto_table) - free(swfe->swfe_goto_table, M_DEVBUF, - ntohs(swfe->swfe_goto_table->igt_len)); - if (swfe->swfe_write_metadata) - free(swfe->swfe_write_metadata, M_DEVBUF, - ntohs(swfe->swfe_write_metadata->iwm_len)); - if (swfe->swfe_apply_actions) - free(swfe->swfe_apply_actions, M_DEVBUF, - ntohs(swfe->swfe_apply_actions->ia_len)); - if (swfe->swfe_write_actions) - free(swfe->swfe_write_actions, M_DEVBUF, - ntohs(swfe->swfe_write_actions->ia_len)); - if (swfe->swfe_clear_actions) - free(swfe->swfe_clear_actions, M_DEVBUF, - ntohs(swfe->swfe_clear_actions->ia_len)); - if (swfe->swfe_experimenter) - free(swfe->swfe_experimenter, M_DEVBUF, - ntohs(swfe->swfe_experimenter->ie_len)); - if (swfe->swfe_meter) - free(swfe->swfe_meter, M_DEVBUF, - ntohs(swfe->swfe_meter->im_len)); + swofp_flow_entry_table_free((struct ofp_instruction **) + &swfe->swfe_goto_table); + swofp_flow_entry_table_free((struct ofp_instruction **) + &swfe->swfe_write_metadata); + swofp_flow_entry_table_free((struct ofp_instruction **) + &swfe->swfe_apply_actions); + swofp_flow_entry_table_free((struct ofp_instruction **) + &swfe->swfe_write_actions); + swofp_flow_entry_table_free((struct ofp_instruction **) + &swfe->swfe_clear_actions); + swofp_flow_entry_table_free((struct ofp_instruction **) + &swfe->swfe_experimenter); + swofp_flow_entry_table_free((struct ofp_instruction **) + &swfe->swfe_meter); } void |