The commit is pushed to "branch-rh7-3.10.0-1160.99.1.vz7.211.x-ovz" and will 
appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1160.99.1.vz7.211.2
------>
commit 0d7c51e4b52f8f8e9ff0cb45002c5f6d2f4c552a
Author: Florian Westphal <f...@strlen.de>
Date:   Wed Nov 1 18:46:54 2023 +0800

    ms/netfilter: nf_tables: fix oops during rule dump
    
    We can oops in nf_tables_fill_rule_info().
    
    Its not possible to fetch previous element in rcu-protected lists
    when deletions are not prevented somehow: list_del_rcu poisons
    the ->prev pointer value.
    
    Before rcu-conversion this was safe as dump operations did hold
    nfnetlink mutex.
    
    Pass previous rule as argument, obtained by keeping a pointer to
    the previous rule during traversal.
    
    mFixes: d9adf22a291883 ("netfilter: nf_tables: use call_rcu in netlink 
dumps")
    Signed-off-by: Florian Westphal <f...@strlen.de>
    Signed-off-by: Pablo Neira Ayuso <pa...@netfilter.org>
    
    (cherry picked from ms commit 2c82c7e724ff51cab78e1afd5c2aaa31994fe41e)
    Changes:
     - move hunks from __nf_tables_dump_rules to nf_tables_dump_rules
    
    https://virtuozzo.atlassian.net/browse/PSBM-150147
    Signed-off-by: Pavel Tikhomirov <ptikhomi...@virtuozzo.com>
    
    =================
    Patchset description:
    netfilter: nf_tables: switch read path to rcu
    
    We have a customer claiming that iptables-nft takes too long to list
    rules from container on big systems. So we remove global nfnl_lock from
    read code paths and replace it with rcu to improve perfomane for that
    case.
    
    https://virtuozzo.atlassian.net/browse/PSBM-150147
    Signed-off-by: Pavel Tikhomirov <ptikhomi...@virtuozzo.com>
    
    Florian Westphal (2):
      netfilter: nf_tables: use call_rcu in netlink dumps
      netfilter: nf_tables: fix oops during rule dump
    
    Pavel Tikhomirov (1):
      netfilter: nf_tables: use list_entry_rcu in nft_do_chain
---
 net/netfilter/nf_tables_api.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 2a3680da9cd2..21b7b0f81f8f 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1890,13 +1890,13 @@ static int nf_tables_fill_rule_info(struct sk_buff 
*skb, struct net *net,
                                    u32 flags, int family,
                                    const struct nft_table *table,
                                    const struct nft_chain *chain,
-                                   const struct nft_rule *rule)
+                                   const struct nft_rule *rule,
+                                   const struct nft_rule *prule)
 {
        struct nlmsghdr *nlh;
        struct nfgenmsg *nfmsg;
        const struct nft_expr *expr, *next;
        struct nlattr *list;
-       const struct nft_rule *prule;
        int type = event | NFNL_SUBSYS_NFTABLES << 8;
 
        nlh = nlmsg_put(skb, portid, seq, type, sizeof(struct nfgenmsg),
@@ -1917,8 +1917,7 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, 
struct net *net,
                         NFTA_RULE_PAD))
                goto nla_put_failure;
 
-       if ((event != NFT_MSG_DELRULE) && (rule->list.prev != &chain->rules)) {
-               prule = list_entry(rule->list.prev, struct nft_rule, list);
+       if (event != NFT_MSG_DELRULE && prule) {
                if (nla_put_be64(skb, NFTA_RULE_POSITION,
                                 cpu_to_be64(prule->handle),
                                 NFTA_RULE_PAD))
@@ -1967,7 +1966,7 @@ static int nf_tables_rule_notify(const struct nft_ctx 
*ctx,
 
        err = nf_tables_fill_rule_info(skb, ctx->net, ctx->portid, ctx->seq,
                                       event, 0, ctx->afi->family, ctx->table,
-                                      ctx->chain, rule);
+                                      ctx->chain, rule, NULL);
        if (err < 0) {
                kfree_skb(skb);
                goto err;
@@ -1996,7 +1995,7 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
        const struct nft_af_info *afi;
        const struct nft_table *table;
        const struct nft_chain *chain;
-       const struct nft_rule *rule;
+       const struct nft_rule *rule, *prule = NULL;
        unsigned int idx = 0, s_idx = cb->args[0];
        struct net *net = sock_net(skb->sk);
        int family = nfmsg->nfgen_family;
@@ -2020,7 +2019,7 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
 
                                list_for_each_entry_rcu(rule, &chain->rules, 
list) {
                                        if (!nft_is_active(net, rule))
-                                               goto cont;
+                                               goto cont_skip;
                                        if (idx < s_idx)
                                                goto cont;
                                        if (idx > s_idx)
@@ -2030,11 +2029,13 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
                                                                      
cb->nlh->nlmsg_seq,
                                                                      
NFT_MSG_NEWRULE,
                                                                      
NLM_F_MULTI | NLM_F_APPEND,
-                                                                     
afi->family, table, chain, rule) < 0)
+                                                                     
afi->family, table, chain, rule, prule) < 0)
                                                goto done;
 
                                        nl_dump_check_consistent(cb, 
nlmsg_hdr(skb));
 cont:
+                                       prule = rule;
+cont_skip:
                                        idx++;
                                }
                        }
@@ -2134,7 +2135,7 @@ static int nf_tables_getrule(struct sock *nlsk, struct 
sk_buff *skb,
 
        err = nf_tables_fill_rule_info(skb2, net, NETLINK_CB(skb).portid,
                                       nlh->nlmsg_seq, NFT_MSG_NEWRULE, 0,
-                                      family, table, chain, rule);
+                                      family, table, chain, rule, NULL);
        if (err < 0)
                goto err;
 
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to