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 15:40:35 +0200
commita331cf39804fa2f1f47148a82621aedabc87d939 (patch)
treeb590a18d16b486ceb90c6a437392d389c7178a4b
parent421f8a82bde62f8a16df48007633c7627118ff2a (diff)
downloadNetworkManager-a331cf39804fa2f1f47148a82621aedabc87d939.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