diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2011-02-17 22:26:36 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-02-22 13:19:31 -0500 |
commit | eaefd1105bc431ef329599e307a07f2a36ae7872 (patch) | |
tree | 658eeed417654c8f6015d4d5f957f5a1b5e9521f /net/socket.c | |
parent | 04cfa852ff8dab923640500ee850d19e75bacabc (diff) |
net: add __rcu annotations to sk_wq and wq
Add proper RCU annotations/verbs to sk_wq and wq members
Fix __sctp_write_space() sk_sleep() abuse (and sock->wq access)
Fix sunrpc sk_sleep() abuse too
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/net/socket.c b/net/socket.c index ac2219f90d5d..9fa1e3b4366e 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -240,17 +240,19 @@ static struct kmem_cache *sock_inode_cachep __read_mostly; | |||
240 | static struct inode *sock_alloc_inode(struct super_block *sb) | 240 | static struct inode *sock_alloc_inode(struct super_block *sb) |
241 | { | 241 | { |
242 | struct socket_alloc *ei; | 242 | struct socket_alloc *ei; |
243 | struct socket_wq *wq; | ||
243 | 244 | ||
244 | ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL); | 245 | ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL); |
245 | if (!ei) | 246 | if (!ei) |
246 | return NULL; | 247 | return NULL; |
247 | ei->socket.wq = kmalloc(sizeof(struct socket_wq), GFP_KERNEL); | 248 | wq = kmalloc(sizeof(*wq), GFP_KERNEL); |
248 | if (!ei->socket.wq) { | 249 | if (!wq) { |
249 | kmem_cache_free(sock_inode_cachep, ei); | 250 | kmem_cache_free(sock_inode_cachep, ei); |
250 | return NULL; | 251 | return NULL; |
251 | } | 252 | } |
252 | init_waitqueue_head(&ei->socket.wq->wait); | 253 | init_waitqueue_head(&wq->wait); |
253 | ei->socket.wq->fasync_list = NULL; | 254 | wq->fasync_list = NULL; |
255 | RCU_INIT_POINTER(ei->socket.wq, wq); | ||
254 | 256 | ||
255 | ei->socket.state = SS_UNCONNECTED; | 257 | ei->socket.state = SS_UNCONNECTED; |
256 | ei->socket.flags = 0; | 258 | ei->socket.flags = 0; |
@@ -273,9 +275,11 @@ static void wq_free_rcu(struct rcu_head *head) | |||
273 | static void sock_destroy_inode(struct inode *inode) | 275 | static void sock_destroy_inode(struct inode *inode) |
274 | { | 276 | { |
275 | struct socket_alloc *ei; | 277 | struct socket_alloc *ei; |
278 | struct socket_wq *wq; | ||
276 | 279 | ||
277 | ei = container_of(inode, struct socket_alloc, vfs_inode); | 280 | ei = container_of(inode, struct socket_alloc, vfs_inode); |
278 | call_rcu(&ei->socket.wq->rcu, wq_free_rcu); | 281 | wq = rcu_dereference_protected(ei->socket.wq, 1); |
282 | call_rcu(&wq->rcu, wq_free_rcu); | ||
279 | kmem_cache_free(sock_inode_cachep, ei); | 283 | kmem_cache_free(sock_inode_cachep, ei); |
280 | } | 284 | } |
281 | 285 | ||
@@ -524,7 +528,7 @@ void sock_release(struct socket *sock) | |||
524 | module_put(owner); | 528 | module_put(owner); |
525 | } | 529 | } |
526 | 530 | ||
527 | if (sock->wq->fasync_list) | 531 | if (rcu_dereference_protected(sock->wq, 1)->fasync_list) |
528 | printk(KERN_ERR "sock_release: fasync list not empty!\n"); | 532 | printk(KERN_ERR "sock_release: fasync list not empty!\n"); |
529 | 533 | ||
530 | percpu_sub(sockets_in_use, 1); | 534 | percpu_sub(sockets_in_use, 1); |
@@ -1108,15 +1112,16 @@ static int sock_fasync(int fd, struct file *filp, int on) | |||
1108 | { | 1112 | { |
1109 | struct socket *sock = filp->private_data; | 1113 | struct socket *sock = filp->private_data; |
1110 | struct sock *sk = sock->sk; | 1114 | struct sock *sk = sock->sk; |
1115 | struct socket_wq *wq; | ||
1111 | 1116 | ||
1112 | if (sk == NULL) | 1117 | if (sk == NULL) |
1113 | return -EINVAL; | 1118 | return -EINVAL; |
1114 | 1119 | ||
1115 | lock_sock(sk); | 1120 | lock_sock(sk); |
1121 | wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk)); | ||
1122 | fasync_helper(fd, filp, on, &wq->fasync_list); | ||
1116 | 1123 | ||
1117 | fasync_helper(fd, filp, on, &sock->wq->fasync_list); | 1124 | if (!wq->fasync_list) |
1118 | |||
1119 | if (!sock->wq->fasync_list) | ||
1120 | sock_reset_flag(sk, SOCK_FASYNC); | 1125 | sock_reset_flag(sk, SOCK_FASYNC); |
1121 | else | 1126 | else |
1122 | sock_set_flag(sk, SOCK_FASYNC); | 1127 | sock_set_flag(sk, SOCK_FASYNC); |