Skip to content

daemon: fix network address handling bugs

Sebastien Tardif via GitGitGadget git 3 versions – New

Get series with b4
b4 am [email protected]

Versions newest first · linked by author and title

  1. v3 Latest3 patches 0 repliesNew
  2. v23 patches 1 replySuperseded
  3. v13 patches 3 repliesSuperseded

Changes since v1 from the cover letter

* Split the single patch into three separate commits, one per fix, per Patrick's review.
* Deduplicated the address family handling in lookup_hostname(): instead of duplicating the inet_ntop() call for each family, the address pointer is extracted into a local void *addr variable first, then inet_ntop() is called once, per Patrick's suggestion.
* The (void *) intermediate cast on ai_addr is used intentionally: C guarantees any object pointer round-trips safely through void *, and it keeps the per-family blocks shorter than spelling out the full struct casts.
* For the REMOTE_PORT NULL guard: both REMOTE_ADDR and REMOTE_PORT are set by the same code path in handle(), so neither should be NULL independently. The guard makes the code consistent with the existing REMOTE_ADDR check and avoids undefined behavior from printf %s with a NULL argument.
* Die on unexpected address families in lookup_hostname() rather than silently leaving addrbuf uninitialized.

Patches in v3 No applies recorded yet

#Subject and filesSizeRepliesApplied
1/3daemon: fix IPv6 address corruption in lookup_hostname()daemon.c+13 -20 replies
2/3daemon: fix IPv6 address truncation in ip2str()daemon.c+7 -70 replies
3/3daemon: guard NULL REMOTE_PORT in execute() loggingdaemon.c+1 -10 replies

Reviews trailers per patch

No Reviewed-by, Acked-by or Tested-by trailers for v3 yet.

Read the v3 thread

Cover letter [PATCH v3 0/3] daemon: fix network address handling bugs

Fix three related issues in daemon.c's network address handling:

IPv6 address corruption in lookup_hostname(): getaddrinfo() is called 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. Fixed by checking ai_family and handling both AF_INET and AF_INET6.

IPv6 address truncation in ip2str(): The sockaddr struct size (ai_addrlen) is passed as the output buffer size to inet_ntop(). For IPv6, sizeof(sockaddr_in6) is 28 bytes but INET6_ADDRSTRLEN is 46, so long IPv6 addresses are silently truncated. Fixed by passing sizeof(ip) instead, and dropping the now-unused len parameter.

NULL pointer in execute() logging: REMOTE_PORT environment variable is used in a format string without a NULL check (only REMOTE_ADDR was checked). If REMOTE_PORT is unset, NULL is passed to printf's %s, which is undefined behavior. Fixed by using a fallback string.

Changes since v1:

* Split the single patch into three separate commits, one per fix, per Patrick's review.
* Deduplicated the address family handling in lookup_hostname(): instead of duplicating the inet_ntop() call for each family, the address pointer is extracted into a local void *addr variable first, then inet_ntop() is called once, per Patrick's suggestion.
* The (void *) intermediate cast on ai_addr is used intentionally: C guarantees any object pointer round-trips safely through void *, and it keeps the per-family blocks shorter than spelling out the full struct casts.
* For the REMOTE_PORT NULL guard: both REMOTE_ADDR and REMOTE_PORT are set by the same code path in handle(), so neither should be NULL independently. The guard makes the code consistent with the existing REMOTE_ADDR check and avoids undefined behavior from printf %s with a NULL argument.
* Die on unexpected address families in lookup_hostname() rather than silently leaving addrbuf uninitialized.

Sebastien Tardif (3):
daemon: fix IPv6 address corruption in lookup_hostname()
daemon: fix IPv6 address truncation in ip2str()
daemon: guard NULL REMOTE_PORT in execute() logging

 daemon.c | 31 +++++++++++++++++++++----------
 1 file changed, 21 insertions(+), 10 deletions(-)

base-commit: 59ff4886a579f4bc91e976fe18590b9ae02c7a08
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2300%2FSebTardif%2Ffix%2Fdaemon-ipv6-and-null-port-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2300/SebTardif/fix/daemon-ipv6-and-null-port-v3
Pull-Request: https://github.com/git/git/pull/2300

Range-diff vs v2:

 1:  b2d8143811 = 1:  b2d8143811 daemon: fix IPv6 address corruption in lookup_hostname()
 2:  5c01ec3cad = 2:  5c01ec3cad daemon: fix IPv6 address truncation in ip2str()
 3:  e312735716 ! 3:  4e74294071 daemon: guard NULL REMOTE_PORT in execute() logging

@@ Commit message
daemon: guard NULL REMOTE_PORT in execute() logging

REMOTE_ADDR and REMOTE_PORT are both set by the same code path in
- handle(), so neither should be NULL independently. However, the
- existing code checks REMOTE_ADDR before the loginfo() call but not
- REMOTE_PORT. If REMOTE_PORT were unset, NULL would be passed to
+ handle(), so when the existing REMOTE_ADDR check passes, REMOTE_PORT
+ is guaranteed to be non-NULL. Guard REMOTE_PORT as well so that a
+ future change that breaks this invariant does not pass NULL to
printf's %s, which is undefined behavior.

- Add a fallback string for the NULL case, matching the existing
- REMOTE_ADDR guard for consistency.
-

## daemon.c ##

Signature · 1 line
gitgitgadget