From 401a2eb834bdddd8931161eb86204eb80d26b2c7 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 22 Sep 2015 14:03:32 +0200 Subject: [PATCH] systemd: avoid potential crash due to uncanceled timers in client_receive_advertise() Got a crash with unknown reason on nm-1-0 branch. It's unclear why, but the reason could be that a lease in client_receive_advertise() was cleared, but not its timers. Backtrace from nm-1-0 branch (note that the systemd code where the crash happend is different, but similar): #0 sd_event_source_unref (s=0xf5c007e8fb894853) at dhcp-manager/systemd-dhcp/nm-sd-adapt.c:53 #1 0x0000555555682340 in client_timeout_t1 (s=, usec=, userdata=0x5555559f5240) at dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp6-client.c:451 #2 0x00005555556a078f in time_ready (source=0x5555559f3c20) at dhcp-manager/systemd-dhcp/nm-sd-adapt.c:146 #3 0x00007ffff4a481b3 in g_timeout_dispatch () from /lib64/libglib-2.0.so.0 #4 0x00007ffff4a4779a in g_main_context_dispatch () from /lib64/libglib-2.0.so.0 #5 0x00007ffff4a47ae8 in g_main_context_iterate.isra.24 () from /lib64/libglib-2.0.so.0 #6 0x00007ffff4a47dba in g_main_loop_run () from /lib64/libglib-2.0.so.0 #7 0x0000555555597073 in main (argc=1, argv=0x7fffffffe2b8) at main.c:512 Equivalent upstream systemd patch: https://github.com/systemd/systemd/pull/1332 https://github.com/systemd/systemd/commit/f89087272b5561c9a3fc9d6a4e2a09f75f688fa7 https://bugzilla.redhat.com/show_bug.cgi?id=1260727 --- src/systemd/src/libsystemd-network/sd-dhcp6-client.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c index 5f1393c60c..ee61b4f114 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c @@ -864,7 +864,10 @@ static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *adver r = dhcp6_lease_get_preference(client->lease, &pref_lease); if (r < 0 || pref_advertise > pref_lease) { - sd_dhcp6_lease_unref(client->lease); + if (client->lease) { + dhcp6_lease_clear_timers(&client->lease->ia); + sd_dhcp6_lease_unref(client->lease); + } client->lease = lease; lease = NULL; r = 0;