[NETLINK]: Return -EPROTONOSUPPORT in netlink_create() if no kernel socket is registered

This is necessary for dynamic number of netlink groups to make sure we know
the number of possible groups before bind() is called. With this change pure
userspace communication using unused netlink protocols becomes impossible.

Signed-off-by: Patrick McHardy <[EMAIL PROTECTED]>

---
commit 159b54716bcf5aea4c3141a64072613db7934e11
tree 557c423ebef8a7527b2f69dc1a706cb7acbf6cf1
parent b96b2df4048e0b5fbfc9979d5a5fbcb200211b43
author Patrick McHardy <[EMAIL PROTECTED]> Mon, 15 Aug 2005 02:09:40 +0200
committer Patrick McHardy <[EMAIL PROTECTED]> Mon, 15 Aug 2005 02:09:40 +0200

 net/netlink/af_netlink.c |   72 ++++++++++++++++++++++++++++------------------
 1 files changed, 44 insertions(+), 28 deletions(-)

diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -102,6 +102,7 @@ struct netlink_table {
 	struct hlist_head mc_list;
 	unsigned int nl_nonroot;
 	struct module *module;
+	int registered;
 };
 
 static struct netlink_table *nl_table;
@@ -343,11 +344,32 @@ static struct proto netlink_proto = {
 	.obj_size = sizeof(struct netlink_sock),
 };
 
-static int netlink_create(struct socket *sock, int protocol)
+static int __netlink_create(struct socket *sock, int protocol)
 {
 	struct sock *sk;
 	struct netlink_sock *nlk;
-	struct module *module;
+
+	sock->ops = &netlink_ops;
+
+	sk = sk_alloc(PF_NETLINK, GFP_KERNEL, &netlink_proto, 1);
+	if (!sk)
+		return -ENOMEM;
+
+	sock_init_data(sock, sk);
+
+	nlk = nlk_sk(sk);
+	spin_lock_init(&nlk->cb_lock);
+	init_waitqueue_head(&nlk->wait);
+
+	sk->sk_destruct = netlink_sock_destruct;
+	sk->sk_protocol = protocol;
+	return 0;
+}
+
+static int netlink_create(struct socket *sock, int protocol)
+{
+	struct module *module = NULL;
+	int err = 0;
 
 	sock->state = SS_UNCONNECTED;
 
@@ -358,41 +380,33 @@ static int netlink_create(struct socket 
 		return -EPROTONOSUPPORT;
 
 	netlink_lock_table();
-	if (!nl_table[protocol].hash.entries) {
 #ifdef CONFIG_KMOD
-		/* We do 'best effort'.  If we find a matching module,
-		 * it is loaded.  If not, we don't return an error to
-		 * allow pure userspace<->userspace communication. -HW
-		 */
+	if (!nl_table[protocol].registered) {
 		netlink_unlock_table();
 		request_module("net-pf-%d-proto-%d", PF_NETLINK, protocol);
 		netlink_lock_table();
-#endif
 	}
-	module = nl_table[protocol].module;
-	if (!try_module_get(module))
-		module = NULL;
+#endif
+	if (nl_table[protocol].registered &&
+	    try_module_get(nl_table[protocol].module))
+		module = nl_table[protocol].module;
+	else
+		err = -EPROTONOSUPPORT;
 	netlink_unlock_table();
 
-	sock->ops = &netlink_ops;
-
-	sk = sk_alloc(PF_NETLINK, GFP_KERNEL, &netlink_proto, 1);
-	if (!sk) {
-		module_put(module);
-		return -ENOMEM;
-	}
-
-	sock_init_data(sock, sk);
+	if (err)
+		goto out;
 
-	nlk = nlk_sk(sk);
+	if ((err = __netlink_create(sock, protocol) < 0))
+		goto out_module;
 
-	nlk->module = module;
-	spin_lock_init(&nlk->cb_lock);
-	init_waitqueue_head(&nlk->wait);
-	sk->sk_destruct = netlink_sock_destruct;
+	nlk_sk(sock->sk)->module = module;
+out:
+	return err;
 
-	sk->sk_protocol = protocol;
-	return 0;
+out_module:
+	module_put(module);
+	goto out;
 }
 
 static int netlink_release(struct socket *sock)
@@ -437,6 +451,7 @@ static int netlink_release(struct socket
 	if (nlk->flags & NETLINK_KERNEL_SOCKET) {
 		netlink_table_grab();
 		nl_table[sk->sk_protocol].module = NULL;
+		nl_table[sk->sk_protocol].registered = 0;
 		netlink_table_ungrab();
 	}
 
@@ -1082,7 +1097,7 @@ netlink_kernel_create(int unit, void (*i
 	if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
 		return NULL;
 
-	if (netlink_create(sock, unit) < 0)
+	if (__netlink_create(sock, unit) < 0)
 		goto out_sock_release;
 
 	sk = sock->sk;
@@ -1098,6 +1113,7 @@ netlink_kernel_create(int unit, void (*i
 
 	netlink_table_grab();
 	nl_table[unit].module = module;
+	nl_table[unit].registered = 1;
 	netlink_table_ungrab();
 
 	return sk;

Reply via email to