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 11:13:50 -0600
commitbf7865e8592f012261840662655aca01db0bba06 (patch)
treece8768ee1f5aac4162483efde6376e8c10a827d3
parentdd20407c4e73d730be093d56e8090844e4a1f1d4 (diff)
downloadNetworkManager-bf7865e8592f012261840662655aca01db0bba06.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. (fixup by dcbw to use cached passed to cache_remove_unknown()) 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.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index d694c286b3..9d306bf610 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);
@@ -4093,6 +4104,33 @@ 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 (struct nl_cache *cache)
+{
+ GPtrArray *objects_to_remove = NULL;
+ struct nl_object *object;
+
+ for (object = nl_cache_get_first (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
@@ -4114,6 +4152,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 (priv->link_cache);
+ cache_remove_unknown (priv->address_cache);
+ cache_remove_unknown (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);
}