rtnetlink: add RTNL_FLAG_DUMP_UNLOCKED flag
authorEric Dumazet <edumazet@google.com>
Thu, 22 Feb 2024 10:50:15 +0000 (10:50 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 26 Feb 2024 11:46:12 +0000 (11:46 +0000)
Similarly to RTNL_FLAG_DOIT_UNLOCKED, this new flag
allows dump operations registered via rtnl_register()
or rtnl_register_module() to opt-out from RTNL protection.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Donald Hunter <donald.hunter@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/netlink.h
include/net/rtnetlink.h
net/core/rtnetlink.c
net/netlink/af_netlink.c

index 1a4445b..5df7340 100644 (file)
@@ -291,6 +291,7 @@ struct netlink_callback {
        u16                     answer_flags;
        u32                     min_dump_alloc;
        unsigned int            prev_seq, seq;
        u16                     answer_flags;
        u32                     min_dump_alloc;
        unsigned int            prev_seq, seq;
+       int                     flags;
        bool                    strict_check;
        union {
                u8              ctx[48];
        bool                    strict_check;
        union {
                u8              ctx[48];
@@ -323,6 +324,7 @@ struct netlink_dump_control {
        void *data;
        struct module *module;
        u32 min_dump_alloc;
        void *data;
        struct module *module;
        u32 min_dump_alloc;
+       int flags;
 };
 
 int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
 };
 
 int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
index 6506221..3bfb80b 100644 (file)
@@ -12,6 +12,7 @@ typedef int (*rtnl_dumpit_func)(struct sk_buff *, struct netlink_callback *);
 enum rtnl_link_flags {
        RTNL_FLAG_DOIT_UNLOCKED         = BIT(0),
        RTNL_FLAG_BULK_DEL_SUPPORTED    = BIT(1),
 enum rtnl_link_flags {
        RTNL_FLAG_DOIT_UNLOCKED         = BIT(0),
        RTNL_FLAG_BULK_DEL_SUPPORTED    = BIT(1),
+       RTNL_FLAG_DUMP_UNLOCKED         = BIT(2),
 };
 
 enum rtnl_kinds {
 };
 
 enum rtnl_kinds {
index 060543f..1b26dfa 100644 (file)
@@ -6532,6 +6532,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
                }
                owner = link->owner;
                dumpit = link->dumpit;
                }
                owner = link->owner;
                dumpit = link->dumpit;
+               flags = link->flags;
 
                if (type == RTM_GETLINK - RTM_BASE)
                        min_dump_alloc = rtnl_calcit(skb, nlh);
 
                if (type == RTM_GETLINK - RTM_BASE)
                        min_dump_alloc = rtnl_calcit(skb, nlh);
@@ -6549,6 +6550,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
                                .dump           = dumpit,
                                .min_dump_alloc = min_dump_alloc,
                                .module         = owner,
                                .dump           = dumpit,
                                .min_dump_alloc = min_dump_alloc,
                                .module         = owner,
+                               .flags          = flags,
                        };
                        err = netlink_dump_start(rtnl, skb, nlh, &c);
                        /* netlink_dump_start() will keep a reference on
                        };
                        err = netlink_dump_start(rtnl, skb, nlh, &c);
                        /* netlink_dump_start() will keep a reference on
index 84cad7b..be5792b 100644 (file)
@@ -2261,6 +2261,8 @@ static int netlink_dump(struct sock *sk, bool lock_taken)
 
                cb->extack = &extack;
 
 
                cb->extack = &extack;
 
+               if (cb->flags & RTNL_FLAG_DUMP_UNLOCKED)
+                       extra_mutex = NULL;
                if (extra_mutex)
                        mutex_lock(extra_mutex);
                nlk->dump_done_errno = cb->dump(skb, cb);
                if (extra_mutex)
                        mutex_lock(extra_mutex);
                nlk->dump_done_errno = cb->dump(skb, cb);
@@ -2355,6 +2357,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
        cb->data = control->data;
        cb->module = control->module;
        cb->min_dump_alloc = control->min_dump_alloc;
        cb->data = control->data;
        cb->module = control->module;
        cb->min_dump_alloc = control->min_dump_alloc;
+       cb->flags = control->flags;
        cb->skb = skb;
 
        cb->strict_check = nlk_test_bit(STRICT_CHK, NETLINK_CB(skb).sk);
        cb->skb = skb;
 
        cb->strict_check = nlk_test_bit(STRICT_CHK, NETLINK_CB(skb).sk);