summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-09-22 12:44:14 +0200
committerThomas Haller <thaller@redhat.com>2015-09-23 16:09:43 +0200
commit9901047ae3464999ab5c52ac408f603c73239597 (patch)
tree3b92cb6e8b25ca1bfd12cc0fc2d2e8fbf8a29802
parentfb0e87be394c0fdb4ccf2911bd089bbdf0b19113 (diff)
downloadNetworkManager-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.c28
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