patch 9.2.0314: channel: can bind to all network interfaces
Commit:
https://github.com/vim/vim/commit/c3c34788109105781aa160d859f823981c0bc360
Author: Zdenek Dohnal <
zdo...@redhat.com>
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 <
zdo...@redhat.com>
Signed-off-by: Christian Brabandt <
c...@256bit.org>
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,
/**/