aboutsummaryrefslogtreecommitdiffstats
path: root/net/packet/af_packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r--net/packet/af_packet.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index c26172995511..bec01a3daf5b 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1684,10 +1684,6 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
1684 1684
1685 mutex_lock(&fanout_mutex); 1685 mutex_lock(&fanout_mutex);
1686 1686
1687 err = -EINVAL;
1688 if (!po->running)
1689 goto out;
1690
1691 err = -EALREADY; 1687 err = -EALREADY;
1692 if (po->fanout) 1688 if (po->fanout)
1693 goto out; 1689 goto out;
@@ -1749,7 +1745,10 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
1749 list_add(&match->list, &fanout_list); 1745 list_add(&match->list, &fanout_list);
1750 } 1746 }
1751 err = -EINVAL; 1747 err = -EINVAL;
1752 if (match->type == type && 1748
1749 spin_lock(&po->bind_lock);
1750 if (po->running &&
1751 match->type == type &&
1753 match->prot_hook.type == po->prot_hook.type && 1752 match->prot_hook.type == po->prot_hook.type &&
1754 match->prot_hook.dev == po->prot_hook.dev) { 1753 match->prot_hook.dev == po->prot_hook.dev) {
1755 err = -ENOSPC; 1754 err = -ENOSPC;
@@ -1761,6 +1760,13 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
1761 err = 0; 1760 err = 0;
1762 } 1761 }
1763 } 1762 }
1763 spin_unlock(&po->bind_lock);
1764
1765 if (err && !refcount_read(&match->sk_ref)) {
1766 list_del(&match->list);
1767 kfree(match);
1768 }
1769
1764out: 1770out:
1765 if (err && rollover) { 1771 if (err && rollover) {
1766 kfree(rollover); 1772 kfree(rollover);
@@ -2834,6 +2840,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
2834 struct virtio_net_hdr vnet_hdr = { 0 }; 2840 struct virtio_net_hdr vnet_hdr = { 0 };
2835 int offset = 0; 2841 int offset = 0;
2836 struct packet_sock *po = pkt_sk(sk); 2842 struct packet_sock *po = pkt_sk(sk);
2843 bool has_vnet_hdr = false;
2837 int hlen, tlen, linear; 2844 int hlen, tlen, linear;
2838 int extra_len = 0; 2845 int extra_len = 0;
2839 2846
@@ -2877,6 +2884,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
2877 err = packet_snd_vnet_parse(msg, &len, &vnet_hdr); 2884 err = packet_snd_vnet_parse(msg, &len, &vnet_hdr);
2878 if (err) 2885 if (err)
2879 goto out_unlock; 2886 goto out_unlock;
2887 has_vnet_hdr = true;
2880 } 2888 }
2881 2889
2882 if (unlikely(sock_flag(sk, SOCK_NOFCS))) { 2890 if (unlikely(sock_flag(sk, SOCK_NOFCS))) {
@@ -2935,7 +2943,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
2935 skb->priority = sk->sk_priority; 2943 skb->priority = sk->sk_priority;
2936 skb->mark = sockc.mark; 2944 skb->mark = sockc.mark;
2937 2945
2938 if (po->has_vnet_hdr) { 2946 if (has_vnet_hdr) {
2939 err = virtio_net_hdr_to_skb(skb, &vnet_hdr, vio_le()); 2947 err = virtio_net_hdr_to_skb(skb, &vnet_hdr, vio_le());
2940 if (err) 2948 if (err)
2941 goto out_free; 2949 goto out_free;
@@ -3063,13 +3071,15 @@ static int packet_do_bind(struct sock *sk, const char *name, int ifindex,
3063 int ret = 0; 3071 int ret = 0;
3064 bool unlisted = false; 3072 bool unlisted = false;
3065 3073
3066 if (po->fanout)
3067 return -EINVAL;
3068
3069 lock_sock(sk); 3074 lock_sock(sk);
3070 spin_lock(&po->bind_lock); 3075 spin_lock(&po->bind_lock);
3071 rcu_read_lock(); 3076 rcu_read_lock();
3072 3077
3078 if (po->fanout) {
3079 ret = -EINVAL;
3080 goto out_unlock;
3081 }
3082
3073 if (name) { 3083 if (name) {
3074 dev = dev_get_by_name_rcu(sock_net(sk), name); 3084 dev = dev_get_by_name_rcu(sock_net(sk), name);
3075 if (!dev) { 3085 if (!dev) {