patch 9.2.0314: channel: can bind to all network interfaces

Commit: 
https://github.com/vim/vim/commit/c3c34788109105781aa160d859f823981c0bc360
Author: Zdenek Dohnal <[email protected]>
Date:   Mon Apr 6 13:42:42 2026 +0000

    patch 9.2.0314: channel: can bind to all network interfaces
    
    Problem:  channel: can bind to all network interfaces in ch_listen()
              (after v9.2.0153)
    Solution: Restrict to a valid hostname, do not allow to bind on all
              network interfaces (Zdenek Dohnal).
    
    This will prevent unintentional binding the process to public network
    interfaces, and opening Vim to communication from outside network if
    firewall allows it.
    
    related: #19231
    closes:  #19799
    
    Signed-off-by: Zdenek Dohnal <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/runtime/doc/channel.txt b/runtime/doc/channel.txt
index f458c1369..55b95c632 100644
--- a/runtime/doc/channel.txt
+++ b/runtime/doc/channel.txt
@@ -674,7 +674,9 @@ ch_listen({address} [, {options}])          *E1573* *E1574* 
*ch_listen()*
                Returns a Channel.  Use |ch_status()| to check for failure.
 
                {address} is a String, see |channel-address| for the possible
-               accepted forms.  Note: IPv6 is not yet supported.
+               accepted forms, however binding to all interfaces is not
+               allowed for security reasons.
+               Note: IPv6 is not yet supported.
 
                If {options} is given it must be a |Dictionary|.
                See |channel-open-options|.
diff --git a/src/channel.c b/src/channel.c
index 442c33a50..37f0bf1be 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -1513,6 +1513,12 @@ channel_listen(
     int                        val = 1;
     channel_T          *channel;
 
+    if (hostname == NULL || *hostname == NUL)
+    {
+       ch_error(NULL, "Hostname/address not defined.");
+       return NULL;
+    }
+
 #ifdef MSWIN
     channel_init_winsock();
 #endif
@@ -1529,47 +1535,42 @@ channel_listen(
     vim_memset((char *)&server, 0, sizeof(server));
     server.sin_family = AF_INET;
     server.sin_port = htons(port_in);
-    if (hostname != NULL && *hostname != NUL)
-    {
+
 #ifdef FEAT_IPV6
-       struct addrinfo hints;
-       struct addrinfo *res = NULL;
-       int             err;
-
-       CLEAR_FIELD(hints);
-       hints.ai_family = AF_INET;
-       hints.ai_socktype = SOCK_STREAM;
-       if ((err = getaddrinfo(hostname, NULL, &hints, &res)) != 0)
-       {
-           ch_error(channel, "in getaddrinfo() in channel_listen()");
-           PERROR(_(e_gethostbyname_in_channel_listen));
-           channel_free(channel);
-           return NULL;
-       }
-       memcpy(&server.sin_addr,
-               &((struct sockaddr_in *)res->ai_addr)->sin_addr,
-               sizeof(server.sin_addr));
-       freeaddrinfo(res);
+    struct addrinfo    hints;
+    struct addrinfo    *res = NULL;
+    int                err;
+
+    CLEAR_FIELD(hints);
+    hints.ai_family = AF_INET;
+    hints.ai_socktype = SOCK_STREAM;
+    if ((err = getaddrinfo(hostname, NULL, &hints, &res)) != 0)
+    {
+       ch_error(channel, "in getaddrinfo() in channel_listen()");
+       PERROR(_(e_gethostbyname_in_channel_listen));
+       channel_free(channel);
+       return NULL;
+    }
+    memcpy(&server.sin_addr,
+       &((struct sockaddr_in *)res->ai_addr)->sin_addr,
+       sizeof(server.sin_addr));
+    freeaddrinfo(res);
 #else
-       if ((host = gethostbyname(hostname)) == NULL)
-       {
-           ch_error(channel, "in gethostbyname() in channel_listen()");
-           PERROR(_(e_gethostbyname_in_channel_listen));
-           channel_free(channel);
-           return NULL;
-       }
-       {
-           char                *p;
+    if ((host = gethostbyname(hostname)) == NULL)
+    {
+       ch_error(channel, "in gethostbyname() in channel_listen()");
+       PERROR(_(e_gethostbyname_in_channel_listen));
+       channel_free(channel);
+       return NULL;
+    }
 
-           // When using host->h_addr_list[0] directly ubsan warns for it to
-           // not be aligned.  First copy the pointer to avoid that.
-           memcpy(&p, &host->h_addr_list[0], sizeof(p));
-           memcpy((char *)&server.sin_addr, p, host->h_length);
-       }
+    char               *p;
+
+    // When using host->h_addr_list[0] directly ubsan warns for it to
+    // not be aligned.  First copy the pointer to avoid that.
+    memcpy(&p, &host->h_addr_list[0], sizeof(p));
+    memcpy((char *)&server.sin_addr, p, host->h_length);
 #endif
-    }
-    else
-       server.sin_addr.s_addr = htonl(INADDR_ANY);
 
     sd = socket(AF_INET, SOCK_STREAM, 0);
     if (sd == -1)
@@ -1631,7 +1632,7 @@ channel_listen(
     channel->ch_listen = TRUE;
     channel->CH_SOCK_FD = (sock_T)sd;
     channel->ch_nb_close_cb = nb_close_cb;
-    channel->ch_hostname = (char *)vim_strsave((char_u *)(hostname != NULL ? 
hostname : ""));
+    channel->ch_hostname = (char *)vim_strsave((char_u *)hostname);
     channel->ch_port = port_in;
     channel->ch_to_be_closed |= (1U << PART_SOCK);
 
diff --git a/src/version.c b/src/version.c
index 438790124..0c3123cd9 100644
--- a/src/version.c
+++ b/src/version.c
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    314,
 /**/
     313,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1w9kUm-006v0V-Pw%40256bit.org.

Raspunde prin e-mail lui