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.