Skip to content

Commit

Permalink
[NETLINK]: Return -EPROTONOSUPPORT in netlink_create() if no kernel s…
Browse files Browse the repository at this point in the history
…ocket 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 <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Patrick McHardy authored and David S. Miller committed Aug 29, 2005
1 parent ac6d439 commit ab33a17
Showing 1 changed file with 44 additions and 28 deletions.
72 changes: 44 additions & 28 deletions net/netlink/af_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -358,41 +380,33 @@ static int netlink_create(struct socket *sock, int protocol)
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)
Expand Down Expand Up @@ -437,6 +451,7 @@ static int netlink_release(struct socket *sock)
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();
}

Expand Down Expand Up @@ -1082,7 +1097,7 @@ netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len), struct
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;
Expand All @@ -1098,6 +1113,7 @@ netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len), struct

netlink_table_grab();
nl_table[unit].module = module;
nl_table[unit].registered = 1;
netlink_table_ungrab();

return sk;
Expand Down

0 comments on commit ab33a17

Please sign in to comment.