From: Florian Westphal <fw@strlen.de>
To: <netdev@vger.kernel.org>
Cc: peterz@infradead.org, Florian Westphal <fw@strlen.de>
Subject: [PATCH net-next 2/8] rtnetlink: add rtnl_register_module
Date: Mon, 6 Nov 2017 11:51:07 +0100 [thread overview]
Message-ID: <20171106105113.20476-3-fw@strlen.de> (raw)
In-Reply-To: <20171106105113.20476-1-fw@strlen.de>
Add yet another rtnl_register function. It will be used by modules
that can be removed.
The passed module struct is used to take a reference while a netlink
dump is in progress to prevent module unload while netlink core can
invoke registered dumper function again.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/net/rtnetlink.h | 2 +
net/core/rtnetlink.c | 103 +++++++++++++++++++++++++++++++++++++-----------
2 files changed, 83 insertions(+), 22 deletions(-)
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index ead018744ff5..e326b3f9eb5f 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -17,6 +17,8 @@ int __rtnl_register(int protocol, int msgtype,
rtnl_doit_func, rtnl_dumpit_func, unsigned 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,
+ rtnl_doit_func, rtnl_dumpit_func, unsigned int flags);
int rtnl_unregister(int protocol, int msgtype);
void rtnl_unregister_all(int protocol);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index c70f62137dd8..50b483b24845 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -62,6 +62,7 @@
struct rtnl_link {
rtnl_doit_func doit;
rtnl_dumpit_func dumpit;
+ struct module *owner;
unsigned int flags;
};
@@ -143,27 +144,10 @@ static inline int rtm_msgindex(int msgtype)
return msgindex;
}
-/**
- * __rtnl_register - Register a rtnetlink message type
- * @protocol: Protocol family or PF_UNSPEC
- * @msgtype: rtnetlink message type
- * @doit: Function pointer called for each request message
- * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message
- * @flags: rtnl_link_flags to modifiy behaviour of doit/dumpit functions
- *
- * Registers the specified function pointers (at least one of them has
- * to be non-NULL) to be called whenever a request message for the
- * specified protocol family and message type is received.
- *
- * The special protocol family PF_UNSPEC may be used to define fallback
- * function pointers for the case when no entry for the specific protocol
- * family exists.
- *
- * Returns 0 on success or a negative error code.
- */
-int __rtnl_register(int protocol, int msgtype,
- rtnl_doit_func doit, rtnl_dumpit_func dumpit,
- unsigned int flags)
+static int rtnl_register_internal(struct module *owner,
+ int protocol, int msgtype,
+ rtnl_doit_func doit, rtnl_dumpit_func dumpit,
+ unsigned int flags)
{
struct rtnl_link *tab;
int msgindex;
@@ -180,6 +164,12 @@ int __rtnl_register(int protocol, int msgtype,
rcu_assign_pointer(rtnl_msg_handlers[protocol], tab);
}
+ WARN_ON(tab[msgindex].owner && tab[msgindex].owner != owner);
+
+ tab[msgindex].owner = owner;
+ /* make sure owner is always visible first */
+ smp_wmb();
+
if (doit)
tab[msgindex].doit = doit;
if (dumpit)
@@ -188,6 +178,60 @@ int __rtnl_register(int protocol, int msgtype,
return 0;
}
+
+/**
+ * rtnl_register_module - Register a rtnetlink message type
+ *
+ * @owner: module registering the hook (THIS_MODULE)
+ * @protocol: Protocol family or PF_UNSPEC
+ * @msgtype: rtnetlink message type
+ * @doit: Function pointer called for each request message
+ * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message
+ * @flags: rtnl_link_flags to modifiy behaviour of doit/dumpit functions
+ *
+ * Like rtnl_register, but for use by removable modules.
+ */
+int rtnl_register_module(struct module *owner,
+ int protocol, int msgtype,
+ rtnl_doit_func doit, rtnl_dumpit_func dumpit,
+ unsigned int flags)
+{
+ int ret;
+
+ rtnl_lock();
+ ret = rtnl_register_internal(owner, protocol, msgtype,
+ doit, dumpit, flags);
+ rtnl_unlock();
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rtnl_register_module);
+
+/**
+ * __rtnl_register - Register a rtnetlink message type
+ * @protocol: Protocol family or PF_UNSPEC
+ * @msgtype: rtnetlink message type
+ * @doit: Function pointer called for each request message
+ * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message
+ * @flags: rtnl_link_flags to modifiy behaviour of doit/dumpit functions
+ *
+ * Registers the specified function pointers (at least one of them has
+ * to be non-NULL) to be called whenever a request message for the
+ * specified protocol family and message type is received.
+ *
+ * The special protocol family PF_UNSPEC may be used to define fallback
+ * function pointers for the case when no entry for the specific protocol
+ * family exists.
+ *
+ * Returns 0 on success or a negative error code.
+ */
+int __rtnl_register(int protocol, int msgtype,
+ rtnl_doit_func doit, rtnl_dumpit_func dumpit,
+ unsigned int flags)
+{
+ return rtnl_register_internal(NULL, protocol, msgtype,
+ doit, dumpit, flags);
+}
EXPORT_SYMBOL_GPL(__rtnl_register);
/**
@@ -235,6 +279,9 @@ int rtnl_unregister(int protocol, int msgtype)
handlers[msgindex].doit = NULL;
handlers[msgindex].dumpit = NULL;
handlers[msgindex].flags = 0;
+ /* make sure we clear owner last */
+ smp_wmb();
+ handlers[msgindex].owner = NULL;
rtnl_unlock();
return 0;
@@ -4346,6 +4393,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
}
if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
+ struct module *owner = NULL;
struct sock *rtnl;
rtnl_dumpit_func dumpit;
u16 min_dump_alloc = 0;
@@ -4360,20 +4408,31 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
dumpit = READ_ONCE(handlers[type].dumpit);
if (!dumpit)
goto err_unlock;
+ owner = READ_ONCE(handlers[type].owner);
}
if (type == RTM_GETLINK - RTM_BASE)
min_dump_alloc = rtnl_calcit(skb, nlh);
+ err = 0;
+ /* need to do this before rcu_read_unlock() */
+ if (!try_module_get(owner))
+ err = -EPROTONOSUPPORT;
+
rcu_read_unlock();
rtnl = net->rtnl;
- {
+ if (err == 0) {
struct netlink_dump_control c = {
.dump = dumpit,
.min_dump_alloc = min_dump_alloc,
+ .module = owner,
};
err = netlink_dump_start(rtnl, skb, nlh, &c);
+ /* netlink_dump_start() will keep a reference on
+ * module if dump is still in progress.
+ */
+ module_put(owner);
}
return err;
}
--
2.13.6
next prev parent reply other threads:[~2017-11-06 10:51 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-11-06 10:51 rtnetlink: fix dump+module unload races, take 2 Florian Westphal
2017-11-06 10:51 ` [PATCH net-next 1/8] rtnetlink: Revert "rtnetlink: add reference counting to prevent module unload while dump is in progress" Florian Westphal
2017-11-06 10:51 ` Florian Westphal [this message]
2017-11-06 12:44 ` [PATCH net-next 2/8] rtnetlink: add rtnl_register_module Peter Zijlstra
2017-11-07 6:11 ` Florian Westphal
2017-11-07 9:10 ` Peter Zijlstra
2017-11-07 9:24 ` Peter Zijlstra
2017-11-07 9:47 ` Florian Westphal
2017-11-07 14:57 ` Peter Zijlstra
2017-11-08 1:27 ` Stephen Hemminger
2017-11-13 7:21 ` Florian Westphal
2017-11-13 7:55 ` Peter Zijlstra
2017-11-13 7:59 ` Florian Westphal
2017-11-07 9:43 ` Florian Westphal
2017-11-06 10:51 ` [PATCH net-next 3/8] qtr: use rtnl_register_module Florian Westphal
2017-11-06 10:51 ` [PATCH net-next 4/8] bridge: " Florian Westphal
2017-11-06 10:51 ` [PATCH net-next 5/8] can: " Florian Westphal
2017-11-06 10:51 ` [PATCH net-next 6/8] decnet: " Florian Westphal
2017-11-06 10:51 ` [PATCH net-next 7/8] phonet: " Florian Westphal
2017-11-06 10:51 ` [PATCH net-next 8/8] mpls: " Florian Westphal
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20171106105113.20476-3-fw@strlen.de \
--to=fw@strlen.de \
--cc=netdev@vger.kernel.org \
--cc=peterz@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.