Skip to content

Commit c3c3478

Browse files
zdohnalchrisbra
authored andcommitted
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]>
1 parent aef8124 commit c3c3478

3 files changed

Lines changed: 44 additions & 39 deletions

File tree

runtime/doc/channel.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,9 @@ ch_listen({address} [, {options}]) *E1573* *E1574* *ch_listen()*
674674
Returns a Channel. Use |ch_status()| to check for failure.
675675

676676
{address} is a String, see |channel-address| for the possible
677-
accepted forms. Note: IPv6 is not yet supported.
677+
accepted forms, however binding to all interfaces is not
678+
allowed for security reasons.
679+
Note: IPv6 is not yet supported.
678680

679681
If {options} is given it must be a |Dictionary|.
680682
See |channel-open-options|.

src/channel.c

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,6 +1513,12 @@ channel_listen(
15131513
int val = 1;
15141514
channel_T *channel;
15151515

1516+
if (hostname == NULL || *hostname == NUL)
1517+
{
1518+
ch_error(NULL, "Hostname/address not defined.");
1519+
return NULL;
1520+
}
1521+
15161522
#ifdef MSWIN
15171523
channel_init_winsock();
15181524
#endif
@@ -1529,47 +1535,42 @@ channel_listen(
15291535
vim_memset((char *)&server, 0, sizeof(server));
15301536
server.sin_family = AF_INET;
15311537
server.sin_port = htons(port_in);
1532-
if (hostname != NULL && *hostname != NUL)
1533-
{
1538+
15341539
#ifdef FEAT_IPV6
1535-
struct addrinfo hints;
1536-
struct addrinfo *res = NULL;
1537-
int err;
1538-
1539-
CLEAR_FIELD(hints);
1540-
hints.ai_family = AF_INET;
1541-
hints.ai_socktype = SOCK_STREAM;
1542-
if ((err = getaddrinfo(hostname, NULL, &hints, &res)) != 0)
1543-
{
1544-
ch_error(channel, "in getaddrinfo() in channel_listen()");
1545-
PERROR(_(e_gethostbyname_in_channel_listen));
1546-
channel_free(channel);
1547-
return NULL;
1548-
}
1549-
memcpy(&server.sin_addr,
1550-
&((struct sockaddr_in *)res->ai_addr)->sin_addr,
1551-
sizeof(server.sin_addr));
1552-
freeaddrinfo(res);
1540+
struct addrinfo hints;
1541+
struct addrinfo *res = NULL;
1542+
int err;
1543+
1544+
CLEAR_FIELD(hints);
1545+
hints.ai_family = AF_INET;
1546+
hints.ai_socktype = SOCK_STREAM;
1547+
if ((err = getaddrinfo(hostname, NULL, &hints, &res)) != 0)
1548+
{
1549+
ch_error(channel, "in getaddrinfo() in channel_listen()");
1550+
PERROR(_(e_gethostbyname_in_channel_listen));
1551+
channel_free(channel);
1552+
return NULL;
1553+
}
1554+
memcpy(&server.sin_addr,
1555+
&((struct sockaddr_in *)res->ai_addr)->sin_addr,
1556+
sizeof(server.sin_addr));
1557+
freeaddrinfo(res);
15531558
#else
1554-
if ((host = gethostbyname(hostname)) == NULL)
1555-
{
1556-
ch_error(channel, "in gethostbyname() in channel_listen()");
1557-
PERROR(_(e_gethostbyname_in_channel_listen));
1558-
channel_free(channel);
1559-
return NULL;
1560-
}
1561-
{
1562-
char *p;
1559+
if ((host = gethostbyname(hostname)) == NULL)
1560+
{
1561+
ch_error(channel, "in gethostbyname() in channel_listen()");
1562+
PERROR(_(e_gethostbyname_in_channel_listen));
1563+
channel_free(channel);
1564+
return NULL;
1565+
}
15631566

1564-
// When using host->h_addr_list[0] directly ubsan warns for it to
1565-
// not be aligned. First copy the pointer to avoid that.
1566-
memcpy(&p, &host->h_addr_list[0], sizeof(p));
1567-
memcpy((char *)&server.sin_addr, p, host->h_length);
1568-
}
1567+
char *p;
1568+
1569+
// When using host->h_addr_list[0] directly ubsan warns for it to
1570+
// not be aligned. First copy the pointer to avoid that.
1571+
memcpy(&p, &host->h_addr_list[0], sizeof(p));
1572+
memcpy((char *)&server.sin_addr, p, host->h_length);
15691573
#endif
1570-
}
1571-
else
1572-
server.sin_addr.s_addr = htonl(INADDR_ANY);
15731574

15741575
sd = socket(AF_INET, SOCK_STREAM, 0);
15751576
if (sd == -1)
@@ -1631,7 +1632,7 @@ channel_listen(
16311632
channel->ch_listen = TRUE;
16321633
channel->CH_SOCK_FD = (sock_T)sd;
16331634
channel->ch_nb_close_cb = nb_close_cb;
1634-
channel->ch_hostname = (char *)vim_strsave((char_u *)(hostname != NULL ? hostname : ""));
1635+
channel->ch_hostname = (char *)vim_strsave((char_u *)hostname);
16351636
channel->ch_port = port_in;
16361637
channel->ch_to_be_closed |= (1U << PART_SOCK);
16371638

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,8 @@ static char *(features[]) =
734734

735735
static int included_patches[] =
736736
{ /* Add new patch number below this line */
737+
/**/
738+
314,
737739
/**/
738740
313,
739741
/**/

0 commit comments

Comments
 (0)