From 28ec1869fc97743809184d6ec5fd7bcb3ef41f7a Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 21 Nov 2023 21:34:50 +0700 Subject: [PATCH] internal/router/merlin: hardening pre-run condition The postconf script added by ctrld requires all of these conditions to work correctly: - /proc, /tmp were mounted. - dnsmasq is running. Currently, ctrld is only waiting for NTP ready, which may not ensure both of those conditions are true. Explicitly checking those conditions is a safer approach. --- internal/router/merlin/merlin.go | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/internal/router/merlin/merlin.go b/internal/router/merlin/merlin.go index 84ebd1c..8b6a0fc 100644 --- a/internal/router/merlin/merlin.go +++ b/internal/router/merlin/merlin.go @@ -6,6 +6,7 @@ import ( "os" "os/exec" "strings" + "time" "unicode" "github.com/kardianos/service" @@ -44,8 +45,24 @@ func (m *Merlin) Uninstall(_ *service.Config) error { } func (m *Merlin) PreRun() error { + // Wait NTP ready. _ = m.Cleanup() - return ntp.WaitNvram() + if err := ntp.WaitNvram(); err != nil { + return err + } + // Wait until directories mounted. + for _, dir := range []string{"/tmp", "/proc"} { + waitDirExists(dir) + } + // Wait dnsmasq started. + for { + out, _ := exec.Command("pidof", "dnsmasq").CombinedOutput() + if len(bytes.TrimSpace(out)) > 0 { + break + } + time.Sleep(time.Second) + } + return nil } func (m *Merlin) Setup() error { @@ -56,9 +73,6 @@ func (m *Merlin) Setup() error { if val, _ := nvram.Run("get", nvram.CtrldSetupKey); val == "1" { return nil } - if _, err := nvram.Run("set", nvram.CtrldSetupKey+"=1"); err != nil { - return err - } buf, err := os.ReadFile(dnsmasq.MerlinPostConfPath) // Already setup. if bytes.Contains(buf, []byte(dnsmasq.MerlinPostConfMarker)) { @@ -140,3 +154,12 @@ func merlinParsePostConf(buf []byte) []byte { } return buf } + +func waitDirExists(dir string) { + for { + if _, err := os.Stat(dir); !os.IsNotExist(err) { + return + } + time.Sleep(time.Second) + } +}