From 4e97a0bf8488204cdaf6a107d433e042f91dad24 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Sat, 12 Oct 2013 17:29:26 +0200 Subject: [PATCH] lib: fix a segfault introduced in ef3707 when freeing an atom In the change "lldpd: make notifications work when a port goes down", a regression was introduced. It is important to never call `TAILQ_REMOVE` on a marshalled struct, like when we are in liblldpctl. This is because the marshalling process does not keep a real list (prev pointer is incorrect). The change ef3707 did introduce a regression by calling TAILQ_REMOVE in a case where it is useless. We only need to call TAILQ_REMOVE if we won't empty the whole list. So when we call `lldpd_remote_cleanup()` with `all` set to `1`, we don't need to call TAILQ_REMOVE. --- src/lldpd-structs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lldpd-structs.c b/src/lldpd-structs.c index 5c907f0d..12fe3b81 100644 --- a/src/lldpd-structs.c +++ b/src/lldpd-structs.c @@ -131,7 +131,11 @@ lldpd_remote_cleanup(struct lldpd_hardware *hardware, } if (del) { if (expire) expire(hardware, port); - TAILQ_REMOVE(&hardware->h_rports, port, p_entries); + /* This TAILQ_REMOVE is dangerous. It should not be + * called while in liblldpctl because we don't have a + * real list. It is only needed to be called when we + * don't delete the entire list. */ + if (!all) TAILQ_REMOVE(&hardware->h_rports, port, p_entries); lldpd_port_cleanup(port, 1); free(port); } -- 2.39.5