]> Cypherpunks repositories - gostls13.git/commitdiff
net: force cgo for myhostname and mdns nss modules for LookupAddr on unix
authorMateusz Poliwczak <mpoliwczak34@gmail.com>
Sun, 7 May 2023 16:46:42 +0000 (16:46 +0000)
committerGopher Robot <gobot@golang.org>
Thu, 11 May 2023 16:17:04 +0000 (16:17 +0000)
Currently there is a small bug in the LookupAddr for unix systems
that causes the use of go resolver instead of the cgo one.
Example for nss myhostname:

func main() {
        fmt.Println(net.LookupAddr(os.Args[1]))
}

root@arch:~# cat /etc/nsswitch.conf | grep host
hosts:          myhostname dns
root@arch:~# GODEBUG=netdns=+3 go run main.go 192.168.1.200
go package net: confVal.netCgo = false  netGo = false
go package net: dynamic selection of DNS resolver
go package net: hostLookupOrder() = dns
[] lookup 200.1.168.192.in-addr.arpa. on 8.8.8.8:53: no such host
root@arch:~# GODEBUG=netdns=go+3 go run main.go 192.168.1.200
go package net: confVal.netCgo = false  netGo = true
go package net: GODEBUG setting forcing use of Go's resolver
go package net: hostLookupOrder() = dns
[] lookup 200.1.168.192.in-addr.arpa. on 8.8.8.8:53: no such host
root@arch:~# GODEBUG=netdns=cgo+3 go run main.go 192.168.1.200
go package net: confVal.netCgo = true  netGo = false
go package net: using cgo DNS resolver
go package net: hostLookupOrder() = cgo
[arch] <nil>

The problem come from that we are only checking for hostnames that the
myhostname can resolve, but not for the addrs that it can also.

man  nss-myhostname:
       Please keep in mind that nss-myhostname (and nss-resolve) also
       resolve in the other direction — from locally attached IP
       addresses to hostnames.

Change-Id: Ic18a9f99a2214b2938463e9a95f7f3ca5db1c01b
GitHub-Last-Rev: ade40fd3e3057de418b9b6a79f79fb9a53fb6c09
GitHub-Pull-Request: golang/go#59921
Reviewed-on: https://go-review.googlesource.com/c/go/+/491235
Run-TryBot: Ian Lance Taylor <iant@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Mateusz Poliwczak <mpoliwczak34@gmail.com>

src/net/conf.go
src/net/conf_test.go
src/net/lookup_unix.go

index d11a5685027718c86298f41f257c4c906e5d9293..10bc8c366e1a82f397c8d0f2ae4e18c723a6148c 100644 (file)
@@ -188,6 +188,18 @@ func (c *conf) mustUseGoResolver(r *Resolver) bool {
        return c.netGo || r.preferGo() || !cgoAvailable
 }
 
+// addrLookupOrder determines which strategy to use to resolve addresses.
+// The provided Resolver is optional. nil means to not consider its options.
+// It also returns dnsConfig when it was used to determine the lookup order.
+func (c *conf) addrLookupOrder(r *Resolver, addr string) (ret hostLookupOrder, dnsConf *dnsConfig) {
+       if c.dnsDebugLevel > 1 {
+               defer func() {
+                       print("go package net: addrLookupOrder(", addr, ") = ", ret.String(), "\n")
+               }()
+       }
+       return c.lookupOrder(r, "")
+}
+
 // hostLookupOrder determines which strategy to use to resolve hostname.
 // The provided Resolver is optional. nil means to not consider its options.
 // It also returns dnsConfig when it was used to determine the lookup order.
@@ -197,7 +209,10 @@ func (c *conf) hostLookupOrder(r *Resolver, hostname string) (ret hostLookupOrde
                        print("go package net: hostLookupOrder(", hostname, ") = ", ret.String(), "\n")
                }()
        }
+       return c.lookupOrder(r, hostname)
+}
 
+func (c *conf) lookupOrder(r *Resolver, hostname string) (ret hostLookupOrder, dnsConf *dnsConfig) {
        // fallbackOrder is the order we return if we can't figure it out.
        var fallbackOrder hostLookupOrder
 
@@ -339,23 +354,9 @@ func (c *conf) hostLookupOrder(r *Resolver, hostname string) (ret hostLookupOrde
                return fallbackOrder, dnsConf
        }
 
-       var mdnsSource, filesSource, dnsSource, unknownSource bool
+       var filesSource, dnsSource, unknownSource bool
        var first string
        for _, src := range srcs {
-               if src.source == "myhostname" {
-                       // Let the cgo resolver handle myhostname
-                       // if we are looking up the local hostname.
-                       if canUseCgo {
-                               if isLocalhost(hostname) || isGateway(hostname) || isOutbound(hostname) {
-                                       return hostLookupCgo, dnsConf
-                               }
-                               hn, err := getHostname()
-                               if err != nil || stringsEqualFold(hostname, hn) {
-                                       return hostLookupCgo, dnsConf
-                               }
-                       }
-                       continue
-               }
                if src.source == "files" || src.source == "dns" {
                        if canUseCgo && !src.standardCriteria() {
                                // non-standard; let libc deal with it.
@@ -371,16 +372,50 @@ func (c *conf) hostLookupOrder(r *Resolver, hostname string) (ret hostLookupOrde
                        }
                        continue
                }
-               if stringsHasPrefix(src.source, "mdns") {
-                       // e.g. "mdns4", "mdns4_minimal"
-                       // We already returned true before if it was *.local.
-                       // libc wouldn't have found a hit on this anyway.
-                       mdnsSource = true
-                       continue
-               }
-               // Some source we don't know how to deal with.
+
                if canUseCgo {
-                       return hostLookupCgo, dnsConf
+                       switch {
+                       case hostname != "" && src.source == "myhostname":
+                               // Let the cgo resolver handle myhostname
+                               // if we are looking up the local hostname.
+                               if isLocalhost(hostname) || isGateway(hostname) || isOutbound(hostname) {
+                                       return hostLookupCgo, dnsConf
+                               }
+                               hn, err := getHostname()
+                               if err != nil || stringsEqualFold(hostname, hn) {
+                                       return hostLookupCgo, dnsConf
+                               }
+                               continue
+                       case hostname != "" && stringsHasPrefix(src.source, "mdns"):
+                               // e.g. "mdns4", "mdns4_minimal"
+                               // We already returned true before if it was *.local.
+                               // libc wouldn't have found a hit on this anyway.
+
+                               // We don't parse mdns.allow files. They're rare. If one
+                               // exists, it might list other TLDs (besides .local) or even
+                               // '*', so just let libc deal with it.
+                               var haveMDNSAllow bool
+                               switch c.mdnsTest {
+                               case mdnsFromSystem:
+                                       _, err := os.Stat("/etc/mdns.allow")
+                                       if err != nil && !errors.Is(err, fs.ErrNotExist) {
+                                               // Let libc figure out what is going on.
+                                               return hostLookupCgo, dnsConf
+                                       }
+                                       haveMDNSAllow = err == nil
+                               case mdnsAssumeExists:
+                                       haveMDNSAllow = true
+                               case mdnsAssumeDoesNotExist:
+                                       haveMDNSAllow = false
+                               }
+                               if haveMDNSAllow {
+                                       return hostLookupCgo, dnsConf
+                               }
+                               continue
+                       default:
+                               // Some source we don't know how to deal with.
+                               return hostLookupCgo, dnsConf
+                       }
                }
 
                unknownSource = true
@@ -389,29 +424,6 @@ func (c *conf) hostLookupOrder(r *Resolver, hostname string) (ret hostLookupOrde
                }
        }
 
-       // We don't parse mdns.allow files. They're rare. If one
-       // exists, it might list other TLDs (besides .local) or even
-       // '*', so just let libc deal with it.
-       if canUseCgo && mdnsSource {
-               var haveMDNSAllow bool
-               switch c.mdnsTest {
-               case mdnsFromSystem:
-                       _, err := os.Stat("/etc/mdns.allow")
-                       if err != nil && !errors.Is(err, fs.ErrNotExist) {
-                               // Let libc figure out what is going on.
-                               return hostLookupCgo, dnsConf
-                       }
-                       haveMDNSAllow = err == nil
-               case mdnsAssumeExists:
-                       haveMDNSAllow = true
-               case mdnsAssumeDoesNotExist:
-                       haveMDNSAllow = false
-               }
-               if haveMDNSAllow {
-                       return hostLookupCgo, dnsConf
-               }
-       }
-
        // If we saw a source we don't recognize, which can only
        // happen if we can't use the cgo resolver, treat it as DNS.
        if unknownSource {
index 08d774bfe2c303c2d2f80e107c290194eecfdbc5..d2cdac80837fa85534ebd85c872e1103b17e2fab 100644 (file)
@@ -304,7 +304,6 @@ func TestConfHostLookupOrder(t *testing.T) {
                                {"anything.localhost.localdomain", "myhostname", hostLookupCgo},
                                {"Anything.Localhost.Localdomain", "myhostname", hostLookupCgo},
                                {"somehostname", "myhostname", hostLookupFilesDNS},
-                               {"", "myhostname", hostLookupFilesDNS}, // Issue 13623
                        },
                },
                {
@@ -392,6 +391,42 @@ func TestConfHostLookupOrder(t *testing.T) {
        }
 }
 
+func TestAddrLookupOrder(t *testing.T) {
+       // This test is written for a system with cgo available,
+       // without using the netgo tag.
+       if netGoBuildTag {
+               t.Skip("skipping test because net package built with netgo tag")
+       }
+       if !cgoAvailable {
+               t.Skip("skipping test because cgo resolver not available")
+       }
+
+       defer setSystemNSS(getSystemNSS(), 0)
+       c, err := newResolvConfTest()
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer c.teardown()
+
+       if !c.forceUpdateConf(defaultResolvConf, time.Now().Add(time.Hour)) {
+               t.Fatal("failed to change resolv config")
+       }
+
+       setSystemNSS(nssStr(t, "hosts: files myhostname dns"), time.Hour)
+       cnf := &conf{}
+       order, _ := cnf.addrLookupOrder(nil, "192.0.2.1")
+       if order != hostLookupCgo {
+               t.Errorf("addrLookupOrder returned: %v, want cgo", order)
+       }
+
+       setSystemNSS(nssStr(t, "hosts: files mdns4 dns"), time.Hour)
+       order, _ = cnf.addrLookupOrder(nil, "192.0.2.1")
+       if order != hostLookupCgo {
+               t.Errorf("addrLookupOrder returned: %v, want cgo", order)
+       }
+
+}
+
 func setSystemNSS(nss *nssConf, addDur time.Duration) {
        nssConfig.mu.Lock()
        nssConfig.nssConf = nss
index ad35551f9d5c27dfd81189d8fac784eadb2680c7..dc75e0a3b68e566ac73f1a83e8e4772911743624 100644 (file)
@@ -117,7 +117,7 @@ func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error)
 }
 
 func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) {
-       order, conf := systemConf().hostLookupOrder(r, "")
+       order, conf := systemConf().addrLookupOrder(r, addr)
        if order == hostLookupCgo {
                return cgoLookupPTR(ctx, addr)
        }