diff options
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r-- | net/packet/af_packet.c | 28 |
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 | |||
1764 | out: | 1770 | out: |
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) { |