aboutsummaryrefslogtreecommitdiffstats
path: root/net/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c132
1 files changed, 57 insertions, 75 deletions
diff --git a/net/socket.c b/net/socket.c
index 5e8d0af3c0e7..367d5477d00f 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -94,6 +94,7 @@
94 94
95#include <net/compat.h> 95#include <net/compat.h>
96#include <net/wext.h> 96#include <net/wext.h>
97#include <net/cls_cgroup.h>
97 98
98#include <net/sock.h> 99#include <net/sock.h>
99#include <linux/netfilter.h> 100#include <linux/netfilter.h>
@@ -252,9 +253,14 @@ static struct inode *sock_alloc_inode(struct super_block *sb)
252 ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL); 253 ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
253 if (!ei) 254 if (!ei)
254 return NULL; 255 return NULL;
255 init_waitqueue_head(&ei->socket.wait); 256 ei->socket.wq = kmalloc(sizeof(struct socket_wq), GFP_KERNEL);
257 if (!ei->socket.wq) {
258 kmem_cache_free(sock_inode_cachep, ei);
259 return NULL;
260 }
261 init_waitqueue_head(&ei->socket.wq->wait);
262 ei->socket.wq->fasync_list = NULL;
256 263
257 ei->socket.fasync_list = NULL;
258 ei->socket.state = SS_UNCONNECTED; 264 ei->socket.state = SS_UNCONNECTED;
259 ei->socket.flags = 0; 265 ei->socket.flags = 0;
260 ei->socket.ops = NULL; 266 ei->socket.ops = NULL;
@@ -264,10 +270,21 @@ static struct inode *sock_alloc_inode(struct super_block *sb)
264 return &ei->vfs_inode; 270 return &ei->vfs_inode;
265} 271}
266 272
273
274static void wq_free_rcu(struct rcu_head *head)
275{
276 struct socket_wq *wq = container_of(head, struct socket_wq, rcu);
277
278 kfree(wq);
279}
280
267static void sock_destroy_inode(struct inode *inode) 281static void sock_destroy_inode(struct inode *inode)
268{ 282{
269 kmem_cache_free(sock_inode_cachep, 283 struct socket_alloc *ei;
270 container_of(inode, struct socket_alloc, vfs_inode)); 284
285 ei = container_of(inode, struct socket_alloc, vfs_inode);
286 call_rcu(&ei->socket.wq->rcu, wq_free_rcu);
287 kmem_cache_free(sock_inode_cachep, ei);
271} 288}
272 289
273static void init_once(void *foo) 290static void init_once(void *foo)
@@ -513,7 +530,7 @@ void sock_release(struct socket *sock)
513 module_put(owner); 530 module_put(owner);
514 } 531 }
515 532
516 if (sock->fasync_list) 533 if (sock->wq->fasync_list)
517 printk(KERN_ERR "sock_release: fasync list not empty!\n"); 534 printk(KERN_ERR "sock_release: fasync list not empty!\n");
518 535
519 percpu_sub(sockets_in_use, 1); 536 percpu_sub(sockets_in_use, 1);
@@ -542,6 +559,8 @@ static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
542 struct sock_iocb *si = kiocb_to_siocb(iocb); 559 struct sock_iocb *si = kiocb_to_siocb(iocb);
543 int err; 560 int err;
544 561
562 sock_update_classid(sock->sk);
563
545 si->sock = sock; 564 si->sock = sock;
546 si->scm = NULL; 565 si->scm = NULL;
547 si->msg = msg; 566 si->msg = msg;
@@ -620,10 +639,9 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
620 put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, 639 put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
621 sizeof(tv), &tv); 640 sizeof(tv), &tv);
622 } else { 641 } else {
623 struct timespec ts; 642 skb_get_timestampns(skb, &ts[0]);
624 skb_get_timestampns(skb, &ts);
625 put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, 643 put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
626 sizeof(ts), &ts); 644 sizeof(ts[0]), &ts[0]);
627 } 645 }
628 } 646 }
629 647
@@ -656,19 +674,21 @@ inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, struct sk_buff
656 sizeof(__u32), &skb->dropcount); 674 sizeof(__u32), &skb->dropcount);
657} 675}
658 676
659void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, 677void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
660 struct sk_buff *skb) 678 struct sk_buff *skb)
661{ 679{
662 sock_recv_timestamp(msg, sk, skb); 680 sock_recv_timestamp(msg, sk, skb);
663 sock_recv_drops(msg, sk, skb); 681 sock_recv_drops(msg, sk, skb);
664} 682}
665EXPORT_SYMBOL_GPL(sock_recv_ts_and_drops); 683EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
666 684
667static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock, 685static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
668 struct msghdr *msg, size_t size, int flags) 686 struct msghdr *msg, size_t size, int flags)
669{ 687{
670 struct sock_iocb *si = kiocb_to_siocb(iocb); 688 struct sock_iocb *si = kiocb_to_siocb(iocb);
671 689
690 sock_update_classid(sock->sk);
691
672 si->sock = sock; 692 si->sock = sock;
673 si->scm = NULL; 693 si->scm = NULL;
674 si->msg = msg; 694 si->msg = msg;
@@ -762,6 +782,8 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
762 if (unlikely(!sock->ops->splice_read)) 782 if (unlikely(!sock->ops->splice_read))
763 return -EINVAL; 783 return -EINVAL;
764 784
785 sock_update_classid(sock->sk);
786
765 return sock->ops->splice_read(sock, ppos, pipe, len, flags); 787 return sock->ops->splice_read(sock, ppos, pipe, len, flags);
766} 788}
767 789
@@ -1068,87 +1090,44 @@ static int sock_close(struct inode *inode, struct file *filp)
1068 * 1. fasync_list is modified only under process context socket lock 1090 * 1. fasync_list is modified only under process context socket lock
1069 * i.e. under semaphore. 1091 * i.e. under semaphore.
1070 * 2. fasync_list is used under read_lock(&sk->sk_callback_lock) 1092 * 2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1071 * or under socket lock. 1093 * or under socket lock
1072 * 3. fasync_list can be used from softirq context, so that
1073 * modification under socket lock have to be enhanced with
1074 * write_lock_bh(&sk->sk_callback_lock).
1075 * --ANK (990710)
1076 */ 1094 */
1077 1095
1078static int sock_fasync(int fd, struct file *filp, int on) 1096static int sock_fasync(int fd, struct file *filp, int on)
1079{ 1097{
1080 struct fasync_struct *fa, *fna = NULL, **prev; 1098 struct socket *sock = filp->private_data;
1081 struct socket *sock; 1099 struct sock *sk = sock->sk;
1082 struct sock *sk;
1083
1084 if (on) {
1085 fna = kmalloc(sizeof(struct fasync_struct), GFP_KERNEL);
1086 if (fna == NULL)
1087 return -ENOMEM;
1088 }
1089
1090 sock = filp->private_data;
1091 1100
1092 sk = sock->sk; 1101 if (sk == NULL)
1093 if (sk == NULL) {
1094 kfree(fna);
1095 return -EINVAL; 1102 return -EINVAL;
1096 }
1097 1103
1098 lock_sock(sk); 1104 lock_sock(sk);
1099 1105
1100 spin_lock(&filp->f_lock); 1106 fasync_helper(fd, filp, on, &sock->wq->fasync_list);
1101 if (on)
1102 filp->f_flags |= FASYNC;
1103 else
1104 filp->f_flags &= ~FASYNC;
1105 spin_unlock(&filp->f_lock);
1106
1107 prev = &(sock->fasync_list);
1108
1109 for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev)
1110 if (fa->fa_file == filp)
1111 break;
1112
1113 if (on) {
1114 if (fa != NULL) {
1115 write_lock_bh(&sk->sk_callback_lock);
1116 fa->fa_fd = fd;
1117 write_unlock_bh(&sk->sk_callback_lock);
1118 1107
1119 kfree(fna); 1108 if (!sock->wq->fasync_list)
1120 goto out; 1109 sock_reset_flag(sk, SOCK_FASYNC);
1121 } 1110 else
1122 fna->fa_file = filp;
1123 fna->fa_fd = fd;
1124 fna->magic = FASYNC_MAGIC;
1125 fna->fa_next = sock->fasync_list;
1126 write_lock_bh(&sk->sk_callback_lock);
1127 sock->fasync_list = fna;
1128 sock_set_flag(sk, SOCK_FASYNC); 1111 sock_set_flag(sk, SOCK_FASYNC);
1129 write_unlock_bh(&sk->sk_callback_lock);
1130 } else {
1131 if (fa != NULL) {
1132 write_lock_bh(&sk->sk_callback_lock);
1133 *prev = fa->fa_next;
1134 if (!sock->fasync_list)
1135 sock_reset_flag(sk, SOCK_FASYNC);
1136 write_unlock_bh(&sk->sk_callback_lock);
1137 kfree(fa);
1138 }
1139 }
1140 1112
1141out: 1113 release_sock(sk);
1142 release_sock(sock->sk);
1143 return 0; 1114 return 0;
1144} 1115}
1145 1116
1146/* This function may be called only under socket lock or callback_lock */ 1117/* This function may be called only under socket lock or callback_lock or rcu_lock */
1147 1118
1148int sock_wake_async(struct socket *sock, int how, int band) 1119int sock_wake_async(struct socket *sock, int how, int band)
1149{ 1120{
1150 if (!sock || !sock->fasync_list) 1121 struct socket_wq *wq;
1122
1123 if (!sock)
1124 return -1;
1125 rcu_read_lock();
1126 wq = rcu_dereference(sock->wq);
1127 if (!wq || !wq->fasync_list) {
1128 rcu_read_unlock();
1151 return -1; 1129 return -1;
1130 }
1152 switch (how) { 1131 switch (how) {
1153 case SOCK_WAKE_WAITD: 1132 case SOCK_WAKE_WAITD:
1154 if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) 1133 if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
@@ -1160,11 +1139,12 @@ int sock_wake_async(struct socket *sock, int how, int band)
1160 /* fall through */ 1139 /* fall through */
1161 case SOCK_WAKE_IO: 1140 case SOCK_WAKE_IO:
1162call_kill: 1141call_kill:
1163 __kill_fasync(sock->fasync_list, SIGIO, band); 1142 kill_fasync(&wq->fasync_list, SIGIO, band);
1164 break; 1143 break;
1165 case SOCK_WAKE_URG: 1144 case SOCK_WAKE_URG:
1166 __kill_fasync(sock->fasync_list, SIGURG, band); 1145 kill_fasync(&wq->fasync_list, SIGURG, band);
1167 } 1146 }
1147 rcu_read_unlock();
1168 return 0; 1148 return 0;
1169} 1149}
1170 1150
@@ -2642,7 +2622,7 @@ static int bond_ioctl(struct net *net, unsigned int cmd,
2642 return dev_ioctl(net, cmd, uifr); 2622 return dev_ioctl(net, cmd, uifr);
2643 default: 2623 default:
2644 return -EINVAL; 2624 return -EINVAL;
2645 }; 2625 }
2646} 2626}
2647 2627
2648static int siocdevprivate_ioctl(struct net *net, unsigned int cmd, 2628static int siocdevprivate_ioctl(struct net *net, unsigned int cmd,
@@ -3096,6 +3076,8 @@ int kernel_setsockopt(struct socket *sock, int level, int optname,
3096int kernel_sendpage(struct socket *sock, struct page *page, int offset, 3076int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3097 size_t size, int flags) 3077 size_t size, int flags)
3098{ 3078{
3079 sock_update_classid(sock->sk);
3080
3099 if (sock->ops->sendpage) 3081 if (sock->ops->sendpage)
3100 return sock->ops->sendpage(sock, page, offset, size, flags); 3082 return sock->ops->sendpage(sock, page, offset, size, flags);
3101 3083