• Thomas Haller's avatar
    iface-helper: fix non-reentrant call to platform for failed IPv6 DAD · ad21d542
    Thomas Haller authored
    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: f85728ec
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1546656
    ad21d542
nm-iface-helper.c 22.8 KB