|
@@ -1091,8 +1091,10 @@ static void netlink_remove(struct sock *sk)
|
|
|
mutex_unlock(&nl_sk_hash_lock);
|
|
|
|
|
|
netlink_table_grab();
|
|
|
- if (nlk_sk(sk)->subscriptions)
|
|
|
+ if (nlk_sk(sk)->subscriptions) {
|
|
|
__sk_del_bind_node(sk);
|
|
|
+ netlink_update_listeners(sk);
|
|
|
+ }
|
|
|
netlink_table_ungrab();
|
|
|
}
|
|
|
|
|
@@ -1226,8 +1228,8 @@ static int netlink_release(struct socket *sock)
|
|
|
|
|
|
module_put(nlk->module);
|
|
|
|
|
|
- netlink_table_grab();
|
|
|
if (netlink_is_kernel(sk)) {
|
|
|
+ netlink_table_grab();
|
|
|
BUG_ON(nl_table[sk->sk_protocol].registered == 0);
|
|
|
if (--nl_table[sk->sk_protocol].registered == 0) {
|
|
|
struct listeners *old;
|
|
@@ -1241,11 +1243,16 @@ static int netlink_release(struct socket *sock)
|
|
|
nl_table[sk->sk_protocol].flags = 0;
|
|
|
nl_table[sk->sk_protocol].registered = 0;
|
|
|
}
|
|
|
- } else if (nlk->subscriptions) {
|
|
|
- netlink_update_listeners(sk);
|
|
|
+ netlink_table_ungrab();
|
|
|
}
|
|
|
- netlink_table_ungrab();
|
|
|
|
|
|
+ if (nlk->netlink_unbind) {
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < nlk->ngroups; i++)
|
|
|
+ if (test_bit(i, nlk->groups))
|
|
|
+ nlk->netlink_unbind(i + 1);
|
|
|
+ }
|
|
|
kfree(nlk->groups);
|
|
|
nlk->groups = NULL;
|
|
|
|
|
@@ -1410,8 +1417,8 @@ static int netlink_realloc_groups(struct sock *sk)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static void netlink_unbind(int group, long unsigned int groups,
|
|
|
- struct netlink_sock *nlk)
|
|
|
+static void netlink_undo_bind(int group, long unsigned int groups,
|
|
|
+ struct netlink_sock *nlk)
|
|
|
{
|
|
|
int undo;
|
|
|
|
|
@@ -1461,7 +1468,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
|
|
|
err = nlk->netlink_bind(group);
|
|
|
if (!err)
|
|
|
continue;
|
|
|
- netlink_unbind(group, groups, nlk);
|
|
|
+ netlink_undo_bind(group, groups, nlk);
|
|
|
return err;
|
|
|
}
|
|
|
}
|
|
@@ -1471,7 +1478,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
|
|
|
netlink_insert(sk, net, nladdr->nl_pid) :
|
|
|
netlink_autobind(sock);
|
|
|
if (err) {
|
|
|
- netlink_unbind(nlk->ngroups, groups, nlk);
|
|
|
+ netlink_undo_bind(nlk->ngroups, groups, nlk);
|
|
|
return err;
|
|
|
}
|
|
|
}
|