From 3455c30a58ff14952acf86f8ea068ef8f3b6d889 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Wed, 12 Jun 2019 17:58:49 +0200 Subject: [PATCH] ovs/ovsdb: guard against OVSDB integrity issues Don't crash in situations, where the bridge or a port has a child with UUID we don't know. This could happen if we mess up the parsing of messages from OVSDB, but could also theoretically happen in OVSDB sends us bad data. (cherry picked from commit 99c7adc1e12862f22026bb8f806c9223db9a78ec) --- src/devices/ovs/nm-ovsdb.c | 40 +++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/src/devices/ovs/nm-ovsdb.c b/src/devices/ovs/nm-ovsdb.c index 82e25f396c..5f46c23a26 100644 --- a/src/devices/ovs/nm-ovsdb.c +++ b/src/devices/ovs/nm-ovsdb.c @@ -584,9 +584,14 @@ _add_interface (NMOvsdb *self, json_t *params, json_array_append_new (ports, json_pack ("[s, s]", "uuid", port_uuid)); - if ( g_strcmp0 (ovs_port->name, nm_connection_get_interface_name (port)) != 0 - || g_strcmp0 (ovs_port->connection_uuid, nm_connection_get_uuid (port)) != 0) + if (!ovs_port) { + /* This would be a violation of ovsdb's reference integrity (a bug). */ + _LOGW ("Unknown port '%s' in bridge '%s'", port_uuid, bridge_uuid); continue; + } else if ( strcmp (ovs_port->name, nm_connection_get_interface_name (port)) != 0 + || g_strcmp0 (ovs_port->connection_uuid, nm_connection_get_uuid (port)) != 0) { + continue; + } for (ii = 0; ii < ovs_port->interfaces->len; ii++) { interface_uuid = g_ptr_array_index (ovs_port->interfaces, ii); @@ -594,9 +599,13 @@ _add_interface (NMOvsdb *self, json_t *params, json_array_append_new (interfaces, json_pack ("[s, s]", "uuid", interface_uuid)); - if ( g_strcmp0 (ovs_interface->name, nm_connection_get_interface_name (interface)) == 0 - && g_strcmp0 (ovs_interface->connection_uuid, nm_connection_get_uuid (interface)) == 0) + if (!ovs_interface) { + /* This would be a violation of ovsdb's reference integrity (a bug). */ + _LOGW ("Unknown interface '%s' in port '%s'", interface_uuid, port_uuid); + } else if ( strcmp (ovs_interface->name, nm_connection_get_interface_name (interface)) == 0 + && g_strcmp0 (ovs_interface->connection_uuid, nm_connection_get_uuid (interface)) == 0) { has_interface = TRUE; + } } break; @@ -692,16 +701,27 @@ _delete_interface (NMOvsdb *self, json_t *params, const char *ifname) interfaces_changed = FALSE; + if (!ovs_port) { + /* This would be a violation of ovsdb's reference integrity (a bug). */ + _LOGW ("Unknown port '%s' in bridge '%s'", port_uuid, bridge_uuid); + continue; + } + for (ii = 0; ii < ovs_port->interfaces->len; ii++) { interface_uuid = g_ptr_array_index (ovs_port->interfaces, ii); ovs_interface = g_hash_table_lookup (priv->interfaces, interface_uuid); json_array_append_new (interfaces, json_pack ("[s,s]", "uuid", interface_uuid)); - if (strcmp (ovs_interface->name, ifname) == 0) { - /* skip the interface */ - interfaces_changed = TRUE; - continue; + if (ovs_interface) { + if (strcmp (ovs_interface->name, ifname) == 0) { + /* skip the interface */ + interfaces_changed = TRUE; + continue; + } + } else { + /* This would be a violation of ovsdb's reference integrity (a bug). */ + _LOGW ("Unknown interface '%s' in port '%s'", interface_uuid, port_uuid); } json_array_append_new (new_interfaces, json_pack ("[s,s]", "uuid", interface_uuid)); @@ -929,7 +949,9 @@ ovsdb_got_update (NMOvsdb *self, json_t *msg) if (old) { ovs_interface = g_hash_table_lookup (priv->interfaces, key); - if (!new || g_strcmp0 (ovs_interface->name, name) != 0) { + if (!ovs_interface) { + _LOGW ("Interface '%s' was not seen", key); + } else if (!new || strcmp (ovs_interface->name, name) != 0) { old = FALSE; _LOGT ("removed an '%s' interface: %s%s%s", ovs_interface->type, ovs_interface->name,