summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2015-01-15 09:18:07 +0100
committerDan Williams <dcbw@redhat.com>2015-01-15 09:33:35 -0600
commit6c1a6d2d5f8c102a7b43e167791954ba36dff31e (patch)
tree1ed87f15e691a4729ea77a16a33bc234ae630996
parent5828a4b0b441056967429db0c5a7d1186077c8a6 (diff)
downloadNetworkManager-6c1a6d2d5f8c102a7b43e167791954ba36dff31e.tar.gz
platform: avoid storing unknown netlink object types (bgo #742928)
Testing WWAN connections through a Nokia Series 40 phone, addresses of family AF_PHONET end up triggering an assert() in object_has_ifindex(), just because object_type_from_nl_object() only handles AF_INET and AF_INET6 address. In order to avoid this kind of problems, we'll try to make sure that the object caches kept by NM only store known object types. https://bugzilla.gnome.org/show_bug.cgi?id=742928 Connect: ppp0 <--> /dev/ttyACM0 nm-pppd-plugin-Message: nm-ppp-plugin: (nm_phasechange): status 5 / phase 'establish' NetworkManager[27434]: <info> (ppp0): new Generic device (driver: 'unknown' ifindex: 12) NetworkManager[27434]: <info> (ppp0): exported as /org/freedesktop/NetworkManager/Devices/4 [Thread 0x7ffff1ecf700 (LWP 27439) exited] NetworkManager[27434]: <info> (ttyACM0): device state change: ip-config -> deactivating (reason 'user-requested') [70 110 39] Terminating on signal 15 nm-pppd-plugin-Message: nm-ppp-plugin: (nm_phasechange): status 10 / phase 'terminate' ** NetworkManager:ERROR:platform/nm-linux-platform.c:1534:object_has_ifindex: code should not be reached Program received signal SIGABRT, Aborted. 0x00007ffff4692a97 in raise () from /usr/lib/libc.so.6 (gdb) bt #0 0x00007ffff4692a97 in raise () from /usr/lib/libc.so.6 #1 0x00007ffff4693e6a in abort () from /usr/lib/libc.so.6 #2 0x00007ffff4c8d7f5 in g_assertion_message () from /usr/lib/libglib-2.0.so.0 #3 0x00007ffff4c8d88a in g_assertion_message_expr () from /usr/lib/libglib-2.0.so.0 #4 0x0000000000472b91 in object_has_ifindex (object=0x8a8320, ifindex=12) at platform/nm-linux-platform.c:1534 #5 0x0000000000472bec in check_cache_items (platform=0x7fe8a0, cache=0x7fda30, ifindex=12) at platform/nm-linux-platform.c:1549 #6 0x0000000000472de3 in announce_object (platform=0x7fe8a0, object=0x8a8c30, change_type=NM_PLATFORM_SIGNAL_REMOVED, reason=NM_PLATFORM_REASON_EXTERNAL) at platform/nm-linux-platform.c:1617 #7 0x0000000000473dd2 in event_notification (msg=0x8a7970, user_data=0x7fe8a0) at platform/nm-linux-platform.c:1992 #8 0x00007ffff5ee14de in nl_recvmsgs_report () from /usr/lib/libnl-3.so.200 #9 0x00007ffff5ee1849 in nl_recvmsgs () from /usr/lib/libnl-3.so.200 #10 0x00000000004794df in event_handler (channel=0x7fc930, io_condition=G_IO_IN, user_data=0x7fe8a0) at platform/nm-linux-platform.c:4152 #11 0x00007ffff4c6791d in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0 #12 0x00007ffff4c67cf8 in ?? () from /usr/lib/libglib-2.0.so.0 #13 0x00007ffff4c68022 in g_main_loop_run () from /usr/lib/libglib-2.0.so.0 #14 0x00000000004477ee in main (argc=1, argv=0x7fffffffeaa8) at main.c:447 (gdb) fr 4 #4 0x0000000000472b91 in object_has_ifindex (object=0x8a8320, ifindex=12) at platform/nm-linux-platform.c:1534 1534 g_assert_not_reached ();
-rw-r--r--src/platform/nm-linux-platform.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 48b5f8e16b..42cecb8f22 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -1725,9 +1725,15 @@ refresh_object (NMPlatform *platform, struct nl_object *object, gboolean removed
announce_object (platform, cached_object, NM_PLATFORM_SIGNAL_REMOVED, reason);
}
} else {
+ ObjectType type;
+
if (!kernel_object)
return FALSE;
+ /* Unsupported object types should never have reached the caches */
+ type = object_type_from_nl_object (kernel_object);
+ g_assert (type != OBJECT_TYPE_UNKNOWN);
+
hack_empty_master_iff_lower_up (platform, kernel_object);
if (cached_object)
@@ -1741,7 +1747,7 @@ refresh_object (NMPlatform *platform, struct nl_object *object, gboolean removed
announce_object (platform, kernel_object, cached_object ? NM_PLATFORM_SIGNAL_CHANGED : NM_PLATFORM_SIGNAL_ADDED, reason);
/* Refresh the master device (even on enslave/release) */
- if (object_type_from_nl_object (kernel_object) == OBJECT_TYPE_LINK) {
+ if (type == OBJECT_TYPE_LINK) {
int kernel_master = rtnl_link_get_master ((struct rtnl_link *) kernel_object);
int cached_master = cached_object ? rtnl_link_get_master ((struct rtnl_link *) cached_object) : 0;
struct nl_object *master_object;
@@ -2003,6 +2009,11 @@ event_notification (struct nl_msg *msg, gpointer user_data)
*/
if (!kernel_object)
return NL_OK;
+
+ /* Ignore unsupported object types (e.g. AF_PHONET family addresses) */
+ if (type == OBJECT_TYPE_UNKNOWN)
+ return NL_OK;
+
/* Handle external addition */
if (!cached_object) {
nle = nl_cache_add (cache, kernel_object);
@@ -4086,6 +4097,34 @@ cache_announce_changes (NMPlatform *platform, struct nl_cache *new, struct nl_ca
nl_cache_free (old);
}
+/* The cache should always avoid containing objects not handled by NM, like
+ * e.g. addresses of the AF_PHONET family. */
+static void
+cache_remove_unknown (NMPlatform *platform, struct nl_cache *cache)
+{
+ NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
+ GPtrArray *objects_to_remove = NULL;
+ struct nl_object *object;
+
+ for (object = nl_cache_get_first (priv->address_cache); object; object = nl_cache_get_next (object)) {
+ if (object_type_from_nl_object (object) == OBJECT_TYPE_UNKNOWN) {
+ if (!objects_to_remove)
+ objects_to_remove = g_ptr_array_new_with_free_func ((GDestroyNotify) nl_object_put);
+ nl_object_get (object);
+ g_ptr_array_add (objects_to_remove, object);
+ }
+ }
+
+ if (objects_to_remove) {
+ guint i;
+
+ for (i = 0; i < objects_to_remove->len; i++)
+ nl_cache_remove (g_ptr_array_index (objects_to_remove, i));
+
+ g_ptr_array_free (objects_to_remove, TRUE);
+ }
+}
+
/* Creates and populates the netlink object caches. Called upon platform init and
* when we run out of sync (out of buffer space, netlink congestion control). In case
* the caches already exist, it finds changed, added and removed objects, announces
@@ -4107,6 +4146,11 @@ cache_repopulate_all (NMPlatform *platform)
rtnl_route_alloc_cache (priv->nlh, AF_UNSPEC, 0, &priv->route_cache);
g_assert (priv->link_cache && priv->address_cache && priv->route_cache);
+ /* Remove all unknown objects from the caches */
+ cache_remove_unknown (platform, priv->link_cache);
+ cache_remove_unknown (platform, priv->address_cache);
+ cache_remove_unknown (platform, priv->route_cache);
+
for (object = nl_cache_get_first (priv->address_cache); object; object = nl_cache_get_next (object)) {
_rtnl_addr_hack_lifetimes_rel_to_abs ((struct rtnl_addr *) object);
}