From: Feng <[email protected]>

The rcu lock protect is added 3 years ago with the commit
e688a7f8c6cb7a18aae7e55ccdd175f0ad9e69c0. But I find the dump
operation is protected by the nfnl_lock in the current codes. The
dump is a synchronization opertion in the netlink callback function
which is protected by the nfnl_lock.

BTW, I made some tests for this issue. I used the lockdep_nfnl_is_held
to check if the dump functions hold the lock at the entry and exit.
It shows all dump functions holds the nfnl_lock with subsystem id
NFNL_SUBSYS_NFTABLES.

Signed-off-by: Feng <[email protected]>
---
 net/netfilter/nf_tables_api.c | 42 +++++++++++++++---------------------------
 1 file changed, 15 insertions(+), 27 deletions(-)

diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index a019a87..23a3be5c 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -498,14 +498,13 @@ static int nf_tables_dump_tables(struct sk_buff *skb,
        struct net *net = sock_net(skb->sk);
        int family = nfmsg->nfgen_family;
 
-       rcu_read_lock();
        cb->seq = net->nft.base_seq;
 
-       list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
+       list_for_each_entry(afi, &net->nft.af_info, list) {
                if (family != NFPROTO_UNSPEC && family != afi->family)
                        continue;
 
-               list_for_each_entry_rcu(table, &afi->tables, list) {
+               list_for_each_entry(table, &afi->tables, list) {
                        if (idx < s_idx)
                                goto cont;
                        if (idx > s_idx)
@@ -527,7 +526,6 @@ static int nf_tables_dump_tables(struct sk_buff *skb,
                }
        }
 done:
-       rcu_read_unlock();
        cb->args[0] = idx;
        return skb->len;
 }
@@ -1089,15 +1087,14 @@ static int nf_tables_dump_chains(struct sk_buff *skb,
        struct net *net = sock_net(skb->sk);
        int family = nfmsg->nfgen_family;
 
-       rcu_read_lock();
        cb->seq = net->nft.base_seq;
 
-       list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
+       list_for_each_entry(afi, &net->nft.af_info, list) {
                if (family != NFPROTO_UNSPEC && family != afi->family)
                        continue;
 
-               list_for_each_entry_rcu(table, &afi->tables, list) {
-                       list_for_each_entry_rcu(chain, &table->chains, list) {
+               list_for_each_entry(table, &afi->tables, list) {
+                       list_for_each_entry(chain, &table->chains, list) {
                                if (idx < s_idx)
                                        goto cont;
                                if (idx > s_idx)
@@ -1120,7 +1117,6 @@ static int nf_tables_dump_chains(struct sk_buff *skb,
                }
        }
 done:
-       rcu_read_unlock();
        cb->args[0] = idx;
        return skb->len;
 }
@@ -1981,24 +1977,23 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
        struct net *net = sock_net(skb->sk);
        int family = nfmsg->nfgen_family;
 
-       rcu_read_lock();
        cb->seq = net->nft.base_seq;
 
-       list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
+       list_for_each_entry(afi, &net->nft.af_info, list) {
                if (family != NFPROTO_UNSPEC && family != afi->family)
                        continue;
 
-               list_for_each_entry_rcu(table, &afi->tables, list) {
+               list_for_each_entry(table, &afi->tables, list) {
                        if (ctx && ctx->table[0] &&
                            strcmp(ctx->table, table->name) != 0)
                                continue;
 
-                       list_for_each_entry_rcu(chain, &table->chains, list) {
+                       list_for_each_entry(chain, &table->chains, list) {
                                if (ctx && ctx->chain[0] &&
                                    strcmp(ctx->chain, chain->name) != 0)
                                        continue;
 
-                               list_for_each_entry_rcu(rule, &chain->rules, 
list) {
+                               list_for_each_entry(rule, &chain->rules, list) {
                                        if (!nft_is_active(net, rule))
                                                goto cont;
                                        if (idx < s_idx)
@@ -2021,8 +2016,6 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
                }
        }
 done:
-       rcu_read_unlock();
-
        cb->args[0] = idx;
        return skb->len;
 }
@@ -2699,10 +2692,9 @@ static int nf_tables_dump_sets(struct sk_buff *skb, 
struct netlink_callback *cb)
        if (cb->args[1])
                return skb->len;
 
-       rcu_read_lock();
        cb->seq = net->nft.base_seq;
 
-       list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
+       list_for_each_entry(afi, &net->nft.af_info, list) {
                if (ctx->afi && ctx->afi != afi)
                        continue;
 
@@ -2712,7 +2704,7 @@ static int nf_tables_dump_sets(struct sk_buff *skb, 
struct netlink_callback *cb)
 
                        cur_family = 0;
                }
-               list_for_each_entry_rcu(table, &afi->tables, list) {
+               list_for_each_entry(table, &afi->tables, list) {
                        if (ctx->table && ctx->table != table)
                                continue;
 
@@ -2723,7 +2715,7 @@ static int nf_tables_dump_sets(struct sk_buff *skb, 
struct netlink_callback *cb)
                                cur_table = NULL;
                        }
                        idx = 0;
-                       list_for_each_entry_rcu(set, &table->sets, list) {
+                       list_for_each_entry(set, &table->sets, list) {
                                if (idx < s_idx)
                                        goto cont;
                                if (!nft_is_active(net, set))
@@ -2750,7 +2742,6 @@ static int nf_tables_dump_sets(struct sk_buff *skb, 
struct netlink_callback *cb)
        }
        cb->args[1] = 1;
 done:
-       rcu_read_unlock();
        return skb->len;
 }
 
@@ -4246,15 +4237,14 @@ static int nf_tables_dump_obj(struct sk_buff *skb, 
struct netlink_callback *cb)
        if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
                reset = true;
 
-       rcu_read_lock();
        cb->seq = net->nft.base_seq;
 
-       list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
+       list_for_each_entry(afi, &net->nft.af_info, list) {
                if (family != NFPROTO_UNSPEC && family != afi->family)
                        continue;
 
-               list_for_each_entry_rcu(table, &afi->tables, list) {
-                       list_for_each_entry_rcu(obj, &table->objects, list) {
+               list_for_each_entry(table, &afi->tables, list) {
+                       list_for_each_entry(obj, &table->objects, list) {
                                if (!nft_is_active(net, obj))
                                        goto cont;
                                if (idx < s_idx)
@@ -4283,8 +4273,6 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct 
netlink_callback *cb)
                }
        }
 done:
-       rcu_read_unlock();
-
        cb->args[0] = idx;
        return skb->len;
 }
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to