Skip to content

Commit 3afaa57

Browse files
SebTardifgitster
authored andcommitted
daemon: fix network address handling bugs
Fix three related issues in daemon.c's network address handling: lookup_hostname() calls getaddrinfo() with AF_UNSPEC hints, so it may return IPv6 results. However, the code unconditionally casts ai_addr to sockaddr_in and passes AF_INET to inet_ntop(). On IPv6-only hosts, this reads from the wrong struct offset, producing garbage IP addresses. Fix by checking ai_family and handling both AF_INET and AF_INET6. ip2str() passes the sockaddr struct size (ai_addrlen) as the output buffer size argument to inet_ntop(). For IPv6, sizeof(sockaddr_in6) is 28 bytes but INET6_ADDRSTRLEN is 46, so long IPv6 addresses are silently truncated. Fix by passing sizeof(ip) instead, and drop the now-unused len parameter. execute() logs "Connection from %s:%s" using REMOTE_ADDR and REMOTE_PORT environment variables, but only checks REMOTE_ADDR for NULL. If REMOTE_PORT is unset, NULL is passed to printf's %s, which is undefined behavior. Fix by using a fallback string. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 67ad421 commit 3afaa57

1 file changed

Lines changed: 19 additions & 12 deletions

File tree

daemon.c

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -674,10 +674,17 @@ static void lookup_hostname(struct hostinfo *hi)
674674

675675
gai = getaddrinfo(hi->hostname.buf, NULL, &hints, &ai);
676676
if (!gai) {
677-
struct sockaddr_in *sin_addr = (void *)ai->ai_addr;
678-
679-
inet_ntop(AF_INET, &sin_addr->sin_addr,
680-
addrbuf, sizeof(addrbuf));
677+
if (ai->ai_family == AF_INET) {
678+
struct sockaddr_in *sa =
679+
(struct sockaddr_in *)ai->ai_addr;
680+
inet_ntop(AF_INET, &sa->sin_addr,
681+
addrbuf, sizeof(addrbuf));
682+
} else if (ai->ai_family == AF_INET6) {
683+
struct sockaddr_in6 *sa6 =
684+
(struct sockaddr_in6 *)ai->ai_addr;
685+
inet_ntop(AF_INET6, &sa6->sin6_addr,
686+
addrbuf, sizeof(addrbuf));
687+
}
681688
strbuf_addstr(&hi->ip_address, addrbuf);
682689

683690
if (ai->ai_canonname)
@@ -742,7 +749,7 @@ static int execute(void)
742749
struct strvec env = STRVEC_INIT;
743750

744751
if (addr)
745-
loginfo("Connection from %s:%s", addr, port);
752+
loginfo("Connection from %s:%s", addr, port ? port : "?");
746753

747754
set_keep_alive(0);
748755
alarm(init_timeout ? init_timeout : timeout);
@@ -936,7 +943,7 @@ struct socketlist {
936943
size_t alloc;
937944
};
938945

939-
static const char *ip2str(int family, struct sockaddr *sin, socklen_t len)
946+
static const char *ip2str(int family, struct sockaddr *sin)
940947
{
941948
#ifdef NO_IPV6
942949
static char ip[INET_ADDRSTRLEN];
@@ -947,11 +954,11 @@ static const char *ip2str(int family, struct sockaddr *sin, socklen_t len)
947954
switch (family) {
948955
#ifndef NO_IPV6
949956
case AF_INET6:
950-
inet_ntop(family, &((struct sockaddr_in6*)sin)->sin6_addr, ip, len);
957+
inet_ntop(family, &((struct sockaddr_in6*)sin)->sin6_addr, ip, sizeof(ip));
951958
break;
952959
#endif
953960
case AF_INET:
954-
inet_ntop(family, &((struct sockaddr_in*)sin)->sin_addr, ip, len);
961+
inet_ntop(family, &((struct sockaddr_in*)sin)->sin_addr, ip, sizeof(ip));
955962
break;
956963
default:
957964
xsnprintf(ip, sizeof(ip), "<unknown>");
@@ -1008,14 +1015,14 @@ static int setup_named_sock(char *listen_addr, int listen_port, struct socketlis
10081015

10091016
if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
10101017
logerror("Could not bind to %s: %s",
1011-
ip2str(ai->ai_family, ai->ai_addr, ai->ai_addrlen),
1018+
ip2str(ai->ai_family, ai->ai_addr),
10121019
strerror(errno));
10131020
close(sockfd);
10141021
continue; /* not fatal */
10151022
}
10161023
if (listen(sockfd, 5) < 0) {
10171024
logerror("Could not listen to %s: %s",
1018-
ip2str(ai->ai_family, ai->ai_addr, ai->ai_addrlen),
1025+
ip2str(ai->ai_family, ai->ai_addr),
10191026
strerror(errno));
10201027
close(sockfd);
10211028
continue; /* not fatal */
@@ -1069,15 +1076,15 @@ static int setup_named_sock(char *listen_addr, int listen_port, struct socketlis
10691076

10701077
if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) {
10711078
logerror("Could not bind to %s: %s",
1072-
ip2str(AF_INET, (struct sockaddr *)&sin, sizeof(sin)),
1079+
ip2str(AF_INET, (struct sockaddr *)&sin),
10731080
strerror(errno));
10741081
close(sockfd);
10751082
return 0;
10761083
}
10771084

10781085
if (listen(sockfd, 5) < 0) {
10791086
logerror("Could not listen to %s: %s",
1080-
ip2str(AF_INET, (struct sockaddr *)&sin, sizeof(sin)),
1087+
ip2str(AF_INET, (struct sockaddr *)&sin),
10811088
strerror(errno));
10821089
close(sockfd);
10831090
return 0;

0 commit comments

Comments
 (0)