]> git.dujemihanovic.xyz Git - linux.git/commitdiff
netfilter: nf_tables: Audit log dump reset after the fact
authorPhil Sutter <phil@nwl.cc>
Fri, 9 Aug 2024 13:07:30 +0000 (15:07 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 14 Aug 2024 21:37:35 +0000 (23:37 +0200)
In theory, dumpreset may fail and invalidate the preceeding log message.
Fix this and use the occasion to prepare for object reset locking, which
benefits from a few unrelated changes:

* Add an early call to nfnetlink_unicast if not resetting which
  effectively skips the audit logging but also unindents it.
* Extract the table's name from the netlink attribute (which is verified
  via earlier table lookup) to not rely upon validity of the looked up
  table pointer.
* Do not use local variable family, it will vanish.

Fixes: 8e6cf365e1d5 ("audit: log nftables configuration change events")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Reviewed-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/nf_tables_api.c

index 481ee78e77bcf96d2271b465b259554f83df33b0..4fa132715fcc2948f389b36d514b89115ad3f59e 100644 (file)
@@ -8055,6 +8055,7 @@ static int nf_tables_dump_obj_done(struct netlink_callback *cb)
 static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,
                            const struct nlattr * const nla[])
 {
+       const struct nftables_pernet *nft_net = nft_pernet(info->net);
        struct netlink_ext_ack *extack = info->extack;
        u8 genmask = nft_genmask_cur(info->net);
        u8 family = info->nfmsg->nfgen_family;
@@ -8064,6 +8065,7 @@ static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,
        struct sk_buff *skb2;
        bool reset = false;
        u32 objtype;
+       char *buf;
        int err;
 
        if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
@@ -8102,27 +8104,23 @@ static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,
        if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
                reset = true;
 
-       if (reset) {
-               const struct nftables_pernet *nft_net;
-               char *buf;
-
-               nft_net = nft_pernet(net);
-               buf = kasprintf(GFP_ATOMIC, "%s:%u", table->name, nft_net->base_seq);
-
-               audit_log_nfcfg(buf,
-                               family,
-                               1,
-                               AUDIT_NFT_OP_OBJ_RESET,
-                               GFP_ATOMIC);
-               kfree(buf);
-       }
-
        err = nf_tables_fill_obj_info(skb2, net, NETLINK_CB(skb).portid,
                                      info->nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0,
                                      family, table, obj, reset);
        if (err < 0)
                goto err_fill_obj_info;
 
+       if (!reset)
+               return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
+
+       buf = kasprintf(GFP_ATOMIC, "%.*s:%u",
+                       nla_len(nla[NFTA_OBJ_TABLE]),
+                       (char *)nla_data(nla[NFTA_OBJ_TABLE]),
+                       nft_net->base_seq);
+       audit_log_nfcfg(buf, info->nfmsg->nfgen_family, 1,
+                       AUDIT_NFT_OP_OBJ_RESET, GFP_ATOMIC);
+       kfree(buf);
+
        return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
 
 err_fill_obj_info: