diff options
author | David Herrmann <dh.herrmann@googlemail.com> | 2016-06-07 10:38:33 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2016-06-07 10:38:33 +0200 |
commit | 82e4eda664d40ef60829e27d84b1610c2f4070cd (patch) | |
tree | 2343814aeed404b9f112c77fd04069bccb5d7b5f | |
parent | 138f4c69064504bf7ef83cc8a53133f007ad84d6 (diff) |
sd-netlink: fix deep recursion in message destruction (#3455)
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).
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-message.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c index 86d8dee867..df3b3c922e 100644 --- a/src/libsystemd/sd-netlink/netlink-message.c +++ b/src/libsystemd/sd-netlink/netlink-message.c @@ -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; |