]> Cypherpunks repositories - gostls13.git/commitdiff
net: fix race in (*resolverConfig).tryUpdate
authorMatthew Dempsky <mdempsky@google.com>
Fri, 22 Jan 2016 21:31:57 +0000 (13:31 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Sat, 20 Feb 2016 10:03:47 +0000 (10:03 +0000)
Fixes #14072.

Change-Id: Ie31caa06690ac621906fc5acd34da2efa4e2049f
Reviewed-on: https://go-review.googlesource.com/18860
Reviewed-by: Mikio Hara <mikioh.mikioh@gmail.com>
Run-TryBot: Mikio Hara <mikioh.mikioh@gmail.com>

src/net/dnsclient_unix.go
src/net/dnsconfig_unix.go
src/net/dnsconfig_unix_test.go

index 17188f0024c0c6a1e2244426ea36acba9387a25b..736e57322cc7c7571e6f407f380bb80cea07c973 100644 (file)
@@ -229,7 +229,6 @@ type resolverConfig struct {
        // time to recheck resolv.conf.
        ch          chan struct{} // guards lastChecked and modTime
        lastChecked time.Time     // last time resolv.conf was checked
-       modTime     time.Time     // time of resolv.conf modification
 
        mu        sync.RWMutex // protects dnsConfig
        dnsConfig *dnsConfig   // parsed resolv.conf structure used in lookups
@@ -239,16 +238,12 @@ var resolvConf resolverConfig
 
 // init initializes conf and is only called via conf.initOnce.
 func (conf *resolverConfig) init() {
-       // Set dnsConfig, modTime, and lastChecked so we don't parse
+       // Set dnsConfig and lastChecked so we don't parse
        // resolv.conf twice the first time.
        conf.dnsConfig = systemConf().resolv
        if conf.dnsConfig == nil {
                conf.dnsConfig = dnsReadConfig("/etc/resolv.conf")
        }
-
-       if fi, err := os.Stat("/etc/resolv.conf"); err == nil {
-               conf.modTime = fi.ModTime()
-       }
        conf.lastChecked = time.Now()
 
        // Prepare ch so that only one update of resolverConfig may
@@ -274,17 +269,12 @@ func (conf *resolverConfig) tryUpdate(name string) {
        }
        conf.lastChecked = now
 
+       var mtime time.Time
        if fi, err := os.Stat(name); err == nil {
-               if fi.ModTime().Equal(conf.modTime) {
-                       return
-               }
-               conf.modTime = fi.ModTime()
-       } else {
-               // If modTime wasn't set prior, assume nothing has changed.
-               if conf.modTime.IsZero() {
-                       return
-               }
-               conf.modTime = time.Time{}
+               mtime = fi.ModTime()
+       }
+       if mtime.Equal(conf.dnsConfig.mtime) {
+               return
        }
 
        dnsConf := dnsReadConfig(name)
index 6073fdb6d83943d13f5af03de97ed8bac4dba386..0515ca90de1d3fe5edad4ac01dcd6a9ab19dd3cf 100644 (file)
@@ -8,18 +8,21 @@
 
 package net
 
+import "time"
+
 var defaultNS = []string{"127.0.0.1", "::1"}
 
 type dnsConfig struct {
-       servers    []string // servers to use
-       search     []string // suffixes to append to local name
-       ndots      int      // number of dots in name to trigger absolute lookup
-       timeout    int      // seconds before giving up on packet
-       attempts   int      // lost packets before giving up on server
-       rotate     bool     // round robin among servers
-       unknownOpt bool     // anything unknown was encountered
-       lookup     []string // OpenBSD top-level database "lookup" order
-       err        error    // any error that occurs during open of resolv.conf
+       servers    []string  // servers to use
+       search     []string  // suffixes to append to local name
+       ndots      int       // number of dots in name to trigger absolute lookup
+       timeout    int       // seconds before giving up on packet
+       attempts   int       // lost packets before giving up on server
+       rotate     bool      // round robin among servers
+       unknownOpt bool      // anything unknown was encountered
+       lookup     []string  // OpenBSD top-level database "lookup" order
+       err        error     // any error that occurs during open of resolv.conf
+       mtime      time.Time // time of resolv.conf modification
 }
 
 // See resolv.conf(5) on a Linux machine.
@@ -38,6 +41,13 @@ func dnsReadConfig(filename string) *dnsConfig {
                return conf
        }
        defer file.close()
+       if fi, err := file.file.Stat(); err == nil {
+               conf.mtime = fi.ModTime()
+       } else {
+               conf.servers = defaultNS
+               conf.err = err
+               return conf
+       }
        for line, ok := file.readLine(); ok; line, ok = file.readLine() {
                if len(line) > 0 && (line[0] == ';' || line[0] == '#') {
                        // comment.
index c8eed618904c98028debdd9feb7401b24f2244be..849c0da93bafb84d89fd3db3b060907a88242e01 100644 (file)
@@ -10,6 +10,7 @@ import (
        "os"
        "reflect"
        "testing"
+       "time"
 )
 
 var dnsReadConfigTests = []struct {
@@ -76,6 +77,7 @@ func TestDNSReadConfig(t *testing.T) {
                if conf.err != nil {
                        t.Fatal(conf.err)
                }
+               conf.mtime = time.Time{}
                if !reflect.DeepEqual(conf, tt.want) {
                        t.Errorf("%s:\ngot: %+v\nwant: %+v", tt.name, conf, tt.want)
                }