Unverified Commit fa7b54f5 authored by Minseong Choi's avatar Minseong Choi 💬
Browse files

fix(bootstrap): refuse an unbracketed ipv6 nano listen address

validate_listen checked only the port, so FELIS_NANO_LISTEN=::1:8081
passed. Go refuses that form ("too many colons in address") and needs
[::1]:8081, so the unit crash-looped on every start. A host part that
contains a colon must now be in brackets.

With that, the bare ::1 pattern in nano_listen_is_loopback can no
longer match an address that gets this far, so it goes. [::1] stays.
The harness adds ::1:8081 to the refused addresses, and [::]:8081 and
:8081, both of which Go binds, to the accepted ones.
parent 928a1fdf
Loading
Loading
Loading
Loading
+6 −2
Changes for deploy/bootstrap.sh: 6 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -453,12 +453,16 @@ validate_nodeport() {
# port 8081 while nano binds nothing, 127.0.0.1 prints http://127.0.0.1:127.0.0.1/..., and
# the unit crash-loops either way.
validate_listen() {
  local name="$1" value="$2" port="${2##*:}"
  local name="$1" value="$2" port="${2##*:}" host="${2%:*}"
  case "$value" in *:*) ;; *) port="" ;; esac
  case "$port" in
    ''|*[!0-9]*) die "${name} must be host:port (for example 127.0.0.1:8081), got: ${value}" ;;
  esac
  [ "$port" -ge 1 ] && [ "$port" -le 65535 ] || die "${name} port must be 1-65535, got: ${value}"
  # Go takes a colon in the host only inside brackets; ::1:8081 would crash-loop the unit.
  case "$host" in
    *:*) case "$host" in "["*"]") ;; *) die "${name} needs an IPv6 host in brackets (for example [::1]:8081), got: ${value}" ;; esac ;;
  esac
}

validate_settings() {
@@ -2410,7 +2414,7 @@ resolve_nano_listen() {

nano_listen_is_loopback() {
  case "${FELIS_NANO_LISTEN%:*}" in
    127.*|localhost|::1|"[::1]") return 0 ;;
    127.*|localhost|"[::1]") return 0 ;;
    *) return 1 ;;
  esac
}
+2 −2
Changes for deploy/bootstrap_test.sh: 2 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -295,10 +295,10 @@ check_listen() { # value
    validate_listen FELIS_NANO_LISTEN "$1" && echo VALID' _ "$1" 2>&1
}

for v in 8081 127.0.0.1 127.0.0.1:0 127.0.0.1:65536 127.0.0.1:x; do
for v in 8081 127.0.0.1 127.0.0.1:0 127.0.0.1:65536 127.0.0.1:x ::1:8081; do
  expect "listen address $v is refused" "DIE: FELIS_NANO_LISTEN" "$(check_listen "$v")"
done
for v in '[::1]:8081' 0.0.0.0:8081 127.0.0.1:8081; do
for v in '[::1]:8081' '[::]:8081' :8081 0.0.0.0:8081 127.0.0.1:8081; do
  expect "listen address $v is accepted" VALID "$(check_listen "$v")"
done