]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
daemon/event: avoid double-free of client on send failure
authorVincent Bernat <vincent@bernat.ch>
Sat, 9 May 2026 12:58:39 +0000 (14:58 +0200)
committerVincent Bernat <vincent@bernat.ch>
Sat, 9 May 2026 13:26:12 +0000 (15:26 +0200)
levent_ctl_send() used to free the client on write failure. When
called via levent_ctl_send_cb() from client_handle_client() inside
levent_ctl_recv(), the recv side then jumped to recv_error and freed
the same client a second time.

Stop freeing inside levent_ctl_send() and make the caller responsible
(levent_ctl_notify() now frees on -1; the recv path already does).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
src/daemon/event.c

index d117bc5be6aaf3cd5db39b6c09b49d93e722cbaa..24602191612605cba3072c1ff7d5648b459d4ac3 100644 (file)
@@ -258,6 +258,8 @@ levent_ctl_close_clients()
        }
 }
 
+/* Returns the number of bytes written, or -1 on error. On error, the caller
+ * is responsible for freeing the client. */
 static ssize_t
 levent_ctl_send(struct lldpd_one_client *client, int type, void *data, size_t len)
 {
@@ -267,7 +269,6 @@ levent_ctl_send(struct lldpd_one_client *client, int type, void *data, size_t le
        if (bufferevent_write(bev, &hdr, sizeof(struct hmsg_header)) == -1 ||
            (len > 0 && bufferevent_write(bev, data, len) == -1)) {
                log_warnx("event", "unable to create answer to client");
-               levent_ctl_free_client(client);
                return -1;
        }
        bufferevent_enable(bev, EV_WRITE);
@@ -309,7 +310,8 @@ levent_ctl_notify(char *ifname, char *ifalias, int state, struct lldpd_port *nei
                        }
                }
 
-               levent_ctl_send(client, NOTIFICATION, output, output_len);
+               if (levent_ctl_send(client, NOTIFICATION, output, output_len) == -1)
+                       levent_ctl_free_client(client);
        }
 
        free(output);