diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 132 |
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 | |||
274 | static 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 | |||
267 | static void sock_destroy_inode(struct inode *inode) | 281 | static 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 | ||
273 | static void init_once(void *foo) | 290 | static 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 | ||
659 | void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, | 677 | void __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 | } |
665 | EXPORT_SYMBOL_GPL(sock_recv_ts_and_drops); | 683 | EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops); |
666 | 684 | ||
667 | static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock, | 685 | static 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 | ||
1078 | static int sock_fasync(int fd, struct file *filp, int on) | 1096 | static 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 | ||
1141 | out: | 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 | ||
1148 | int sock_wake_async(struct socket *sock, int how, int band) | 1119 | int 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: |
1162 | call_kill: | 1141 | call_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 | ||
2648 | static int siocdevprivate_ioctl(struct net *net, unsigned int cmd, | 2628 | static int siocdevprivate_ioctl(struct net *net, unsigned int cmd, |
@@ -3096,6 +3076,8 @@ int kernel_setsockopt(struct socket *sock, int level, int optname, | |||
3096 | int kernel_sendpage(struct socket *sock, struct page *page, int offset, | 3076 | int 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 | ||