|
@@ -886,6 +886,13 @@ retry:
|
|
if (netlink_is_kernel(sk))
|
|
if (netlink_is_kernel(sk))
|
|
return netlink_unicast_kernel(sk, skb);
|
|
return netlink_unicast_kernel(sk, skb);
|
|
|
|
|
|
|
|
+ if (sk_filter(sk, skb)) {
|
|
|
|
+ int err = skb->len;
|
|
|
|
+ kfree_skb(skb);
|
|
|
|
+ sock_put(sk);
|
|
|
|
+ return err;
|
|
|
|
+ }
|
|
|
|
+
|
|
err = netlink_attachskb(sk, skb, nonblock, &timeo, ssk);
|
|
err = netlink_attachskb(sk, skb, nonblock, &timeo, ssk);
|
|
if (err == 1)
|
|
if (err == 1)
|
|
goto retry;
|
|
goto retry;
|
|
@@ -980,6 +987,9 @@ static inline int do_one_broadcast(struct sock *sk,
|
|
netlink_overrun(sk);
|
|
netlink_overrun(sk);
|
|
/* Clone failed. Notify ALL listeners. */
|
|
/* Clone failed. Notify ALL listeners. */
|
|
p->failure = 1;
|
|
p->failure = 1;
|
|
|
|
+ } else if (sk_filter(sk, p->skb2)) {
|
|
|
|
+ kfree_skb(p->skb2);
|
|
|
|
+ p->skb2 = NULL;
|
|
} else if ((val = netlink_broadcast_deliver(sk, p->skb2)) < 0) {
|
|
} else if ((val = netlink_broadcast_deliver(sk, p->skb2)) < 0) {
|
|
netlink_overrun(sk);
|
|
netlink_overrun(sk);
|
|
} else {
|
|
} else {
|
|
@@ -1533,8 +1543,13 @@ static int netlink_dump(struct sock *sk)
|
|
|
|
|
|
if (len > 0) {
|
|
if (len > 0) {
|
|
mutex_unlock(nlk->cb_mutex);
|
|
mutex_unlock(nlk->cb_mutex);
|
|
- skb_queue_tail(&sk->sk_receive_queue, skb);
|
|
|
|
- sk->sk_data_ready(sk, len);
|
|
|
|
|
|
+
|
|
|
|
+ if (sk_filter(sk, skb))
|
|
|
|
+ kfree_skb(skb);
|
|
|
|
+ else {
|
|
|
|
+ skb_queue_tail(&sk->sk_receive_queue, skb);
|
|
|
|
+ sk->sk_data_ready(sk, skb->len);
|
|
|
|
+ }
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1544,8 +1559,12 @@ static int netlink_dump(struct sock *sk)
|
|
|
|
|
|
memcpy(nlmsg_data(nlh), &len, sizeof(len));
|
|
memcpy(nlmsg_data(nlh), &len, sizeof(len));
|
|
|
|
|
|
- skb_queue_tail(&sk->sk_receive_queue, skb);
|
|
|
|
- sk->sk_data_ready(sk, skb->len);
|
|
|
|
|
|
+ if (sk_filter(sk, skb))
|
|
|
|
+ kfree_skb(skb);
|
|
|
|
+ else {
|
|
|
|
+ skb_queue_tail(&sk->sk_receive_queue, skb);
|
|
|
|
+ sk->sk_data_ready(sk, skb->len);
|
|
|
|
+ }
|
|
|
|
|
|
if (cb->done)
|
|
if (cb->done)
|
|
cb->done(cb);
|
|
cb->done(cb);
|