diff options
author | Thomas Haller <thaller@redhat.com> | 2015-09-22 12:44:14 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2015-09-23 15:40:35 +0200 |
commit | a331cf39804fa2f1f47148a82621aedabc87d939 (patch) | |
tree | b590a18d16b486ceb90c6a437392d389c7178a4b | |
parent | 421f8a82bde62f8a16df48007633c7627118ff2a (diff) | |
download | NetworkManager-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.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 |