]> git.dujemihanovic.xyz Git - linux.git/commitdiff
netfilter: nf_tables: Introduce nf_tables_getobj_single
authorPhil Sutter <phil@nwl.cc>
Fri, 9 Aug 2024 13:07:31 +0000 (15:07 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 14 Aug 2024 21:37:44 +0000 (23:37 +0200)
Outsource the reply skb preparation for non-dump getrule requests into a
distinct function. Prep work for object reset locking.

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 4fa132715fcc2948f389b36d514b89115ad3f59e..c12c9cae784d7fc6b20b8408e44ccad98a1716e7 100644 (file)
@@ -8052,10 +8052,10 @@ static int nf_tables_dump_obj_done(struct netlink_callback *cb)
 }
 
 /* called with rcu_read_lock held */
-static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,
-                           const struct nlattr * const nla[])
+static struct sk_buff *
+nf_tables_getobj_single(u32 portid, const struct nfnl_info *info,
+                       const struct nlattr * const nla[], bool reset)
 {
-       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;
@@ -8063,52 +8063,69 @@ static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,
        struct net *net = info->net;
        struct nft_object *obj;
        struct sk_buff *skb2;
-       bool reset = false;
        u32 objtype;
-       char *buf;
        int err;
 
-       if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
-               struct netlink_dump_control c = {
-                       .start = nf_tables_dump_obj_start,
-                       .dump = nf_tables_dump_obj,
-                       .done = nf_tables_dump_obj_done,
-                       .module = THIS_MODULE,
-                       .data = (void *)nla,
-               };
-
-               return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
-       }
-
        if (!nla[NFTA_OBJ_NAME] ||
            !nla[NFTA_OBJ_TYPE])
-               return -EINVAL;
+               return ERR_PTR(-EINVAL);
 
        table = nft_table_lookup(net, nla[NFTA_OBJ_TABLE], family, genmask, 0);
        if (IS_ERR(table)) {
                NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_TABLE]);
-               return PTR_ERR(table);
+               return ERR_CAST(table);
        }
 
        objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
        obj = nft_obj_lookup(net, table, nla[NFTA_OBJ_NAME], objtype, genmask);
        if (IS_ERR(obj)) {
                NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_NAME]);
-               return PTR_ERR(obj);
+               return ERR_CAST(obj);
        }
 
        skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
        if (!skb2)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
+
+       err = nf_tables_fill_obj_info(skb2, net, portid,
+                                     info->nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0,
+                                     family, table, obj, reset);
+       if (err < 0) {
+               kfree_skb(skb2);
+               return ERR_PTR(err);
+       }
+
+       return skb2;
+}
+
+static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,
+                           const struct nlattr * const nla[])
+{
+       struct nftables_pernet *nft_net = nft_pernet(info->net);
+       u32 portid = NETLINK_CB(skb).portid;
+       struct net *net = info->net;
+       struct sk_buff *skb2;
+       bool reset = false;
+       char *buf;
+
+       if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
+               struct netlink_dump_control c = {
+                       .start = nf_tables_dump_obj_start,
+                       .dump = nf_tables_dump_obj,
+                       .done = nf_tables_dump_obj_done,
+                       .module = THIS_MODULE,
+                       .data = (void *)nla,
+               };
+
+               return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
+       }
 
        if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
                reset = true;
 
-       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;
+       skb2 = nf_tables_getobj_single(portid, info, nla, reset);
+       if (IS_ERR(skb2))
+               return PTR_ERR(skb2);
 
        if (!reset)
                return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
@@ -8121,11 +8138,7 @@ static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,
                        AUDIT_NFT_OP_OBJ_RESET, GFP_ATOMIC);
        kfree(buf);
 
-       return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
-
-err_fill_obj_info:
-       kfree_skb(skb2);
-       return err;
+       return nfnetlink_unicast(skb2, net, portid);
 }
 
 static void nft_obj_destroy(const struct nft_ctx *ctx, struct nft_object *obj)