]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-netlink: fix deep recursion in message destruction (#3455)
authorDavid Herrmann <dh.herrmann@googlemail.com>
Tue, 7 Jun 2016 08:38:33 +0000 (10:38 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 7 Jun 2016 08:38:33 +0000 (10:38 +0200)
On larger systems we might very well see messages with thousands of parts.
When we free them, we must avoid recursing into each part, otherwise we
very likely get stack overflows.

Fix sd_netlink_message_unref() to use an iterative approach rather than
recursion (also avoid tail-recursion in case it is not optimized by the
compiler).

src/libsystemd/sd-netlink/netlink-message.c

index 86d8dee8673a227c312dcd599c4cb3d2e7b94f88..df3b3c922e044dcc951115e75be77503b1184fb5 100644 (file)
@@ -120,7 +120,9 @@ sd_netlink_message *sd_netlink_message_ref(sd_netlink_message *m) {
 }
 
 sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m) {
-        if (m && REFCNT_DEC(m->n_ref) == 0) {
+        sd_netlink_message *t;
+
+        while (m && REFCNT_DEC(m->n_ref) == 0) {
                 unsigned i;
 
                 free(m->hdr);
@@ -128,9 +130,9 @@ sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m) {
                 for (i = 0; i <= m->n_containers; i++)
                         free(m->containers[i].attributes);
 
-                sd_netlink_message_unref(m->next);
-
-                free(m);
+                t = m;
+                m = m->next;
+                free(t);
         }
 
         return NULL;