]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
rtnetlink: Add bulk registration helpers for rtnetlink message handlers.
authorKuniyuki Iwashima <kuniyu@amazon.com>
Tue, 8 Oct 2024 18:47:32 +0000 (11:47 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 17 Oct 2024 13:11:57 +0000 (15:11 +0200)
[ Upstream commit 07cc7b0b942bf55ef1a471470ecda8d2a6a6541f ]

Before commit addf9b90de22 ("net: rtnetlink: use rcu to free rtnl message
handlers"), once rtnl_msg_handlers[protocol] was allocated, the following
rtnl_register_module() for the same protocol never failed.

However, after the commit, rtnl_msg_handler[protocol][msgtype] needs to
be allocated in each rtnl_register_module(), so each call could fail.

Many callers of rtnl_register_module() do not handle the returned error,
and we need to add many error handlings.

To handle that easily, let's add wrapper functions for bulk registration
of rtnetlink message handlers.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Stable-dep-of: d51705614f66 ("mctp: Handle error of rtnl_register_module().")
Signed-off-by: Sasha Levin <sashal@kernel.org>
include/net/rtnetlink.h
net/core/rtnetlink.c

index c9d3ae92c93217524147a45b9cae514e80488805..dcb1c92e69879e1e586155f8af709febf3fb1b33 100644 (file)
@@ -20,6 +20,15 @@ enum rtnl_kinds {
        RTNL_KIND_SET
 };
 
+struct rtnl_msg_handler {
+       struct module *owner;
+       int protocol;
+       int msgtype;
+       rtnl_doit_func doit;
+       rtnl_dumpit_func dumpit;
+       int flags;
+};
+
 void rtnl_register(int protocol, int msgtype,
                   rtnl_doit_func, rtnl_dumpit_func, unsigned int flags);
 int rtnl_register_module(struct module *owner, int protocol, int msgtype,
@@ -27,6 +36,14 @@ int rtnl_register_module(struct module *owner, int protocol, int msgtype,
 int rtnl_unregister(int protocol, int msgtype);
 void rtnl_unregister_all(int protocol);
 
+int __rtnl_register_many(const struct rtnl_msg_handler *handlers, int n);
+void __rtnl_unregister_many(const struct rtnl_msg_handler *handlers, int n);
+
+#define rtnl_register_many(handlers)                           \
+       __rtnl_register_many(handlers, ARRAY_SIZE(handlers))
+#define rtnl_unregister_many(handlers)                         \
+       __rtnl_unregister_many(handlers, ARRAY_SIZE(handlers))
+
 static inline int rtnl_msg_family(const struct nlmsghdr *nlh)
 {
        if (nlmsg_len(nlh) >= sizeof(struct rtgenmsg))
index 8fc86d1edf5611273ae7d1c1e9394cbe22ea1c79..24795110b2ff39259c19c0e447a738d339176184 100644 (file)
@@ -348,6 +348,35 @@ void rtnl_unregister_all(int protocol)
 }
 EXPORT_SYMBOL_GPL(rtnl_unregister_all);
 
+int __rtnl_register_many(const struct rtnl_msg_handler *handlers, int n)
+{
+       const struct rtnl_msg_handler *handler;
+       int i, err;
+
+       for (i = 0, handler = handlers; i < n; i++, handler++) {
+               err = rtnl_register_internal(handler->owner, handler->protocol,
+                                            handler->msgtype, handler->doit,
+                                            handler->dumpit, handler->flags);
+               if (err) {
+                       __rtnl_unregister_many(handlers, i);
+                       break;
+               }
+       }
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(__rtnl_register_many);
+
+void __rtnl_unregister_many(const struct rtnl_msg_handler *handlers, int n)
+{
+       const struct rtnl_msg_handler *handler;
+       int i;
+
+       for (i = n - 1, handler = handlers + n - 1; i >= 0; i--, handler--)
+               rtnl_unregister(handler->protocol, handler->msgtype);
+}
+EXPORT_SYMBOL_GPL(__rtnl_unregister_many);
+
 static LIST_HEAD(link_ops);
 
 static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind)