diff options
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r-- | net/packet/af_packet.c | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 5f94db2f3e9e..1fc4a7885c41 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -77,6 +77,7 @@ | |||
77 | #include <linux/poll.h> | 77 | #include <linux/poll.h> |
78 | #include <linux/module.h> | 78 | #include <linux/module.h> |
79 | #include <linux/init.h> | 79 | #include <linux/init.h> |
80 | #include <linux/mutex.h> | ||
80 | 81 | ||
81 | #ifdef CONFIG_INET | 82 | #ifdef CONFIG_INET |
82 | #include <net/inet_common.h> | 83 | #include <net/inet_common.h> |
@@ -175,6 +176,7 @@ struct packet_sock { | |||
175 | #endif | 176 | #endif |
176 | struct packet_type prot_hook; | 177 | struct packet_type prot_hook; |
177 | spinlock_t bind_lock; | 178 | spinlock_t bind_lock; |
179 | struct mutex pg_vec_lock; | ||
178 | unsigned int running:1, /* prot_hook is attached*/ | 180 | unsigned int running:1, /* prot_hook is attached*/ |
179 | auxdata:1, | 181 | auxdata:1, |
180 | origdev:1; | 182 | origdev:1; |
@@ -220,13 +222,13 @@ static void *packet_lookup_frame(struct packet_sock *po, unsigned int position, | |||
220 | h.raw = po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size); | 222 | h.raw = po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size); |
221 | switch (po->tp_version) { | 223 | switch (po->tp_version) { |
222 | case TPACKET_V1: | 224 | case TPACKET_V1: |
223 | if (status != h.h1->tp_status ? TP_STATUS_USER : | 225 | if (status != (h.h1->tp_status ? TP_STATUS_USER : |
224 | TP_STATUS_KERNEL) | 226 | TP_STATUS_KERNEL)) |
225 | return NULL; | 227 | return NULL; |
226 | break; | 228 | break; |
227 | case TPACKET_V2: | 229 | case TPACKET_V2: |
228 | if (status != h.h2->tp_status ? TP_STATUS_USER : | 230 | if (status != (h.h2->tp_status ? TP_STATUS_USER : |
229 | TP_STATUS_KERNEL) | 231 | TP_STATUS_KERNEL)) |
230 | return NULL; | 232 | return NULL; |
231 | break; | 233 | break; |
232 | } | 234 | } |
@@ -1069,6 +1071,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol) | |||
1069 | */ | 1071 | */ |
1070 | 1072 | ||
1071 | spin_lock_init(&po->bind_lock); | 1073 | spin_lock_init(&po->bind_lock); |
1074 | mutex_init(&po->pg_vec_lock); | ||
1072 | po->prot_hook.func = packet_rcv; | 1075 | po->prot_hook.func = packet_rcv; |
1073 | 1076 | ||
1074 | if (sock->type == SOCK_PACKET) | 1077 | if (sock->type == SOCK_PACKET) |
@@ -1865,6 +1868,7 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing | |||
1865 | synchronize_net(); | 1868 | synchronize_net(); |
1866 | 1869 | ||
1867 | err = -EBUSY; | 1870 | err = -EBUSY; |
1871 | mutex_lock(&po->pg_vec_lock); | ||
1868 | if (closing || atomic_read(&po->mapped) == 0) { | 1872 | if (closing || atomic_read(&po->mapped) == 0) { |
1869 | err = 0; | 1873 | err = 0; |
1870 | #define XC(a, b) ({ __typeof__ ((a)) __t; __t = (a); (a) = (b); __t; }) | 1874 | #define XC(a, b) ({ __typeof__ ((a)) __t; __t = (a); (a) = (b); __t; }) |
@@ -1886,6 +1890,7 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing | |||
1886 | if (atomic_read(&po->mapped)) | 1890 | if (atomic_read(&po->mapped)) |
1887 | printk(KERN_DEBUG "packet_mmap: vma is busy: %d\n", atomic_read(&po->mapped)); | 1891 | printk(KERN_DEBUG "packet_mmap: vma is busy: %d\n", atomic_read(&po->mapped)); |
1888 | } | 1892 | } |
1893 | mutex_unlock(&po->pg_vec_lock); | ||
1889 | 1894 | ||
1890 | spin_lock(&po->bind_lock); | 1895 | spin_lock(&po->bind_lock); |
1891 | if (was_running && !po->running) { | 1896 | if (was_running && !po->running) { |
@@ -1918,7 +1923,7 @@ static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_st | |||
1918 | 1923 | ||
1919 | size = vma->vm_end - vma->vm_start; | 1924 | size = vma->vm_end - vma->vm_start; |
1920 | 1925 | ||
1921 | lock_sock(sk); | 1926 | mutex_lock(&po->pg_vec_lock); |
1922 | if (po->pg_vec == NULL) | 1927 | if (po->pg_vec == NULL) |
1923 | goto out; | 1928 | goto out; |
1924 | if (size != po->pg_vec_len*po->pg_vec_pages*PAGE_SIZE) | 1929 | if (size != po->pg_vec_len*po->pg_vec_pages*PAGE_SIZE) |
@@ -1941,7 +1946,7 @@ static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_st | |||
1941 | err = 0; | 1946 | err = 0; |
1942 | 1947 | ||
1943 | out: | 1948 | out: |
1944 | release_sock(sk); | 1949 | mutex_unlock(&po->pg_vec_lock); |
1945 | return err; | 1950 | return err; |
1946 | } | 1951 | } |
1947 | #endif | 1952 | #endif |