From a0ba4d793dce18103cc8e0d661f4c9a8f248575f Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Fri, 26 Jan 2024 12:46:07 -0500 Subject: [PATCH] MT#55283 don't create chains that already exist Telling netlink to create a chain that already exists should technically be a no-op, BUT it still sets the policy to whatever was given as a side effect. Make sure we don't change the policy by explicitly checking for the chain's existence. closes #1785 Change-Id: I526a4e2a0f9d1dcc6e0e00a6e273e4df55863d6c --- daemon/nftables.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/daemon/nftables.c b/daemon/nftables.c index 3094a41e6..ea4e061ce 100644 --- a/daemon/nftables.c +++ b/daemon/nftables.c @@ -303,9 +303,52 @@ static const char *local_input_chain(struct nftnl_chain *c) { } +static int nftables_do_chain(const struct nlmsghdr *nlh, void *data) { + bool *exists = data; + + g_autoptr(_nftnl_chain) c = nftnl_chain_alloc(); + if (!c) + return MNL_CB_ERROR; + + if (nftnl_chain_nlmsg_parse(nlh, c) < 0) + return MNL_CB_OK; + + *exists = true; + + return MNL_CB_OK; +} + + +static const char *chain_exists(struct mnl_socket *nl, int family, const char *chain, uint32_t *seq) { + g_autoptr(_nftnl_chain) c = nftnl_chain_alloc(); + + nftnl_chain_set_str(c, NFTNL_CHAIN_TABLE, "filter"); + nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, chain); + + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, family, + NLM_F_ACK, *seq); + + nftnl_chain_nlmsg_build_payload(nlh, c); + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) + return "failed to write to netlink socket for chain exists"; + + bool exists = false; + const char *err = read_response("get chain", nl, *seq, nftables_do_chain, &exists); + if (err) + return err; + + return exists ? NULL : "doesn't exist"; +} + + static const char *add_chain(struct mnl_socket *nl, int family, const char *chain, uint32_t *seq, const char *(*callback)(struct nftnl_chain *)) { + if (chain_exists(nl, family, chain, seq) == NULL) + return NULL; + g_autoptr(_nftnl_chain) c = nftnl_chain_alloc(); if (!c) return "failed to allocate chain for adding";