summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@googlemail.com>2016-06-07 10:38:33 +0200
committerLennart Poettering <lennart@poettering.net>2016-06-07 10:38:33 +0200
commit82e4eda664d40ef60829e27d84b1610c2f4070cd (patch)
tree2343814aeed404b9f112c77fd04069bccb5d7b5f
parent138f4c69064504bf7ef83cc8a53133f007ad84d6 (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.c10
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;