Commit 328e19f0 authored by Jussi Laakkonen's avatar Jussi Laakkonen

[connman] Implement firewall failsafe mechanism. Contributes to JB#43998

This commit adds a failsafe mechanism to set policies of all chains to
ACCEPT in case the setup of dynamic rules fails due to iptables error.
It will cleanup and initialize iptables.c before setting the policies.

Also added a pre-cleanup for firewall. It sets the policies to defaults
before the iptables content is saved. This would prevent network
blocking in case of downgrading to version where the rules are not set.
The saved filter.v4 table then has not got DROP as default INPUT chain
policy.
parent 2b89fd8c
......@@ -1076,6 +1076,7 @@ bool __connman_firewall_is_up(void);
int __connman_firewall_init(void);
void __connman_firewall_cleanup(void);
void __connman_firewall_pre_cleanup(void);
typedef int (* connman_nfacct_flush_cb_t) (unsigned int error, void *user_data);
......
......@@ -2490,30 +2490,6 @@ static void cleanup_general_firewall()
__connman_firewall_destroy(general_firewall->ctx);
general_firewall->ctx = NULL;
err = restore_policies(AF_INET, general_firewall->policies,
general_firewall->restore_policies);
if (err)
DBG("failed to restore IPv4 iptables policies, err %d", err);
err = restore_policies(AF_INET6, general_firewall->policiesv6,
general_firewall->restore_policiesv6);
if (err)
DBG("failed to restore IPv6 iptables policies, err %d", err);
g_free(general_firewall->policies);
general_firewall->policies = NULL;
g_free(general_firewall->restore_policies);
general_firewall->restore_policies = NULL;
g_free(general_firewall->policiesv6);
general_firewall->policiesv6 = NULL;
g_free(general_firewall->restore_policiesv6);
general_firewall->restore_policiesv6 = NULL;
g_free(general_firewall);
general_firewall = NULL;
}
......@@ -2558,6 +2534,38 @@ static void cleanup_dynamic_firewall_rules()
dynamic_rules = NULL;
}
static void firewall_failsafe(const char *chain_name, void *user_data)
{
int err;
int type;
const char *data = user_data;
if (!data)
return;
if (!g_strcmp0(data, "AF_INET"))
type = AF_INET;
else if (!g_strcmp0(data, "AF_INET6"))
type = AF_INET6;
else
return;
err = __connman_iptables_change_policy(type, "filter", chain_name,
"ACCEPT");
if (err) {
DBG("cannot set table filter chain %s policy ACCEPT, error %d",
chain_name, err);
return;
}
err = __connman_iptables_commit(type, "filter");
if (err)
DBG("cannot commit table filter chain %s policy, error %d",
chain_name, err);
}
static struct connman_notifier firewall_notifier = {
.name = "firewall",
.service_state_changed = service_state_changed,
......@@ -2582,11 +2590,52 @@ int __connman_firewall_init(void)
DBG("cannot register notifier, dynamic rules disabled");
cleanup_dynamic_firewall_rules();
}
} else {
DBG("dynamic rules disabled, policy ACCEPT set for all chains");
connman_error("firewall initialization error, reset iptables");
__connman_iptables_cleanup();
__connman_iptables_init();
__connman_iptables_iterate_chains(AF_INET, "filter",
firewall_failsafe, "AF_INET");
__connman_iptables_iterate_chains(AF_INET6, "filter",
firewall_failsafe, "AF_INET6");
}
return 0;
}
void __connman_firewall_pre_cleanup(void)
{
int err;
if (!general_firewall)
return;
err = restore_policies(AF_INET, general_firewall->policies,
general_firewall->restore_policies);
if (err)
DBG("failed to restore IPv4 iptables policies, err %d", err);
err = restore_policies(AF_INET6, general_firewall->policiesv6,
general_firewall->restore_policiesv6);
if (err)
DBG("failed to restore IPv6 iptables policies, err %d", err);
g_free(general_firewall->policies);
general_firewall->policies = NULL;
g_free(general_firewall->restore_policies);
general_firewall->restore_policies = NULL;
g_free(general_firewall->policiesv6);
general_firewall->policiesv6 = NULL;
g_free(general_firewall->restore_policiesv6);
general_firewall->restore_policiesv6 = NULL;
}
void __connman_firewall_cleanup(void)
{
DBG("");
......
......@@ -927,6 +927,7 @@ int main(int argc, char *argv[])
__connman_rtnl_cleanup();
__connman_resolver_cleanup();
__connman_firewall_pre_cleanup();
__connman_iptables_save_all();
__connman_clock_cleanup();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment