diff --git a/daemon/firewall/common/common.go b/daemon/firewall/common/common.go index cdd284f5f9..86156d669f 100644 --- a/daemon/firewall/common/common.go +++ b/daemon/firewall/common/common.go @@ -23,8 +23,8 @@ type ( callbackBool func() bool stopChecker struct { - ch chan bool - sync.RWMutex + ch chan bool + rwm sync.RWMutex } // Common holds common fields and functionality of both firewalls, @@ -36,19 +36,19 @@ type ( Running bool Intercepting bool FwEnabled bool - sync.RWMutex + rwm sync.RWMutex } ) func (s *stopChecker) exit() <-chan bool { - s.RLock() - defer s.RUnlock() + s.rwm.RLock() + defer s.rwm.RUnlock() return s.ch } func (s *stopChecker) stop() { - s.Lock() - defer s.Unlock() + s.rwm.Lock() + defer s.rwm.Unlock() if s.ch != nil { s.ch <- true @@ -60,8 +60,8 @@ func (s *stopChecker) stop() { // SetQueueNum sets the queue number used by the firewall. // It's the queue where all intercepted connections will be sent. func (c *Common) SetQueueNum(qNum *int) { - c.Lock() - defer c.Unlock() + c.rwm.Lock() + defer c.rwm.Unlock() if qNum != nil { c.QueueNum = uint16(*qNum) @@ -71,24 +71,24 @@ func (c *Common) SetQueueNum(qNum *int) { // IsRunning returns if the firewall is running or not. func (c *Common) IsRunning() bool { - c.RLock() - defer c.RUnlock() + c.rwm.RLock() + defer c.rwm.RUnlock() return c != nil && c.Running } // IsFirewallEnabled returns if the firewall is running or not. func (c *Common) IsFirewallEnabled() bool { - c.RLock() - defer c.RUnlock() + c.rwm.RLock() + defer c.rwm.RUnlock() return c != nil && c.FwEnabled } // IsIntercepting returns if the firewall is running or not. func (c *Common) IsIntercepting() bool { - c.RLock() - defer c.RUnlock() + c.rwm.RLock() + defer c.rwm.RUnlock() return c != nil && c.Intercepting } @@ -97,8 +97,8 @@ func (c *Common) IsIntercepting() bool { // We expect to have 2 rules loaded: one to intercept DNS responses and another one // to intercept network traffic. func (c *Common) NewRulesChecker(areRulesLoaded callbackBool, reloadRules callback) { - c.Lock() - defer c.Unlock() + c.rwm.Lock() + defer c.rwm.Unlock() if c.stopCheckerChan != nil { c.stopCheckerChan.stop() c.stopCheckerChan = nil @@ -130,8 +130,8 @@ Exit: // StopCheckingRules stops checking if firewall rules are loaded. func (c *Common) StopCheckingRules() { - c.RLock() - defer c.RUnlock() + c.rwm.RLock() + defer c.rwm.RUnlock() if c.RulesChecker != nil { c.RulesChecker.Stop() diff --git a/daemon/firewall/config/config.go b/daemon/firewall/config/config.go index 92dfe283f3..088f0cc348 100644 --- a/daemon/firewall/config/config.go +++ b/daemon/firewall/config/config.go @@ -5,7 +5,6 @@ // The firewall rules defined by the user are reloaded in these cases: // - When the file system-fw.json changes. // - When the firewall rules are not present when listing them. -// package config import ( @@ -20,30 +19,33 @@ import ( // ExprValues holds the statements' options: // "Name": "ct", // "Values": [ -// { -// "Key": "state", -// "Value": "established" -// }, -// { -// "Key": "state", -// "Value": "related" -// }] +// +// { +// "Key": "state", +// "Value": "established" +// }, +// +// { +// "Key": "state", +// "Value": "related" +// }] type ExprValues struct { Key string Value string } // ExprStatement holds the definition of matches to use against connections. -//{ -// "Op": "!=", -// "Name": "tcp", -// "Values": [ -// { -// "Key": "dport", -// "Value": "443" -// } -// ] -//} +// +// { +// "Op": "!=", +// "Name": "tcp", +// "Values": [ +// { +// "Key": "dport", +// "Value": "443" +// } +// ] +// } type ExprStatement struct { Op string // ==, !=, ... Only one per expression set. Name string // tcp, udp, ct, daddr, log, ... @@ -60,7 +62,7 @@ type FwRule struct { // we need to keep old fields in the struct. Otherwise when receiving a conf from the GUI, the legacy rules would be deleted. Chain string // TODO: deprecated, remove Table string // TODO: deprecated, remove - Parameters string // TODO: deprecated: remove + Parameters string // TODO: deprecated, remove UUID string Description string @@ -70,8 +72,6 @@ type FwRule struct { Position uint64 `json:",string"` Enabled bool - - *sync.RWMutex } // FwChain holds the information that defines a firewall chain. @@ -95,10 +95,6 @@ func (fc *FwChain) IsInvalid() bool { return fc.Name == "" || fc.Family == "" || fc.Table == "" } -type rulesList struct { - Rule *FwRule -} - type chainsList struct { Chains []*FwChain Rule *FwRule // TODO: deprecated, remove @@ -106,7 +102,7 @@ type chainsList struct { // SystemConfig holds the list of rules to be added to the system type SystemConfig struct { - sync.RWMutex + rwm sync.RWMutex SystemRules []*chainsList Version uint32 Enabled bool @@ -115,7 +111,7 @@ type SystemConfig struct { // Config holds the functionality to re/load the firewall configuration from disk. // This is the configuration to manage the system firewall (iptables, nftables). type Config struct { - sync.Mutex + mu sync.Mutex file string watcher *fsnotify.Watcher monitorExitChan chan bool @@ -129,6 +125,20 @@ type Config struct { // preload will be called after daemon startup, whilst reload when a modification is performed. } +// GetSystemRules and SetSystemRules are used to internally lock/unlock the SystemConfig's mutex +func (sc *SystemConfig) GetSystemRules() []*chainsList { + sc.rwm.RLock() + defer sc.rwm.RUnlock() + return sc.SystemRules +} + +// GetSystemRules and SetSystemRules are used to internally lock/unlock the SystemConfig's mutex +func (sc *SystemConfig) SetSystemRules(rules []*chainsList) { + sc.rwm.Lock() + defer sc.rwm.Unlock() + sc.SystemRules = rules +} + // NewSystemFwConfig initializes config fields func (c *Config) NewSystemFwConfig(preLoadCb, reLoadCb func()) (*Config, error) { var err error @@ -138,8 +148,8 @@ func (c *Config) NewSystemFwConfig(preLoadCb, reLoadCb func()) (*Config, error) return nil, err } - c.Lock() - defer c.Unlock() + c.mu.Lock() + defer c.mu.Unlock() c.file = "/etc/opensnitchd/system-fw.json" c.monitorExitChan = make(chan bool, 1) @@ -151,8 +161,8 @@ func (c *Config) NewSystemFwConfig(preLoadCb, reLoadCb func()) (*Config, error) // LoadDiskConfiguration reads and loads the firewall configuration from disk func (c *Config) LoadDiskConfiguration(reload bool) { - c.Lock() - defer c.Unlock() + c.mu.Lock() + defer c.mu.Unlock() raw, err := ioutil.ReadFile(c.file) if err != nil { @@ -180,8 +190,8 @@ func (c *Config) LoadDiskConfiguration(reload bool) { // loadConfigutation reads the system firewall rules from disk. // Then the rules are added based on the configuration defined. func (c *Config) loadConfiguration(rawConfig []byte) { - c.SysConfig.Lock() - defer c.SysConfig.Unlock() + c.SysConfig.rwm.Lock() + defer c.SysConfig.rwm.Unlock() // delete old system rules, that may be different from the new ones c.preloadCallback() @@ -213,8 +223,8 @@ func (c *Config) SaveConfiguration(rawConfig string) error { // StopConfigWatcher stops the configuration watcher and stops the subroutine. func (c *Config) StopConfigWatcher() { - c.Lock() - defer c.Unlock() + c.mu.Lock() + defer c.mu.Unlock() if c.monitorExitChan != nil { c.monitorExitChan <- true @@ -240,7 +250,7 @@ func (c *Config) monitorConfigWorker() { } Exit: log.Debug("stop monitoring firewall config file") - c.Lock() + c.mu.Lock() c.monitorExitChan = nil - c.Unlock() + c.mu.Unlock() } diff --git a/daemon/firewall/iptables/iptables.go b/daemon/firewall/iptables/iptables.go index 3a7cd067dc..df48158bac 100644 --- a/daemon/firewall/iptables/iptables.go +++ b/daemon/firewall/iptables/iptables.go @@ -49,7 +49,7 @@ type SystemRule struct { // SystemChains keeps track of the fw rules that have been added to the system. type SystemChains struct { Rules map[string]*SystemRule - sync.RWMutex + rwm sync.RWMutex } // Iptables struct holds the fields of the iptables fw @@ -64,8 +64,7 @@ type Iptables struct { regexSystemRulesQuery *regexp.Regexp chains SystemChains - - sync.Mutex + mu sync.Mutex } // Fw initializes a new Iptables object diff --git a/daemon/firewall/iptables/monitor.go b/daemon/firewall/iptables/monitor.go index fbcec2f577..bbec98e834 100644 --- a/daemon/firewall/iptables/monitor.go +++ b/daemon/firewall/iptables/monitor.go @@ -23,7 +23,7 @@ func (ipt *Iptables) AreRulesLoaded() bool { } systemRulesLoaded := true - ipt.chains.RLock() + ipt.chains.rwm.RLock() if len(ipt.chains.Rules) > 0 { for _, rule := range ipt.chains.Rules { if chainOut4, err4 := core.Exec("iptables", []string{"-n", "-L", rule.Chain, "-t", rule.Table}); err4 == nil { @@ -42,7 +42,7 @@ func (ipt *Iptables) AreRulesLoaded() bool { } } } - ipt.chains.RUnlock() + ipt.chains.rwm.RUnlock() result := ipt.regexRulesQuery.FindString(outMangle) != "" && systemRulesLoaded diff --git a/daemon/firewall/iptables/rules.go b/daemon/firewall/iptables/rules.go index 6eed8422ca..633951db05 100644 --- a/daemon/firewall/iptables/rules.go +++ b/daemon/firewall/iptables/rules.go @@ -16,8 +16,8 @@ func (ipt *Iptables) RunRule(action Action, enable bool, logError bool, rule []s rule = append([]string{string(action)}, rule...) - ipt.Lock() - defer ipt.Unlock() + ipt.mu.Lock() + defer ipt.mu.Unlock() if _, err4 = core.Exec(ipt.bin, rule); err4 != nil { if logError { diff --git a/daemon/firewall/iptables/system.go b/daemon/firewall/iptables/system.go index 9626787ab4..1cfbd7b7b1 100644 --- a/daemon/firewall/iptables/system.go +++ b/daemon/firewall/iptables/system.go @@ -9,8 +9,8 @@ import ( // CreateSystemRule creates the custom firewall chains and adds them to the system. func (ipt *Iptables) CreateSystemRule(rule *config.FwRule, table, chain, hook string, logErrors bool) bool { - ipt.chains.Lock() - defer ipt.chains.Unlock() + ipt.chains.rwm.Lock() + defer ipt.chains.rwm.Unlock() if rule == nil { return false } @@ -67,8 +67,8 @@ func (ipt *Iptables) AddSystemRules(reload, backupExistingChains bool) { // If force is false and the rule has not been previously added, // it won't try to delete the rules. Otherwise it'll try to delete them. func (ipt *Iptables) DeleteSystemRules(force, backupExistingChains, logErrors bool) { - ipt.chains.Lock() - defer ipt.chains.Unlock() + ipt.chains.rwm.Lock() + defer ipt.chains.rwm.Unlock() for _, fwCfg := range ipt.SysConfig.SystemRules { if fwCfg.Rule == nil { @@ -124,8 +124,8 @@ func (ipt *Iptables) AddSystemRule(action Action, rule *config.FwRule, table, ch if rule == nil { return nil, nil } - ipt.RLock() - defer ipt.RUnlock() + ipt.chains.rwm.RLock() + defer ipt.chains.rwm.RUnlock() chainName := SystemRulePrefix + "-" + chain if table == "" { diff --git a/daemon/firewall/nftables/monitor.go b/daemon/firewall/nftables/monitor.go index 883ea339db..df14615812 100644 --- a/daemon/firewall/nftables/monitor.go +++ b/daemon/firewall/nftables/monitor.go @@ -10,8 +10,8 @@ import ( // AreRulesLoaded checks if the firewall rules for intercept traffic are loaded. func (n *Nft) AreRulesLoaded() bool { - n.Lock() - defer n.Unlock() + n.mu.Lock() + defer n.mu.Unlock() nRules := 0 chains, err := n.conn.ListChains() diff --git a/daemon/firewall/nftables/nftables.go b/daemon/firewall/nftables/nftables.go index 5d05ea87a7..00f55ec064 100644 --- a/daemon/firewall/nftables/nftables.go +++ b/daemon/firewall/nftables/nftables.go @@ -41,7 +41,7 @@ var ( // Nft holds the fields of our nftables firewall type Nft struct { - sync.Mutex + mu sync.Mutex config.Config common.Common diff --git a/daemon/firewall/nftables/system.go b/daemon/firewall/nftables/system.go index 128030d06e..09d1192ca8 100644 --- a/daemon/firewall/nftables/system.go +++ b/daemon/firewall/nftables/system.go @@ -65,9 +65,8 @@ func (n *Nft) CreateSystemRule(chain *config.FwChain, logErrors bool) bool { } // AddSystemRules creates the system firewall from configuration. -func (n *Nft) AddSystemRules(reload, backupExistingChains bool) { - n.SysConfig.RLock() - defer n.SysConfig.RUnlock() +func (n *Nft) AddSystemRules(reload, backupExistingChains bool) { + n.SysConfig.GetSystemRules() if n.SysConfig.Enabled == false { log.Important("[nftables] AddSystemRules() fw disabled") @@ -100,8 +99,8 @@ func (n *Nft) AddSystemRules(reload, backupExistingChains bool) { // If force is false and the rule has not been previously added, // it won't try to delete the tables and chains. Otherwise it'll try to delete them. func (n *Nft) DeleteSystemRules(force, restoreExistingChains, logErrors bool) { - n.Lock() - defer n.Unlock() + n.mu.Lock() + defer n.mu.Unlock() if err := n.delRulesByKey(systemRuleKey); err != nil { log.Warning("error deleting interception rules: %s", err) @@ -117,8 +116,8 @@ func (n *Nft) DeleteSystemRules(force, restoreExistingChains, logErrors bool) { // AddSystemRule inserts a new rule. func (n *Nft) AddSystemRule(rule *config.FwRule, chain *config.FwChain) (err4, err6 error) { - n.Lock() - defer n.Unlock() + n.mu.Lock() + defer n.mu.Unlock() exprList := []expr.Any{} for _, expression := range rule.Expressions {