diff options
Diffstat (limited to 'net/netlink/af_netlink.c')
-rw-r--r-- | net/netlink/af_netlink.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index e41ce458c2a9..fc456a7aaec3 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -315,8 +315,8 @@ err: | |||
315 | static void netlink_remove(struct sock *sk) | 315 | static void netlink_remove(struct sock *sk) |
316 | { | 316 | { |
317 | netlink_table_grab(); | 317 | netlink_table_grab(); |
318 | nl_table[sk->sk_protocol].hash.entries--; | 318 | if (sk_del_node_init(sk)) |
319 | sk_del_node_init(sk); | 319 | nl_table[sk->sk_protocol].hash.entries--; |
320 | if (nlk_sk(sk)->groups) | 320 | if (nlk_sk(sk)->groups) |
321 | __sk_del_bind_node(sk); | 321 | __sk_del_bind_node(sk); |
322 | netlink_table_ungrab(); | 322 | netlink_table_ungrab(); |
@@ -429,7 +429,12 @@ retry: | |||
429 | err = netlink_insert(sk, pid); | 429 | err = netlink_insert(sk, pid); |
430 | if (err == -EADDRINUSE) | 430 | if (err == -EADDRINUSE) |
431 | goto retry; | 431 | goto retry; |
432 | return 0; | 432 | |
433 | /* If 2 threads race to autobind, that is fine. */ | ||
434 | if (err == -EBUSY) | ||
435 | err = 0; | ||
436 | |||
437 | return err; | ||
433 | } | 438 | } |
434 | 439 | ||
435 | static inline int netlink_capable(struct socket *sock, unsigned int flag) | 440 | static inline int netlink_capable(struct socket *sock, unsigned int flag) |
@@ -1095,8 +1100,7 @@ static int netlink_dump(struct sock *sk) | |||
1095 | return 0; | 1100 | return 0; |
1096 | } | 1101 | } |
1097 | 1102 | ||
1098 | nlh = __nlmsg_put(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLMSG_DONE, sizeof(int)); | 1103 | nlh = NLMSG_NEW_ANSWER(skb, cb, NLMSG_DONE, sizeof(len), NLM_F_MULTI); |
1099 | nlh->nlmsg_flags |= NLM_F_MULTI; | ||
1100 | memcpy(NLMSG_DATA(nlh), &len, sizeof(len)); | 1104 | memcpy(NLMSG_DATA(nlh), &len, sizeof(len)); |
1101 | skb_queue_tail(&sk->sk_receive_queue, skb); | 1105 | skb_queue_tail(&sk->sk_receive_queue, skb); |
1102 | sk->sk_data_ready(sk, skb->len); | 1106 | sk->sk_data_ready(sk, skb->len); |
@@ -1107,6 +1111,9 @@ static int netlink_dump(struct sock *sk) | |||
1107 | 1111 | ||
1108 | netlink_destroy_callback(cb); | 1112 | netlink_destroy_callback(cb); |
1109 | return 0; | 1113 | return 0; |
1114 | |||
1115 | nlmsg_failure: | ||
1116 | return -ENOBUFS; | ||
1110 | } | 1117 | } |
1111 | 1118 | ||
1112 | int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | 1119 | int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, |
@@ -1178,7 +1185,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) | |||
1178 | } | 1185 | } |
1179 | 1186 | ||
1180 | rep = __nlmsg_put(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, | 1187 | rep = __nlmsg_put(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, |
1181 | NLMSG_ERROR, sizeof(struct nlmsgerr)); | 1188 | NLMSG_ERROR, sizeof(struct nlmsgerr), 0); |
1182 | errmsg = NLMSG_DATA(rep); | 1189 | errmsg = NLMSG_DATA(rep); |
1183 | errmsg->error = err; | 1190 | errmsg->error = err; |
1184 | memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(struct nlmsghdr)); | 1191 | memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(struct nlmsghdr)); |