提交 513c2500 编写于 作者: P Patrick McHardy 提交者: David S. Miller

[NETLINK]: Don't prevent creating sockets when no kernel socket is registered

This broke the pam audit module which includes an incorrect check for
-ENOENT instead of -EPROTONOTSUPP.
Signed-off-by: NPatrick McHardy <kaber@trash.net>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 e4466399
...@@ -398,24 +398,13 @@ static int netlink_create(struct socket *sock, int protocol) ...@@ -398,24 +398,13 @@ static int netlink_create(struct socket *sock, int protocol)
if (nl_table[protocol].registered && if (nl_table[protocol].registered &&
try_module_get(nl_table[protocol].module)) try_module_get(nl_table[protocol].module))
module = nl_table[protocol].module; module = nl_table[protocol].module;
else
err = -EPROTONOSUPPORT;
groups = nl_table[protocol].groups; groups = nl_table[protocol].groups;
netlink_unlock_table(); netlink_unlock_table();
if (err || (err = __netlink_create(sock, protocol) < 0)) if ((err = __netlink_create(sock, protocol) < 0))
goto out_module; goto out_module;
nlk = nlk_sk(sock->sk); nlk = nlk_sk(sock->sk);
nlk->groups = kmalloc(NLGRPSZ(groups), GFP_KERNEL);
if (nlk->groups == NULL) {
err = -ENOMEM;
goto out_module;
}
memset(nlk->groups, 0, NLGRPSZ(groups));
nlk->ngroups = groups;
nlk->module = module; nlk->module = module;
out: out:
return err; return err;
...@@ -534,6 +523,29 @@ netlink_update_subscriptions(struct sock *sk, unsigned int subscriptions) ...@@ -534,6 +523,29 @@ netlink_update_subscriptions(struct sock *sk, unsigned int subscriptions)
nlk->subscriptions = subscriptions; nlk->subscriptions = subscriptions;
} }
static int netlink_alloc_groups(struct sock *sk)
{
struct netlink_sock *nlk = nlk_sk(sk);
unsigned int groups;
int err = 0;
netlink_lock_table();
groups = nl_table[sk->sk_protocol].groups;
if (!nl_table[sk->sk_protocol].registered)
err = -ENOENT;
netlink_unlock_table();
if (err)
return err;
nlk->groups = kmalloc(NLGRPSZ(groups), GFP_KERNEL);
if (nlk->groups == NULL)
return -ENOMEM;
memset(nlk->groups, 0, NLGRPSZ(groups));
nlk->ngroups = groups;
return 0;
}
static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len) static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
...@@ -545,8 +557,15 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len ...@@ -545,8 +557,15 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len
return -EINVAL; return -EINVAL;
/* Only superuser is allowed to listen multicasts */ /* Only superuser is allowed to listen multicasts */
if (nladdr->nl_groups && !netlink_capable(sock, NL_NONROOT_RECV)) if (nladdr->nl_groups) {
return -EPERM; if (!netlink_capable(sock, NL_NONROOT_RECV))
return -EPERM;
if (nlk->groups == NULL) {
err = netlink_alloc_groups(sk);
if (err)
return err;
}
}
if (nlk->pid) { if (nlk->pid) {
if (nladdr->nl_pid != nlk->pid) if (nladdr->nl_pid != nlk->pid)
...@@ -559,7 +578,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len ...@@ -559,7 +578,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len
return err; return err;
} }
if (!nladdr->nl_groups && !(u32)nlk->groups[0]) if (!nladdr->nl_groups && (nlk->groups == NULL || !(u32)nlk->groups[0]))
return 0; return 0;
netlink_table_grab(); netlink_table_grab();
...@@ -620,7 +639,7 @@ static int netlink_getname(struct socket *sock, struct sockaddr *addr, int *addr ...@@ -620,7 +639,7 @@ static int netlink_getname(struct socket *sock, struct sockaddr *addr, int *addr
nladdr->nl_groups = netlink_group_mask(nlk->dst_group); nladdr->nl_groups = netlink_group_mask(nlk->dst_group);
} else { } else {
nladdr->nl_pid = nlk->pid; nladdr->nl_pid = nlk->pid;
nladdr->nl_groups = nlk->groups[0]; nladdr->nl_groups = nlk->groups ? nlk->groups[0] : 0;
} }
return 0; return 0;
} }
...@@ -976,6 +995,11 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, ...@@ -976,6 +995,11 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
if (!netlink_capable(sock, NL_NONROOT_RECV)) if (!netlink_capable(sock, NL_NONROOT_RECV))
return -EPERM; return -EPERM;
if (nlk->groups == NULL) {
err = netlink_alloc_groups(sk);
if (err)
return err;
}
if (!val || val - 1 >= nlk->ngroups) if (!val || val - 1 >= nlk->ngroups)
return -EINVAL; return -EINVAL;
netlink_table_grab(); netlink_table_grab();
...@@ -1483,8 +1507,7 @@ static int netlink_seq_show(struct seq_file *seq, void *v) ...@@ -1483,8 +1507,7 @@ static int netlink_seq_show(struct seq_file *seq, void *v)
s, s,
s->sk_protocol, s->sk_protocol,
nlk->pid, nlk->pid,
nlk->flags & NETLINK_KERNEL_SOCKET ? nlk->groups ? (u32)nlk->groups[0] : 0,
0 : (unsigned int)nlk->groups[0],
atomic_read(&s->sk_rmem_alloc), atomic_read(&s->sk_rmem_alloc),
atomic_read(&s->sk_wmem_alloc), atomic_read(&s->sk_wmem_alloc),
nlk->cb, nlk->cb,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册