diff options
author | Thomas Haller <thaller@redhat.com> | 2015-09-22 12:44:14 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2015-09-23 16:09:43 +0200 |
commit | 9901047ae3464999ab5c52ac408f603c73239597 (patch) | |
tree | 3b92cb6e8b25ca1bfd12cc0fc2d2e8fbf8a29802 | |
parent | fb0e87be394c0fdb4ccf2911bd089bbdf0b19113 (diff) | |
download | NetworkManager-9901047ae3464999ab5c52ac408f603c73239597.tar.gz |
systemd/adapt: fix potential crash invoking sd_event_source callbacks
It is common that the callbacks unref the event source. Hence we must
ensure that the @source stays alive until the callback returns.
-rw-r--r-- | src/systemd/nm-sd-adapt.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/src/systemd/nm-sd-adapt.c b/src/systemd/nm-sd-adapt.c index 1f6038e9c9..67ddc8da1b 100644 --- a/src/systemd/nm-sd-adapt.c +++ b/src/systemd/nm-sd-adapt.c @@ -91,6 +91,7 @@ static gboolean io_ready (GIOChannel *channel, GIOCondition condition, struct sd_event_source *source) { int r, revents = 0; + gboolean result; if (condition & G_IO_IN) revents |= EPOLLIN; @@ -103,13 +104,18 @@ io_ready (GIOChannel *channel, GIOCondition condition, struct sd_event_source *s if (condition & G_IO_HUP) revents |= EPOLLHUP; + source->refcount++; + r = source->io_cb (source, g_io_channel_unix_get_fd (channel), revents, source->user_data); - if (r < 0) { + if (r < 0 || source->refcount <= 1) { source->id = 0; - return G_SOURCE_REMOVE; - } + result = G_SOURCE_REMOVE; + } else + result = G_SOURCE_CONTINUE; + + sd_event_source_unref (source); - return G_SOURCE_CONTINUE; + return result; } int @@ -151,14 +157,20 @@ static gboolean time_ready (struct sd_event_source *source) { int r; + gboolean result; + + source->refcount++; r = source->time_cb (source, source->usec, source->user_data); - if (r < 0) { + if (r < 0 || source->refcount <= 1) { source->id = 0; - return G_SOURCE_REMOVE; - } + result = G_SOURCE_REMOVE; + } else + result = G_SOURCE_CONTINUE; + + sd_event_source_unref (source); - return G_SOURCE_CONTINUE; + return result; } int |