Skip to content

Commit 92bf9d8

Browse files
committed
prevent routes/rules from leaking on various config changes
Runtime changes to `metric`, `no_defaultroute`, `disable_addr_rules`, and the `ip{4,6}table{,_local}` options can lead to various routes and rules being leaked. Instead of updating to the new value right away, mark `reload_ip` first, then do the teardown, change the value, and finally set everything up again. For the broader `reload` case, it works the same. Explicit teardown was added in order to avoid having to 'inject' the changing values into farther-away code (the async case with `mark_interface_down` is particularly gnarly). Signed-off-by: Leon M. Busch-George <leon@georgemail.eu>
1 parent fd7b03e commit 92bf9d8

1 file changed

Lines changed: 39 additions & 7 deletions

File tree

interface.c

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,14 @@ interface_change_config(struct interface *if_old, struct interface *if_new)
13391339
__var |= __changed; \
13401340
})
13411341

1342+
#define CHECK(field, __var) ({ \
1343+
__var |= (if_old->field != if_new->field); \
1344+
})
1345+
1346+
#define APPLY(field) ({ \
1347+
if_old->field = if_new->field; \
1348+
})
1349+
13421350
if_old->config = if_new->config;
13431351
if_old->tags = if_new->tags;
13441352
if (if_old->config_autostart != if_new->config_autostart) {
@@ -1383,16 +1391,17 @@ interface_change_config(struct interface *if_old, struct interface *if_new)
13831391
if_old->proto_ip.no_dns = if_new->proto_ip.no_dns;
13841392
interface_replace_dns(&if_old->config_ip, &if_new->config_ip);
13851393

1386-
UPDATE(metric, reload_ip);
1387-
UPDATE(proto_ip.no_defaultroute, reload_ip);
1388-
UPDATE(ip4table, reload_ip);
1389-
UPDATE(ip6table, reload_ip);
1390-
UPDATE(ip4table_local, reload_ip);
1391-
UPDATE(ip6table_local, reload_ip);
1392-
UPDATE(disable_addr_rules, reload_ip);
1394+
CHECK(metric, reload_ip);
1395+
CHECK(proto_ip.no_defaultroute, reload_ip);
1396+
CHECK(ip4table, reload_ip);
1397+
CHECK(ip6table, reload_ip);
1398+
CHECK(ip4table_local, reload_ip);
1399+
CHECK(ip6table_local, reload_ip);
1400+
CHECK(disable_addr_rules, reload_ip);
13931401
interface_merge_assignment_data(if_old, if_new);
13941402

13951403
#undef UPDATE
1404+
#undef CHECK
13961405

13971406
if (!reload) {
13981407
struct device *old_dev = if_old->main_dev.dev;
@@ -1405,6 +1414,18 @@ interface_change_config(struct interface *if_old, struct interface *if_new)
14051414
D(INTERFACE, "Reload interface '%s' because of config changes",
14061415
if_old->name);
14071416
interface_clear_errors(if_old);
1417+
1418+
interface_ip_set_enabled(&if_old->config_ip, false);
1419+
interface_ip_set_enabled(&if_old->proto_ip, false);
1420+
1421+
APPLY(metric);
1422+
APPLY(proto_ip.no_defaultroute);
1423+
APPLY(ip4table);
1424+
APPLY(ip6table);
1425+
APPLY(ip4table_local);
1426+
APPLY(ip6table_local);
1427+
APPLY(disable_addr_rules);
1428+
14081429
set_config_state(if_old, IFC_RELOAD);
14091430
goto out;
14101431
}
@@ -1415,10 +1436,21 @@ interface_change_config(struct interface *if_old, struct interface *if_new)
14151436

14161437
interface_ip_set_enabled(&if_old->config_ip, false);
14171438
interface_ip_set_enabled(&if_old->proto_ip, false);
1439+
1440+
APPLY(metric);
1441+
APPLY(proto_ip.no_defaultroute);
1442+
APPLY(ip4table);
1443+
APPLY(ip6table);
1444+
APPLY(ip4table_local);
1445+
APPLY(ip6table_local);
1446+
APPLY(disable_addr_rules);
1447+
14181448
interface_ip_set_enabled(&if_old->proto_ip, proto_ip_enabled);
14191449
interface_ip_set_enabled(&if_old->config_ip, config_ip_enabled);
14201450
}
14211451

1452+
#undef APPLY
1453+
14221454
if (update_prefix_delegation)
14231455
interface_update_prefix_delegation(&if_old->proto_ip);
14241456

0 commit comments

Comments
 (0)