@@ -1698,6 +1698,8 @@ register_listener(struct server_address *addr, struct sudo_event_base *evbase)
16981698 /* TODO: make non-fatal */
16991699 if ((l = malloc (sizeof (* l ))) == NULL )
17001700 sudo_fatalx (U_ ("%s: %s" ), __func__ , U_ ("unable to allocate memory" ));
1701+ l -> sa_str = addr -> sa_str ;
1702+ sudo_rcstr_addref (l -> sa_str );
17011703 l -> sock = sock ;
17021704 l -> tls = addr -> tls ;
17031705 l -> ev = sudo_ev_alloc (sock , SUDO_EV_READ |SUDO_EV_PERSIST , listener_cb , l );
@@ -1716,22 +1718,63 @@ register_listener(struct server_address *addr, struct sudo_event_base *evbase)
17161718static bool
17171719server_setup (struct sudo_event_base * base )
17181720{
1721+ struct listener_list kept_listeners =
1722+ TAILQ_HEAD_INITIALIZER (kept_listeners );
17191723 struct server_address * addr ;
17201724 struct listener * l ;
17211725 int nlisteners = 0 ;
17221726 bool ret ;
17231727 debug_decl (server_setup , SUDO_DEBUG_UTIL );
17241728
1725- /* Free old listeners (if any) and register new ones. */
1729+ /*
1730+ * Free any listeners not present in the new config.
1731+ * We must free non-matching listeners before adding new ones.
1732+ */
17261733 while ((l = TAILQ_FIRST (& listeners )) != NULL ) {
17271734 TAILQ_REMOVE (& listeners , l , entries );
1728- sudo_ev_free (l -> ev );
1729- close (l -> sock );
1730- free (l );
1735+
1736+ TAILQ_FOREACH (addr , logsrvd_conf_server_listen_address (), entries ) {
1737+ if (strcmp (addr -> sa_str , l -> sa_str ) == 0 ) {
1738+ TAILQ_INSERT_TAIL (& kept_listeners , l , entries );
1739+ break ;
1740+ }
1741+ }
1742+ if (addr == NULL ) {
1743+ /* Listener not used in new config. */
1744+ sudo_rcstr_delref (l -> sa_str );
1745+ sudo_ev_free (l -> ev );
1746+ close (l -> sock );
1747+ free (l );
1748+ }
17311749 }
1750+
1751+ /* Register new listeners, reusing existing ones. */
17321752 TAILQ_FOREACH (addr , logsrvd_conf_server_listen_address (), entries ) {
1733- nlisteners += register_listener (addr , base );
1753+ /* Check for addr in kept_listeners first. */
1754+ TAILQ_FOREACH (l , & kept_listeners , entries ) {
1755+ if (strcmp (addr -> sa_str , l -> sa_str ) == 0 ) {
1756+ /* Reuse existing listener. */
1757+ TAILQ_REMOVE (& kept_listeners , l , entries );
1758+ TAILQ_INSERT_TAIL (& listeners , l , entries );
1759+
1760+ /* Update l->sa_str from new addr. */
1761+ sudo_rcstr_delref (l -> sa_str );
1762+ l -> sa_str = addr -> sa_str ;
1763+ sudo_rcstr_addref (l -> sa_str );
1764+
1765+ nlisteners ++ ;
1766+ break ;
1767+ }
1768+ }
1769+
1770+ if (l == NULL ) {
1771+ /* Register new listener. */
1772+ nlisteners += register_listener (addr , base );
1773+ }
17341774 }
1775+ if (!TAILQ_EMPTY (& kept_listeners ))
1776+ sudo_warnx ("bug: kept_listeners not empty" );
1777+
17351778 ret = nlisteners > 0 ;
17361779
17371780#if defined(HAVE_OPENSSL )
0 commit comments