|
|
1d03cd |
From ef0f28bc8efdc5292ceb593c9c5a646f030e0994 Mon Sep 17 00:00:00 2001
|
|
|
1d03cd |
From: Phil Sutter <psutter@redhat.com>
|
|
|
1d03cd |
Date: Thu, 9 Feb 2023 15:25:37 +0100
|
|
|
1d03cd |
Subject: [PATCH] monitor: Sanitize startup race condition
|
|
|
1d03cd |
|
|
|
1d03cd |
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2130721
|
|
|
1d03cd |
Upstream Status: nftables commit 545edb7a8ef0a
|
|
|
1d03cd |
|
|
|
1d03cd |
commit 545edb7a8ef0a8acf991b1b7857fddc24d7b151a
|
|
|
1d03cd |
Author: Phil Sutter <phil@nwl.cc>
|
|
|
1d03cd |
Date: Wed Sep 28 23:26:42 2022 +0200
|
|
|
1d03cd |
|
|
|
1d03cd |
monitor: Sanitize startup race condition
|
|
|
1d03cd |
|
|
|
1d03cd |
During startup, 'nft monitor' first fetches the current ruleset and then
|
|
|
1d03cd |
keeps this cache up to date based on received events. This is racey, as
|
|
|
1d03cd |
any ruleset changes in between the initial fetch and the socket opening
|
|
|
1d03cd |
are not recognized.
|
|
|
1d03cd |
|
|
|
1d03cd |
This script demonstrates the problem:
|
|
|
1d03cd |
|
|
|
1d03cd |
| #!/bin/bash
|
|
|
1d03cd |
|
|
|
|
1d03cd |
| while true; do
|
|
|
1d03cd |
| nft flush ruleset
|
|
|
1d03cd |
| iptables-nft -A FORWARD
|
|
|
1d03cd |
| done &
|
|
|
1d03cd |
| maniploop=$!
|
|
|
1d03cd |
|
|
|
|
1d03cd |
| trap "kill $maniploop; kill \$!; wait" EXIT
|
|
|
1d03cd |
|
|
|
|
1d03cd |
| while true; do
|
|
|
1d03cd |
| nft monitor rules >/dev/null &
|
|
|
1d03cd |
| sleep 0.2
|
|
|
1d03cd |
| kill $!
|
|
|
1d03cd |
| done
|
|
|
1d03cd |
|
|
|
1d03cd |
If the table add event is missed, the rule add event callback fails to
|
|
|
1d03cd |
deserialize the rule and calls abort().
|
|
|
1d03cd |
|
|
|
1d03cd |
Avoid the inconvenient program exit by returning NULL from
|
|
|
1d03cd |
netlink_delinearize_rule() instead of aborting and make callers check
|
|
|
1d03cd |
the return value.
|
|
|
1d03cd |
|
|
|
1d03cd |
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
|
|
1d03cd |
|
|
|
1d03cd |
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
|
|
1d03cd |
---
|
|
|
1d03cd |
src/cache.c | 1 +
|
|
|
1d03cd |
src/monitor.c | 5 +++++
|
|
|
1d03cd |
src/netlink_delinearize.c | 5 ++++-
|
|
|
1d03cd |
3 files changed, 10 insertions(+), 1 deletion(-)
|
|
|
1d03cd |
|
|
|
1d03cd |
diff --git a/src/cache.c b/src/cache.c
|
|
|
1d03cd |
index fd8df88..701aec6 100644
|
|
|
1d03cd |
--- a/src/cache.c
|
|
|
1d03cd |
+++ b/src/cache.c
|
|
|
1d03cd |
@@ -490,6 +490,7 @@ static int list_rule_cb(struct nftnl_rule *nlr, void *data)
|
|
|
1d03cd |
|
|
|
1d03cd |
netlink_dump_rule(nlr, ctx);
|
|
|
1d03cd |
rule = netlink_delinearize_rule(ctx, nlr);
|
|
|
1d03cd |
+ assert(rule);
|
|
|
1d03cd |
list_add_tail(&rule->list, &ctx->list);
|
|
|
1d03cd |
|
|
|
1d03cd |
return 0;
|
|
|
1d03cd |
diff --git a/src/monitor.c b/src/monitor.c
|
|
|
1d03cd |
index 7fa92eb..a6b30a1 100644
|
|
|
1d03cd |
--- a/src/monitor.c
|
|
|
1d03cd |
+++ b/src/monitor.c
|
|
|
1d03cd |
@@ -551,6 +551,10 @@ static int netlink_events_rule_cb(const struct nlmsghdr *nlh, int type,
|
|
|
1d03cd |
|
|
|
1d03cd |
nlr = netlink_rule_alloc(nlh);
|
|
|
1d03cd |
r = netlink_delinearize_rule(monh->ctx, nlr);
|
|
|
1d03cd |
+ if (!r) {
|
|
|
1d03cd |
+ fprintf(stderr, "W: Received event for an unknown table.\n");
|
|
|
1d03cd |
+ goto out_free_nlr;
|
|
|
1d03cd |
+ }
|
|
|
1d03cd |
nlr_for_each_set(nlr, rule_map_decompose_cb, NULL,
|
|
|
1d03cd |
&monh->ctx->nft->cache);
|
|
|
1d03cd |
cmd = netlink_msg2cmd(type, nlh->nlmsg_flags);
|
|
|
1d03cd |
@@ -587,6 +591,7 @@ static int netlink_events_rule_cb(const struct nlmsghdr *nlh, int type,
|
|
|
1d03cd |
break;
|
|
|
1d03cd |
}
|
|
|
1d03cd |
rule_free(r);
|
|
|
1d03cd |
+out_free_nlr:
|
|
|
1d03cd |
nftnl_rule_free(nlr);
|
|
|
1d03cd |
return MNL_CB_OK;
|
|
|
1d03cd |
}
|
|
|
1d03cd |
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
|
|
|
1d03cd |
index c6ad84d..1d47c74 100644
|
|
|
1d03cd |
--- a/src/netlink_delinearize.c
|
|
|
1d03cd |
+++ b/src/netlink_delinearize.c
|
|
|
1d03cd |
@@ -3194,7 +3194,10 @@ struct rule *netlink_delinearize_rule(struct netlink_ctx *ctx,
|
|
|
1d03cd |
pctx->rule = rule_alloc(&netlink_location, &h);
|
|
|
1d03cd |
pctx->table = table_cache_find(&ctx->nft->cache.table_cache,
|
|
|
1d03cd |
h.table.name, h.family);
|
|
|
1d03cd |
- assert(pctx->table != NULL);
|
|
|
1d03cd |
+ if (!pctx->table) {
|
|
|
1d03cd |
+ errno = ENOENT;
|
|
|
1d03cd |
+ return NULL;
|
|
|
1d03cd |
+ }
|
|
|
1d03cd |
|
|
|
1d03cd |
pctx->rule->comment = nftnl_rule_get_comment(nlr);
|
|
|
1d03cd |
|
|
|
1d03cd |
--
|
|
|
1d03cd |
2.39.1
|
|
|
1d03cd |
|