iface-helper: fix non-reentrant call to platform for failed IPv6 DAD

System Internals / NetworkManager - Thomas Haller [redhat.com] - 21 February 2018 11:08 EST

Platform invokes change events while reading netlink events. However, platform code is not re-entrant and calling into platform again is not allowed (aside operations that do not process the netlink socket, like lookup of the platform cache).

That basically means, we have to always process events in an idle handler. That is not a too strong limitation, because we anyway don't know the call context in which the platform event is emitted and we should avoid unguarded recursive calls into platform.

Otherwise, we get hit an assertion/crash in nm-iface-helper:

1 raise() 2 abort() 3 g_assertion_message() 4 g_assertion_message_expr() 5 do_delete_object() 6 ip6_address_delete() >>> 7 nm_platform_ip6_address_delete() 8 nm_platform_ip6_address_sync() 9 nm_ip6_config_commit() 10 ndisc_config_changed() 11 ffi_call_unix64() 12 ffi_call() 13 g_cclosure_marshal_generic_va() 14 _g_closure_invoke_va() 15 g_signal_emit_valist() 16 g_signal_emit() >>> 17 nm_ndisc_dad_failed() 18 ffi_call_unix64() 19 ffi_call() 20 g_cclosure_marshal_generic() 21 g_closure_invoke() 22 signal_emit_unlocked_R() 23 g_signal_emit_valist() 24 g_signal_emit() >>> 25 nm_platform_cache_update_emit_signal() 26 event_handler_recvmsgs() 27 event_handler_read_netlink() 28 delayed_action_handle_one() 29 delayed_action_handle_all() 30 do_delete_object() 31 ip6_address_delete() 32 nm_platform_ip6_address_delete() 33 nm_platform_ip6_address_sync() >>> 34 nm_ip6_config_commit() 35 ndisc_config_changed() 36 ffi_call_unix64() 37 ffi_call() 38 g_cclosure_marshal_generic_va() 39 _g_closure_invoke_va() 40 g_signal_emit_valist() 41 g_signal_emit() 42 check_timestamps() 43 receive_ra() 44 ndp_call_eventfd_handler() 45 ndp_callall_eventfd_handler() 46 event_ready() 47 g_main_context_dispatch() 48 g_main_context_iterate.isra.22() 49 g_main_loop_run() >>> 50 main()

NMPlatform already has a check to assert against recursive calls in delayed_action_handle_all():

g_return_val_if_fail (priv->delayed_action.is_handling == 0, FALSE);

priv->delayed_action.is_handling++;

priv->delayed_action.is_handling--;

Fixes: f85728ecff824b1fece43aba51d8171db2766ea2

https://bugzilla.redhat.com/show_bug.cgi?id=1546656

ad21d5421 iface-helper: fix non-reentrant call to platform for failed IPv6 DAD
src/devices/nm-device.c | 36 +++++++++++++-----------------
src/ndisc/nm-ndisc.h | 31 ++++++++++++++++++++++++++
src/nm-iface-helper.c | 59 ++++++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 100 insertions(+), 26 deletions(-)

Upstream: cgit.freedesktop.org


  • Share