diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-12-31 02:31:57 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-12-31 02:31:57 -0500 |
commit | a9de18eb761f7c1c860964b2e5addc1a35c7e861 (patch) | |
tree | 886e75fdfd09690cd262ca69cb7f5d1d42b48602 /net/unix | |
parent | b2aaf8f74cdc84a9182f6cabf198b7763bcb9d40 (diff) | |
parent | 6a94cb73064c952255336cc57731904174b2c58f (diff) |
Merge branch 'linus' into stackprotector
Conflicts:
arch/x86/include/asm/pda.h
kernel/fork.c
Diffstat (limited to 'net/unix')
-rw-r--r-- | net/unix/af_unix.c | 264 | ||||
-rw-r--r-- | net/unix/garbage.c | 74 | ||||
-rw-r--r-- | net/unix/sysctl_net_unix.c | 3 |
3 files changed, 196 insertions, 145 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index c647aab8d418..c6250d0055d2 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -164,7 +164,7 @@ static inline int unix_our_peer(struct sock *sk, struct sock *osk) | |||
164 | 164 | ||
165 | static inline int unix_may_send(struct sock *sk, struct sock *osk) | 165 | static inline int unix_may_send(struct sock *sk, struct sock *osk) |
166 | { | 166 | { |
167 | return (unix_peer(osk) == NULL || unix_our_peer(sk, osk)); | 167 | return unix_peer(osk) == NULL || unix_our_peer(sk, osk); |
168 | } | 168 | } |
169 | 169 | ||
170 | static inline int unix_recvq_full(struct sock const *sk) | 170 | static inline int unix_recvq_full(struct sock const *sk) |
@@ -197,7 +197,7 @@ static inline void unix_release_addr(struct unix_address *addr) | |||
197 | * - if started by zero, it is abstract name. | 197 | * - if started by zero, it is abstract name. |
198 | */ | 198 | */ |
199 | 199 | ||
200 | static int unix_mkname(struct sockaddr_un * sunaddr, int len, unsigned *hashp) | 200 | static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned *hashp) |
201 | { | 201 | { |
202 | if (len <= sizeof(short) || len > sizeof(*sunaddr)) | 202 | if (len <= sizeof(short) || len > sizeof(*sunaddr)) |
203 | return -EINVAL; | 203 | return -EINVAL; |
@@ -211,12 +211,12 @@ static int unix_mkname(struct sockaddr_un * sunaddr, int len, unsigned *hashp) | |||
211 | * we are guaranteed that it is a valid memory location in our | 211 | * we are guaranteed that it is a valid memory location in our |
212 | * kernel address buffer. | 212 | * kernel address buffer. |
213 | */ | 213 | */ |
214 | ((char *)sunaddr)[len]=0; | 214 | ((char *)sunaddr)[len] = 0; |
215 | len = strlen(sunaddr->sun_path)+1+sizeof(short); | 215 | len = strlen(sunaddr->sun_path)+1+sizeof(short); |
216 | return len; | 216 | return len; |
217 | } | 217 | } |
218 | 218 | ||
219 | *hashp = unix_hash_fold(csum_partial((char*)sunaddr, len, 0)); | 219 | *hashp = unix_hash_fold(csum_partial(sunaddr, len, 0)); |
220 | return len; | 220 | return len; |
221 | } | 221 | } |
222 | 222 | ||
@@ -295,8 +295,7 @@ static struct sock *unix_find_socket_byinode(struct net *net, struct inode *i) | |||
295 | if (!net_eq(sock_net(s), net)) | 295 | if (!net_eq(sock_net(s), net)) |
296 | continue; | 296 | continue; |
297 | 297 | ||
298 | if(dentry && dentry->d_inode == i) | 298 | if (dentry && dentry->d_inode == i) { |
299 | { | ||
300 | sock_hold(s); | 299 | sock_hold(s); |
301 | goto found; | 300 | goto found; |
302 | } | 301 | } |
@@ -354,7 +353,7 @@ static void unix_sock_destructor(struct sock *sk) | |||
354 | WARN_ON(!sk_unhashed(sk)); | 353 | WARN_ON(!sk_unhashed(sk)); |
355 | WARN_ON(sk->sk_socket); | 354 | WARN_ON(sk->sk_socket); |
356 | if (!sock_flag(sk, SOCK_DEAD)) { | 355 | if (!sock_flag(sk, SOCK_DEAD)) { |
357 | printk("Attempt to release alive unix socket: %p\n", sk); | 356 | printk(KERN_INFO "Attempt to release alive unix socket: %p\n", sk); |
358 | return; | 357 | return; |
359 | } | 358 | } |
360 | 359 | ||
@@ -362,12 +361,16 @@ static void unix_sock_destructor(struct sock *sk) | |||
362 | unix_release_addr(u->addr); | 361 | unix_release_addr(u->addr); |
363 | 362 | ||
364 | atomic_dec(&unix_nr_socks); | 363 | atomic_dec(&unix_nr_socks); |
364 | local_bh_disable(); | ||
365 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); | ||
366 | local_bh_enable(); | ||
365 | #ifdef UNIX_REFCNT_DEBUG | 367 | #ifdef UNIX_REFCNT_DEBUG |
366 | printk(KERN_DEBUG "UNIX %p is destroyed, %d are still alive.\n", sk, atomic_read(&unix_nr_socks)); | 368 | printk(KERN_DEBUG "UNIX %p is destroyed, %d are still alive.\n", sk, |
369 | atomic_read(&unix_nr_socks)); | ||
367 | #endif | 370 | #endif |
368 | } | 371 | } |
369 | 372 | ||
370 | static int unix_release_sock (struct sock *sk, int embrion) | 373 | static int unix_release_sock(struct sock *sk, int embrion) |
371 | { | 374 | { |
372 | struct unix_sock *u = unix_sk(sk); | 375 | struct unix_sock *u = unix_sk(sk); |
373 | struct dentry *dentry; | 376 | struct dentry *dentry; |
@@ -392,9 +395,9 @@ static int unix_release_sock (struct sock *sk, int embrion) | |||
392 | 395 | ||
393 | wake_up_interruptible_all(&u->peer_wait); | 396 | wake_up_interruptible_all(&u->peer_wait); |
394 | 397 | ||
395 | skpair=unix_peer(sk); | 398 | skpair = unix_peer(sk); |
396 | 399 | ||
397 | if (skpair!=NULL) { | 400 | if (skpair != NULL) { |
398 | if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) { | 401 | if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) { |
399 | unix_state_lock(skpair); | 402 | unix_state_lock(skpair); |
400 | /* No more writes */ | 403 | /* No more writes */ |
@@ -414,7 +417,7 @@ static int unix_release_sock (struct sock *sk, int embrion) | |||
414 | /* Try to flush out this socket. Throw out buffers at least */ | 417 | /* Try to flush out this socket. Throw out buffers at least */ |
415 | 418 | ||
416 | while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { | 419 | while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { |
417 | if (state==TCP_LISTEN) | 420 | if (state == TCP_LISTEN) |
418 | unix_release_sock(skb->sk, 1); | 421 | unix_release_sock(skb->sk, 1); |
419 | /* passed fds are erased in the kfree_skb hook */ | 422 | /* passed fds are erased in the kfree_skb hook */ |
420 | kfree_skb(skb); | 423 | kfree_skb(skb); |
@@ -453,11 +456,11 @@ static int unix_listen(struct socket *sock, int backlog) | |||
453 | struct unix_sock *u = unix_sk(sk); | 456 | struct unix_sock *u = unix_sk(sk); |
454 | 457 | ||
455 | err = -EOPNOTSUPP; | 458 | err = -EOPNOTSUPP; |
456 | if (sock->type!=SOCK_STREAM && sock->type!=SOCK_SEQPACKET) | 459 | if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET) |
457 | goto out; /* Only stream/seqpacket sockets accept */ | 460 | goto out; /* Only stream/seqpacket sockets accept */ |
458 | err = -EINVAL; | 461 | err = -EINVAL; |
459 | if (!u->addr) | 462 | if (!u->addr) |
460 | goto out; /* No listens on an unbound socket */ | 463 | goto out; /* No listens on an unbound socket */ |
461 | unix_state_lock(sk); | 464 | unix_state_lock(sk); |
462 | if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN) | 465 | if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN) |
463 | goto out_unlock; | 466 | goto out_unlock; |
@@ -467,8 +470,7 @@ static int unix_listen(struct socket *sock, int backlog) | |||
467 | sk->sk_state = TCP_LISTEN; | 470 | sk->sk_state = TCP_LISTEN; |
468 | /* set credentials so connect can copy them */ | 471 | /* set credentials so connect can copy them */ |
469 | sk->sk_peercred.pid = task_tgid_vnr(current); | 472 | sk->sk_peercred.pid = task_tgid_vnr(current); |
470 | sk->sk_peercred.uid = current->euid; | 473 | current_euid_egid(&sk->sk_peercred.uid, &sk->sk_peercred.gid); |
471 | sk->sk_peercred.gid = current->egid; | ||
472 | err = 0; | 474 | err = 0; |
473 | 475 | ||
474 | out_unlock: | 476 | out_unlock: |
@@ -566,9 +568,9 @@ static const struct proto_ops unix_seqpacket_ops = { | |||
566 | }; | 568 | }; |
567 | 569 | ||
568 | static struct proto unix_proto = { | 570 | static struct proto unix_proto = { |
569 | .name = "UNIX", | 571 | .name = "UNIX", |
570 | .owner = THIS_MODULE, | 572 | .owner = THIS_MODULE, |
571 | .obj_size = sizeof(struct unix_sock), | 573 | .obj_size = sizeof(struct unix_sock), |
572 | }; | 574 | }; |
573 | 575 | ||
574 | /* | 576 | /* |
@@ -579,7 +581,7 @@ static struct proto unix_proto = { | |||
579 | */ | 581 | */ |
580 | static struct lock_class_key af_unix_sk_receive_queue_lock_key; | 582 | static struct lock_class_key af_unix_sk_receive_queue_lock_key; |
581 | 583 | ||
582 | static struct sock * unix_create1(struct net *net, struct socket *sock) | 584 | static struct sock *unix_create1(struct net *net, struct socket *sock) |
583 | { | 585 | { |
584 | struct sock *sk = NULL; | 586 | struct sock *sk = NULL; |
585 | struct unix_sock *u; | 587 | struct unix_sock *u; |
@@ -592,7 +594,7 @@ static struct sock * unix_create1(struct net *net, struct socket *sock) | |||
592 | if (!sk) | 594 | if (!sk) |
593 | goto out; | 595 | goto out; |
594 | 596 | ||
595 | sock_init_data(sock,sk); | 597 | sock_init_data(sock, sk); |
596 | lockdep_set_class(&sk->sk_receive_queue.lock, | 598 | lockdep_set_class(&sk->sk_receive_queue.lock, |
597 | &af_unix_sk_receive_queue_lock_key); | 599 | &af_unix_sk_receive_queue_lock_key); |
598 | 600 | ||
@@ -611,6 +613,11 @@ static struct sock * unix_create1(struct net *net, struct socket *sock) | |||
611 | out: | 613 | out: |
612 | if (sk == NULL) | 614 | if (sk == NULL) |
613 | atomic_dec(&unix_nr_socks); | 615 | atomic_dec(&unix_nr_socks); |
616 | else { | ||
617 | local_bh_disable(); | ||
618 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); | ||
619 | local_bh_enable(); | ||
620 | } | ||
614 | return sk; | 621 | return sk; |
615 | } | 622 | } |
616 | 623 | ||
@@ -630,7 +637,7 @@ static int unix_create(struct net *net, struct socket *sock, int protocol) | |||
630 | * nothing uses it. | 637 | * nothing uses it. |
631 | */ | 638 | */ |
632 | case SOCK_RAW: | 639 | case SOCK_RAW: |
633 | sock->type=SOCK_DGRAM; | 640 | sock->type = SOCK_DGRAM; |
634 | case SOCK_DGRAM: | 641 | case SOCK_DGRAM: |
635 | sock->ops = &unix_dgram_ops; | 642 | sock->ops = &unix_dgram_ops; |
636 | break; | 643 | break; |
@@ -653,7 +660,7 @@ static int unix_release(struct socket *sock) | |||
653 | 660 | ||
654 | sock->sk = NULL; | 661 | sock->sk = NULL; |
655 | 662 | ||
656 | return unix_release_sock (sk, 0); | 663 | return unix_release_sock(sk, 0); |
657 | } | 664 | } |
658 | 665 | ||
659 | static int unix_autobind(struct socket *sock) | 666 | static int unix_autobind(struct socket *sock) |
@@ -662,7 +669,7 @@ static int unix_autobind(struct socket *sock) | |||
662 | struct net *net = sock_net(sk); | 669 | struct net *net = sock_net(sk); |
663 | struct unix_sock *u = unix_sk(sk); | 670 | struct unix_sock *u = unix_sk(sk); |
664 | static u32 ordernum = 1; | 671 | static u32 ordernum = 1; |
665 | struct unix_address * addr; | 672 | struct unix_address *addr; |
666 | int err; | 673 | int err; |
667 | 674 | ||
668 | mutex_lock(&u->readlock); | 675 | mutex_lock(&u->readlock); |
@@ -681,7 +688,7 @@ static int unix_autobind(struct socket *sock) | |||
681 | 688 | ||
682 | retry: | 689 | retry: |
683 | addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short); | 690 | addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short); |
684 | addr->hash = unix_hash_fold(csum_partial((void*)addr->name, addr->len, 0)); | 691 | addr->hash = unix_hash_fold(csum_partial(addr->name, addr->len, 0)); |
685 | 692 | ||
686 | spin_lock(&unix_table_lock); | 693 | spin_lock(&unix_table_lock); |
687 | ordernum = (ordernum+1)&0xFFFFF; | 694 | ordernum = (ordernum+1)&0xFFFFF; |
@@ -711,37 +718,39 @@ static struct sock *unix_find_other(struct net *net, | |||
711 | int type, unsigned hash, int *error) | 718 | int type, unsigned hash, int *error) |
712 | { | 719 | { |
713 | struct sock *u; | 720 | struct sock *u; |
714 | struct nameidata nd; | 721 | struct path path; |
715 | int err = 0; | 722 | int err = 0; |
716 | 723 | ||
717 | if (sunname->sun_path[0]) { | 724 | if (sunname->sun_path[0]) { |
718 | err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd); | 725 | struct inode *inode; |
726 | err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path); | ||
719 | if (err) | 727 | if (err) |
720 | goto fail; | 728 | goto fail; |
721 | err = vfs_permission(&nd, MAY_WRITE); | 729 | inode = path.dentry->d_inode; |
730 | err = inode_permission(inode, MAY_WRITE); | ||
722 | if (err) | 731 | if (err) |
723 | goto put_fail; | 732 | goto put_fail; |
724 | 733 | ||
725 | err = -ECONNREFUSED; | 734 | err = -ECONNREFUSED; |
726 | if (!S_ISSOCK(nd.path.dentry->d_inode->i_mode)) | 735 | if (!S_ISSOCK(inode->i_mode)) |
727 | goto put_fail; | 736 | goto put_fail; |
728 | u = unix_find_socket_byinode(net, nd.path.dentry->d_inode); | 737 | u = unix_find_socket_byinode(net, inode); |
729 | if (!u) | 738 | if (!u) |
730 | goto put_fail; | 739 | goto put_fail; |
731 | 740 | ||
732 | if (u->sk_type == type) | 741 | if (u->sk_type == type) |
733 | touch_atime(nd.path.mnt, nd.path.dentry); | 742 | touch_atime(path.mnt, path.dentry); |
734 | 743 | ||
735 | path_put(&nd.path); | 744 | path_put(&path); |
736 | 745 | ||
737 | err=-EPROTOTYPE; | 746 | err = -EPROTOTYPE; |
738 | if (u->sk_type != type) { | 747 | if (u->sk_type != type) { |
739 | sock_put(u); | 748 | sock_put(u); |
740 | goto fail; | 749 | goto fail; |
741 | } | 750 | } |
742 | } else { | 751 | } else { |
743 | err = -ECONNREFUSED; | 752 | err = -ECONNREFUSED; |
744 | u=unix_find_socket_byname(net, sunname, len, type, hash); | 753 | u = unix_find_socket_byname(net, sunname, len, type, hash); |
745 | if (u) { | 754 | if (u) { |
746 | struct dentry *dentry; | 755 | struct dentry *dentry; |
747 | dentry = unix_sk(u)->dentry; | 756 | dentry = unix_sk(u)->dentry; |
@@ -753,9 +762,9 @@ static struct sock *unix_find_other(struct net *net, | |||
753 | return u; | 762 | return u; |
754 | 763 | ||
755 | put_fail: | 764 | put_fail: |
756 | path_put(&nd.path); | 765 | path_put(&path); |
757 | fail: | 766 | fail: |
758 | *error=err; | 767 | *error = err; |
759 | return NULL; | 768 | return NULL; |
760 | } | 769 | } |
761 | 770 | ||
@@ -765,8 +774,8 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
765 | struct sock *sk = sock->sk; | 774 | struct sock *sk = sock->sk; |
766 | struct net *net = sock_net(sk); | 775 | struct net *net = sock_net(sk); |
767 | struct unix_sock *u = unix_sk(sk); | 776 | struct unix_sock *u = unix_sk(sk); |
768 | struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr; | 777 | struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; |
769 | struct dentry * dentry = NULL; | 778 | struct dentry *dentry = NULL; |
770 | struct nameidata nd; | 779 | struct nameidata nd; |
771 | int err; | 780 | int err; |
772 | unsigned hash; | 781 | unsigned hash; |
@@ -777,7 +786,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
777 | if (sunaddr->sun_family != AF_UNIX) | 786 | if (sunaddr->sun_family != AF_UNIX) |
778 | goto out; | 787 | goto out; |
779 | 788 | ||
780 | if (addr_len==sizeof(short)) { | 789 | if (addr_len == sizeof(short)) { |
781 | err = unix_autobind(sock); | 790 | err = unix_autobind(sock); |
782 | goto out; | 791 | goto out; |
783 | } | 792 | } |
@@ -873,8 +882,8 @@ out_mknod_unlock: | |||
873 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 882 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
874 | path_put(&nd.path); | 883 | path_put(&nd.path); |
875 | out_mknod_parent: | 884 | out_mknod_parent: |
876 | if (err==-EEXIST) | 885 | if (err == -EEXIST) |
877 | err=-EADDRINUSE; | 886 | err = -EADDRINUSE; |
878 | unix_release_addr(addr); | 887 | unix_release_addr(addr); |
879 | goto out_up; | 888 | goto out_up; |
880 | } | 889 | } |
@@ -909,7 +918,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, | |||
909 | { | 918 | { |
910 | struct sock *sk = sock->sk; | 919 | struct sock *sk = sock->sk; |
911 | struct net *net = sock_net(sk); | 920 | struct net *net = sock_net(sk); |
912 | struct sockaddr_un *sunaddr=(struct sockaddr_un*)addr; | 921 | struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr; |
913 | struct sock *other; | 922 | struct sock *other; |
914 | unsigned hash; | 923 | unsigned hash; |
915 | int err; | 924 | int err; |
@@ -925,7 +934,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, | |||
925 | goto out; | 934 | goto out; |
926 | 935 | ||
927 | restart: | 936 | restart: |
928 | other=unix_find_other(net, sunaddr, alen, sock->type, hash, &err); | 937 | other = unix_find_other(net, sunaddr, alen, sock->type, hash, &err); |
929 | if (!other) | 938 | if (!other) |
930 | goto out; | 939 | goto out; |
931 | 940 | ||
@@ -959,14 +968,14 @@ restart: | |||
959 | */ | 968 | */ |
960 | if (unix_peer(sk)) { | 969 | if (unix_peer(sk)) { |
961 | struct sock *old_peer = unix_peer(sk); | 970 | struct sock *old_peer = unix_peer(sk); |
962 | unix_peer(sk)=other; | 971 | unix_peer(sk) = other; |
963 | unix_state_double_unlock(sk, other); | 972 | unix_state_double_unlock(sk, other); |
964 | 973 | ||
965 | if (other != old_peer) | 974 | if (other != old_peer) |
966 | unix_dgram_disconnected(sk, old_peer); | 975 | unix_dgram_disconnected(sk, old_peer); |
967 | sock_put(old_peer); | 976 | sock_put(old_peer); |
968 | } else { | 977 | } else { |
969 | unix_peer(sk)=other; | 978 | unix_peer(sk) = other; |
970 | unix_state_double_unlock(sk, other); | 979 | unix_state_double_unlock(sk, other); |
971 | } | 980 | } |
972 | return 0; | 981 | return 0; |
@@ -1002,7 +1011,7 @@ static long unix_wait_for_peer(struct sock *other, long timeo) | |||
1002 | static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, | 1011 | static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, |
1003 | int addr_len, int flags) | 1012 | int addr_len, int flags) |
1004 | { | 1013 | { |
1005 | struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr; | 1014 | struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; |
1006 | struct sock *sk = sock->sk; | 1015 | struct sock *sk = sock->sk; |
1007 | struct net *net = sock_net(sk); | 1016 | struct net *net = sock_net(sk); |
1008 | struct unix_sock *u = unix_sk(sk), *newu, *otheru; | 1017 | struct unix_sock *u = unix_sk(sk), *newu, *otheru; |
@@ -1124,8 +1133,7 @@ restart: | |||
1124 | newsk->sk_state = TCP_ESTABLISHED; | 1133 | newsk->sk_state = TCP_ESTABLISHED; |
1125 | newsk->sk_type = sk->sk_type; | 1134 | newsk->sk_type = sk->sk_type; |
1126 | newsk->sk_peercred.pid = task_tgid_vnr(current); | 1135 | newsk->sk_peercred.pid = task_tgid_vnr(current); |
1127 | newsk->sk_peercred.uid = current->euid; | 1136 | current_euid_egid(&newsk->sk_peercred.uid, &newsk->sk_peercred.gid); |
1128 | newsk->sk_peercred.gid = current->egid; | ||
1129 | newu = unix_sk(newsk); | 1137 | newu = unix_sk(newsk); |
1130 | newsk->sk_sleep = &newu->peer_wait; | 1138 | newsk->sk_sleep = &newu->peer_wait; |
1131 | otheru = unix_sk(other); | 1139 | otheru = unix_sk(other); |
@@ -1177,16 +1185,17 @@ out: | |||
1177 | 1185 | ||
1178 | static int unix_socketpair(struct socket *socka, struct socket *sockb) | 1186 | static int unix_socketpair(struct socket *socka, struct socket *sockb) |
1179 | { | 1187 | { |
1180 | struct sock *ska=socka->sk, *skb = sockb->sk; | 1188 | struct sock *ska = socka->sk, *skb = sockb->sk; |
1181 | 1189 | ||
1182 | /* Join our sockets back to back */ | 1190 | /* Join our sockets back to back */ |
1183 | sock_hold(ska); | 1191 | sock_hold(ska); |
1184 | sock_hold(skb); | 1192 | sock_hold(skb); |
1185 | unix_peer(ska)=skb; | 1193 | unix_peer(ska) = skb; |
1186 | unix_peer(skb)=ska; | 1194 | unix_peer(skb) = ska; |
1187 | ska->sk_peercred.pid = skb->sk_peercred.pid = task_tgid_vnr(current); | 1195 | ska->sk_peercred.pid = skb->sk_peercred.pid = task_tgid_vnr(current); |
1188 | ska->sk_peercred.uid = skb->sk_peercred.uid = current->euid; | 1196 | current_euid_egid(&skb->sk_peercred.uid, &skb->sk_peercred.gid); |
1189 | ska->sk_peercred.gid = skb->sk_peercred.gid = current->egid; | 1197 | ska->sk_peercred.uid = skb->sk_peercred.uid; |
1198 | ska->sk_peercred.gid = skb->sk_peercred.gid; | ||
1190 | 1199 | ||
1191 | if (ska->sk_type != SOCK_DGRAM) { | 1200 | if (ska->sk_type != SOCK_DGRAM) { |
1192 | ska->sk_state = TCP_ESTABLISHED; | 1201 | ska->sk_state = TCP_ESTABLISHED; |
@@ -1205,7 +1214,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags) | |||
1205 | int err; | 1214 | int err; |
1206 | 1215 | ||
1207 | err = -EOPNOTSUPP; | 1216 | err = -EOPNOTSUPP; |
1208 | if (sock->type!=SOCK_STREAM && sock->type!=SOCK_SEQPACKET) | 1217 | if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET) |
1209 | goto out; | 1218 | goto out; |
1210 | 1219 | ||
1211 | err = -EINVAL; | 1220 | err = -EINVAL; |
@@ -1244,7 +1253,7 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_ | |||
1244 | { | 1253 | { |
1245 | struct sock *sk = sock->sk; | 1254 | struct sock *sk = sock->sk; |
1246 | struct unix_sock *u; | 1255 | struct unix_sock *u; |
1247 | struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr; | 1256 | struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; |
1248 | int err = 0; | 1257 | int err = 0; |
1249 | 1258 | ||
1250 | if (peer) { | 1259 | if (peer) { |
@@ -1284,7 +1293,7 @@ static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb) | |||
1284 | skb->destructor = sock_wfree; | 1293 | skb->destructor = sock_wfree; |
1285 | UNIXCB(skb).fp = NULL; | 1294 | UNIXCB(skb).fp = NULL; |
1286 | 1295 | ||
1287 | for (i=scm->fp->count-1; i>=0; i--) | 1296 | for (i = scm->fp->count-1; i >= 0; i--) |
1288 | unix_notinflight(scm->fp->fp[i]); | 1297 | unix_notinflight(scm->fp->fp[i]); |
1289 | } | 1298 | } |
1290 | 1299 | ||
@@ -1300,14 +1309,23 @@ static void unix_destruct_fds(struct sk_buff *skb) | |||
1300 | sock_wfree(skb); | 1309 | sock_wfree(skb); |
1301 | } | 1310 | } |
1302 | 1311 | ||
1303 | static void unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) | 1312 | static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) |
1304 | { | 1313 | { |
1305 | int i; | 1314 | int i; |
1306 | for (i=scm->fp->count-1; i>=0; i--) | 1315 | |
1316 | /* | ||
1317 | * Need to duplicate file references for the sake of garbage | ||
1318 | * collection. Otherwise a socket in the fps might become a | ||
1319 | * candidate for GC while the skb is not yet queued. | ||
1320 | */ | ||
1321 | UNIXCB(skb).fp = scm_fp_dup(scm->fp); | ||
1322 | if (!UNIXCB(skb).fp) | ||
1323 | return -ENOMEM; | ||
1324 | |||
1325 | for (i = scm->fp->count-1; i >= 0; i--) | ||
1307 | unix_inflight(scm->fp->fp[i]); | 1326 | unix_inflight(scm->fp->fp[i]); |
1308 | UNIXCB(skb).fp = scm->fp; | ||
1309 | skb->destructor = unix_destruct_fds; | 1327 | skb->destructor = unix_destruct_fds; |
1310 | scm->fp = NULL; | 1328 | return 0; |
1311 | } | 1329 | } |
1312 | 1330 | ||
1313 | /* | 1331 | /* |
@@ -1321,7 +1339,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1321 | struct sock *sk = sock->sk; | 1339 | struct sock *sk = sock->sk; |
1322 | struct net *net = sock_net(sk); | 1340 | struct net *net = sock_net(sk); |
1323 | struct unix_sock *u = unix_sk(sk); | 1341 | struct unix_sock *u = unix_sk(sk); |
1324 | struct sockaddr_un *sunaddr=msg->msg_name; | 1342 | struct sockaddr_un *sunaddr = msg->msg_name; |
1325 | struct sock *other = NULL; | 1343 | struct sock *other = NULL; |
1326 | int namelen = 0; /* fake GCC */ | 1344 | int namelen = 0; /* fake GCC */ |
1327 | int err; | 1345 | int err; |
@@ -1332,6 +1350,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1332 | 1350 | ||
1333 | if (NULL == siocb->scm) | 1351 | if (NULL == siocb->scm) |
1334 | siocb->scm = &tmp_scm; | 1352 | siocb->scm = &tmp_scm; |
1353 | wait_for_unix_gc(); | ||
1335 | err = scm_send(sock, msg, siocb->scm); | 1354 | err = scm_send(sock, msg, siocb->scm); |
1336 | if (err < 0) | 1355 | if (err < 0) |
1337 | return err; | 1356 | return err; |
@@ -1362,16 +1381,19 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1362 | goto out; | 1381 | goto out; |
1363 | 1382 | ||
1364 | skb = sock_alloc_send_skb(sk, len, msg->msg_flags&MSG_DONTWAIT, &err); | 1383 | skb = sock_alloc_send_skb(sk, len, msg->msg_flags&MSG_DONTWAIT, &err); |
1365 | if (skb==NULL) | 1384 | if (skb == NULL) |
1366 | goto out; | 1385 | goto out; |
1367 | 1386 | ||
1368 | memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); | 1387 | memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); |
1369 | if (siocb->scm->fp) | 1388 | if (siocb->scm->fp) { |
1370 | unix_attach_fds(siocb->scm, skb); | 1389 | err = unix_attach_fds(siocb->scm, skb); |
1390 | if (err) | ||
1391 | goto out_free; | ||
1392 | } | ||
1371 | unix_get_secdata(siocb->scm, skb); | 1393 | unix_get_secdata(siocb->scm, skb); |
1372 | 1394 | ||
1373 | skb_reset_transport_header(skb); | 1395 | skb_reset_transport_header(skb); |
1374 | err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len); | 1396 | err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); |
1375 | if (err) | 1397 | if (err) |
1376 | goto out_free; | 1398 | goto out_free; |
1377 | 1399 | ||
@@ -1385,7 +1407,7 @@ restart: | |||
1385 | 1407 | ||
1386 | other = unix_find_other(net, sunaddr, namelen, sk->sk_type, | 1408 | other = unix_find_other(net, sunaddr, namelen, sk->sk_type, |
1387 | hash, &err); | 1409 | hash, &err); |
1388 | if (other==NULL) | 1410 | if (other == NULL) |
1389 | goto out_free; | 1411 | goto out_free; |
1390 | } | 1412 | } |
1391 | 1413 | ||
@@ -1405,7 +1427,7 @@ restart: | |||
1405 | err = 0; | 1427 | err = 0; |
1406 | unix_state_lock(sk); | 1428 | unix_state_lock(sk); |
1407 | if (unix_peer(sk) == other) { | 1429 | if (unix_peer(sk) == other) { |
1408 | unix_peer(sk)=NULL; | 1430 | unix_peer(sk) = NULL; |
1409 | unix_state_unlock(sk); | 1431 | unix_state_unlock(sk); |
1410 | 1432 | ||
1411 | unix_dgram_disconnected(sk, other); | 1433 | unix_dgram_disconnected(sk, other); |
@@ -1471,14 +1493,15 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1471 | struct sock_iocb *siocb = kiocb_to_siocb(kiocb); | 1493 | struct sock_iocb *siocb = kiocb_to_siocb(kiocb); |
1472 | struct sock *sk = sock->sk; | 1494 | struct sock *sk = sock->sk; |
1473 | struct sock *other = NULL; | 1495 | struct sock *other = NULL; |
1474 | struct sockaddr_un *sunaddr=msg->msg_name; | 1496 | struct sockaddr_un *sunaddr = msg->msg_name; |
1475 | int err,size; | 1497 | int err, size; |
1476 | struct sk_buff *skb; | 1498 | struct sk_buff *skb; |
1477 | int sent=0; | 1499 | int sent = 0; |
1478 | struct scm_cookie tmp_scm; | 1500 | struct scm_cookie tmp_scm; |
1479 | 1501 | ||
1480 | if (NULL == siocb->scm) | 1502 | if (NULL == siocb->scm) |
1481 | siocb->scm = &tmp_scm; | 1503 | siocb->scm = &tmp_scm; |
1504 | wait_for_unix_gc(); | ||
1482 | err = scm_send(sock, msg, siocb->scm); | 1505 | err = scm_send(sock, msg, siocb->scm); |
1483 | if (err < 0) | 1506 | if (err < 0) |
1484 | return err; | 1507 | return err; |
@@ -1501,8 +1524,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1501 | if (sk->sk_shutdown & SEND_SHUTDOWN) | 1524 | if (sk->sk_shutdown & SEND_SHUTDOWN) |
1502 | goto pipe_err; | 1525 | goto pipe_err; |
1503 | 1526 | ||
1504 | while(sent < len) | 1527 | while (sent < len) { |
1505 | { | ||
1506 | /* | 1528 | /* |
1507 | * Optimisation for the fact that under 0.01% of X | 1529 | * Optimisation for the fact that under 0.01% of X |
1508 | * messages typically need breaking up. | 1530 | * messages typically need breaking up. |
@@ -1521,9 +1543,10 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1521 | * Grab a buffer | 1543 | * Grab a buffer |
1522 | */ | 1544 | */ |
1523 | 1545 | ||
1524 | skb=sock_alloc_send_skb(sk,size,msg->msg_flags&MSG_DONTWAIT, &err); | 1546 | skb = sock_alloc_send_skb(sk, size, msg->msg_flags&MSG_DONTWAIT, |
1547 | &err); | ||
1525 | 1548 | ||
1526 | if (skb==NULL) | 1549 | if (skb == NULL) |
1527 | goto out_err; | 1550 | goto out_err; |
1528 | 1551 | ||
1529 | /* | 1552 | /* |
@@ -1536,10 +1559,16 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1536 | size = min_t(int, size, skb_tailroom(skb)); | 1559 | size = min_t(int, size, skb_tailroom(skb)); |
1537 | 1560 | ||
1538 | memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); | 1561 | memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); |
1539 | if (siocb->scm->fp) | 1562 | if (siocb->scm->fp) { |
1540 | unix_attach_fds(siocb->scm, skb); | 1563 | err = unix_attach_fds(siocb->scm, skb); |
1564 | if (err) { | ||
1565 | kfree_skb(skb); | ||
1566 | goto out_err; | ||
1567 | } | ||
1568 | } | ||
1541 | 1569 | ||
1542 | if ((err = memcpy_fromiovec(skb_put(skb,size), msg->msg_iov, size)) != 0) { | 1570 | err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); |
1571 | if (err) { | ||
1543 | kfree_skb(skb); | 1572 | kfree_skb(skb); |
1544 | goto out_err; | 1573 | goto out_err; |
1545 | } | 1574 | } |
@@ -1553,7 +1582,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1553 | skb_queue_tail(&other->sk_receive_queue, skb); | 1582 | skb_queue_tail(&other->sk_receive_queue, skb); |
1554 | unix_state_unlock(other); | 1583 | unix_state_unlock(other); |
1555 | other->sk_data_ready(other, size); | 1584 | other->sk_data_ready(other, size); |
1556 | sent+=size; | 1585 | sent += size; |
1557 | } | 1586 | } |
1558 | 1587 | ||
1559 | scm_destroy(siocb->scm); | 1588 | scm_destroy(siocb->scm); |
@@ -1565,8 +1594,8 @@ pipe_err_free: | |||
1565 | unix_state_unlock(other); | 1594 | unix_state_unlock(other); |
1566 | kfree_skb(skb); | 1595 | kfree_skb(skb); |
1567 | pipe_err: | 1596 | pipe_err: |
1568 | if (sent==0 && !(msg->msg_flags&MSG_NOSIGNAL)) | 1597 | if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL)) |
1569 | send_sig(SIGPIPE,current,0); | 1598 | send_sig(SIGPIPE, current, 0); |
1570 | err = -EPIPE; | 1599 | err = -EPIPE; |
1571 | out_err: | 1600 | out_err: |
1572 | scm_destroy(siocb->scm); | 1601 | scm_destroy(siocb->scm); |
@@ -1656,13 +1685,10 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1656 | siocb->scm->creds = *UNIXCREDS(skb); | 1685 | siocb->scm->creds = *UNIXCREDS(skb); |
1657 | unix_set_secdata(siocb->scm, skb); | 1686 | unix_set_secdata(siocb->scm, skb); |
1658 | 1687 | ||
1659 | if (!(flags & MSG_PEEK)) | 1688 | if (!(flags & MSG_PEEK)) { |
1660 | { | ||
1661 | if (UNIXCB(skb).fp) | 1689 | if (UNIXCB(skb).fp) |
1662 | unix_detach_fds(siocb->scm, skb); | 1690 | unix_detach_fds(siocb->scm, skb); |
1663 | } | 1691 | } else { |
1664 | else | ||
1665 | { | ||
1666 | /* It is questionable: on PEEK we could: | 1692 | /* It is questionable: on PEEK we could: |
1667 | - do not return fds - good, but too simple 8) | 1693 | - do not return fds - good, but too simple 8) |
1668 | - return fds, and do not return them on read (old strategy, | 1694 | - return fds, and do not return them on read (old strategy, |
@@ -1683,7 +1709,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1683 | scm_recv(sock, msg, siocb->scm, flags); | 1709 | scm_recv(sock, msg, siocb->scm, flags); |
1684 | 1710 | ||
1685 | out_free: | 1711 | out_free: |
1686 | skb_free_datagram(sk,skb); | 1712 | skb_free_datagram(sk, skb); |
1687 | out_unlock: | 1713 | out_unlock: |
1688 | mutex_unlock(&u->readlock); | 1714 | mutex_unlock(&u->readlock); |
1689 | out: | 1715 | out: |
@@ -1694,7 +1720,7 @@ out: | |||
1694 | * Sleep until data has arrive. But check for races.. | 1720 | * Sleep until data has arrive. But check for races.. |
1695 | */ | 1721 | */ |
1696 | 1722 | ||
1697 | static long unix_stream_data_wait(struct sock * sk, long timeo) | 1723 | static long unix_stream_data_wait(struct sock *sk, long timeo) |
1698 | { | 1724 | { |
1699 | DEFINE_WAIT(wait); | 1725 | DEFINE_WAIT(wait); |
1700 | 1726 | ||
@@ -1732,7 +1758,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1732 | struct scm_cookie tmp_scm; | 1758 | struct scm_cookie tmp_scm; |
1733 | struct sock *sk = sock->sk; | 1759 | struct sock *sk = sock->sk; |
1734 | struct unix_sock *u = unix_sk(sk); | 1760 | struct unix_sock *u = unix_sk(sk); |
1735 | struct sockaddr_un *sunaddr=msg->msg_name; | 1761 | struct sockaddr_un *sunaddr = msg->msg_name; |
1736 | int copied = 0; | 1762 | int copied = 0; |
1737 | int check_creds = 0; | 1763 | int check_creds = 0; |
1738 | int target; | 1764 | int target; |
@@ -1763,15 +1789,13 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1763 | 1789 | ||
1764 | mutex_lock(&u->readlock); | 1790 | mutex_lock(&u->readlock); |
1765 | 1791 | ||
1766 | do | 1792 | do { |
1767 | { | ||
1768 | int chunk; | 1793 | int chunk; |
1769 | struct sk_buff *skb; | 1794 | struct sk_buff *skb; |
1770 | 1795 | ||
1771 | unix_state_lock(sk); | 1796 | unix_state_lock(sk); |
1772 | skb = skb_dequeue(&sk->sk_receive_queue); | 1797 | skb = skb_dequeue(&sk->sk_receive_queue); |
1773 | if (skb==NULL) | 1798 | if (skb == NULL) { |
1774 | { | ||
1775 | if (copied >= target) | 1799 | if (copied >= target) |
1776 | goto unlock; | 1800 | goto unlock; |
1777 | 1801 | ||
@@ -1779,7 +1803,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1779 | * POSIX 1003.1g mandates this order. | 1803 | * POSIX 1003.1g mandates this order. |
1780 | */ | 1804 | */ |
1781 | 1805 | ||
1782 | if ((err = sock_error(sk)) != 0) | 1806 | err = sock_error(sk); |
1807 | if (err) | ||
1783 | goto unlock; | 1808 | goto unlock; |
1784 | if (sk->sk_shutdown & RCV_SHUTDOWN) | 1809 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
1785 | goto unlock; | 1810 | goto unlock; |
@@ -1806,7 +1831,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1806 | 1831 | ||
1807 | if (check_creds) { | 1832 | if (check_creds) { |
1808 | /* Never glue messages from different writers */ | 1833 | /* Never glue messages from different writers */ |
1809 | if (memcmp(UNIXCREDS(skb), &siocb->scm->creds, sizeof(siocb->scm->creds)) != 0) { | 1834 | if (memcmp(UNIXCREDS(skb), &siocb->scm->creds, |
1835 | sizeof(siocb->scm->creds)) != 0) { | ||
1810 | skb_queue_head(&sk->sk_receive_queue, skb); | 1836 | skb_queue_head(&sk->sk_receive_queue, skb); |
1811 | break; | 1837 | break; |
1812 | } | 1838 | } |
@@ -1817,8 +1843,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1817 | } | 1843 | } |
1818 | 1844 | ||
1819 | /* Copy address just once */ | 1845 | /* Copy address just once */ |
1820 | if (sunaddr) | 1846 | if (sunaddr) { |
1821 | { | ||
1822 | unix_copy_addr(msg, skb->sk); | 1847 | unix_copy_addr(msg, skb->sk); |
1823 | sunaddr = NULL; | 1848 | sunaddr = NULL; |
1824 | } | 1849 | } |
@@ -1834,16 +1859,14 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1834 | size -= chunk; | 1859 | size -= chunk; |
1835 | 1860 | ||
1836 | /* Mark read part of skb as used */ | 1861 | /* Mark read part of skb as used */ |
1837 | if (!(flags & MSG_PEEK)) | 1862 | if (!(flags & MSG_PEEK)) { |
1838 | { | ||
1839 | skb_pull(skb, chunk); | 1863 | skb_pull(skb, chunk); |
1840 | 1864 | ||
1841 | if (UNIXCB(skb).fp) | 1865 | if (UNIXCB(skb).fp) |
1842 | unix_detach_fds(siocb->scm, skb); | 1866 | unix_detach_fds(siocb->scm, skb); |
1843 | 1867 | ||
1844 | /* put the skb back if we didn't use it up.. */ | 1868 | /* put the skb back if we didn't use it up.. */ |
1845 | if (skb->len) | 1869 | if (skb->len) { |
1846 | { | ||
1847 | skb_queue_head(&sk->sk_receive_queue, skb); | 1870 | skb_queue_head(&sk->sk_receive_queue, skb); |
1848 | break; | 1871 | break; |
1849 | } | 1872 | } |
@@ -1852,9 +1875,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1852 | 1875 | ||
1853 | if (siocb->scm->fp) | 1876 | if (siocb->scm->fp) |
1854 | break; | 1877 | break; |
1855 | } | 1878 | } else { |
1856 | else | ||
1857 | { | ||
1858 | /* It is questionable, see note in unix_dgram_recvmsg. | 1879 | /* It is questionable, see note in unix_dgram_recvmsg. |
1859 | */ | 1880 | */ |
1860 | if (UNIXCB(skb).fp) | 1881 | if (UNIXCB(skb).fp) |
@@ -1882,7 +1903,7 @@ static int unix_shutdown(struct socket *sock, int mode) | |||
1882 | if (mode) { | 1903 | if (mode) { |
1883 | unix_state_lock(sk); | 1904 | unix_state_lock(sk); |
1884 | sk->sk_shutdown |= mode; | 1905 | sk->sk_shutdown |= mode; |
1885 | other=unix_peer(sk); | 1906 | other = unix_peer(sk); |
1886 | if (other) | 1907 | if (other) |
1887 | sock_hold(other); | 1908 | sock_hold(other); |
1888 | unix_state_unlock(sk); | 1909 | unix_state_unlock(sk); |
@@ -1917,16 +1938,15 @@ static int unix_shutdown(struct socket *sock, int mode) | |||
1917 | static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 1938 | static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
1918 | { | 1939 | { |
1919 | struct sock *sk = sock->sk; | 1940 | struct sock *sk = sock->sk; |
1920 | long amount=0; | 1941 | long amount = 0; |
1921 | int err; | 1942 | int err; |
1922 | 1943 | ||
1923 | switch(cmd) | 1944 | switch (cmd) { |
1924 | { | 1945 | case SIOCOUTQ: |
1925 | case SIOCOUTQ: | 1946 | amount = atomic_read(&sk->sk_wmem_alloc); |
1926 | amount = atomic_read(&sk->sk_wmem_alloc); | 1947 | err = put_user(amount, (int __user *)arg); |
1927 | err = put_user(amount, (int __user *)arg); | 1948 | break; |
1928 | break; | 1949 | case SIOCINQ: |
1929 | case SIOCINQ: | ||
1930 | { | 1950 | { |
1931 | struct sk_buff *skb; | 1951 | struct sk_buff *skb; |
1932 | 1952 | ||
@@ -1943,21 +1963,21 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1943 | } else { | 1963 | } else { |
1944 | skb = skb_peek(&sk->sk_receive_queue); | 1964 | skb = skb_peek(&sk->sk_receive_queue); |
1945 | if (skb) | 1965 | if (skb) |
1946 | amount=skb->len; | 1966 | amount = skb->len; |
1947 | } | 1967 | } |
1948 | spin_unlock(&sk->sk_receive_queue.lock); | 1968 | spin_unlock(&sk->sk_receive_queue.lock); |
1949 | err = put_user(amount, (int __user *)arg); | 1969 | err = put_user(amount, (int __user *)arg); |
1950 | break; | 1970 | break; |
1951 | } | 1971 | } |
1952 | 1972 | ||
1953 | default: | 1973 | default: |
1954 | err = -ENOIOCTLCMD; | 1974 | err = -ENOIOCTLCMD; |
1955 | break; | 1975 | break; |
1956 | } | 1976 | } |
1957 | return err; | 1977 | return err; |
1958 | } | 1978 | } |
1959 | 1979 | ||
1960 | static unsigned int unix_poll(struct file * file, struct socket *sock, poll_table *wait) | 1980 | static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table *wait) |
1961 | { | 1981 | { |
1962 | struct sock *sk = sock->sk; | 1982 | struct sock *sk = sock->sk; |
1963 | unsigned int mask; | 1983 | unsigned int mask; |
@@ -1979,7 +1999,8 @@ static unsigned int unix_poll(struct file * file, struct socket *sock, poll_tabl | |||
1979 | mask |= POLLIN | POLLRDNORM; | 1999 | mask |= POLLIN | POLLRDNORM; |
1980 | 2000 | ||
1981 | /* Connection-based need to check for termination and startup */ | 2001 | /* Connection-based need to check for termination and startup */ |
1982 | if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) && sk->sk_state == TCP_CLOSE) | 2002 | if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) && |
2003 | sk->sk_state == TCP_CLOSE) | ||
1983 | mask |= POLLHUP; | 2004 | mask |= POLLHUP; |
1984 | 2005 | ||
1985 | /* | 2006 | /* |
@@ -2075,6 +2096,7 @@ struct unix_iter_state { | |||
2075 | struct seq_net_private p; | 2096 | struct seq_net_private p; |
2076 | int i; | 2097 | int i; |
2077 | }; | 2098 | }; |
2099 | |||
2078 | static struct sock *unix_seq_idx(struct seq_file *seq, loff_t pos) | 2100 | static struct sock *unix_seq_idx(struct seq_file *seq, loff_t pos) |
2079 | { | 2101 | { |
2080 | struct unix_iter_state *iter = seq->private; | 2102 | struct unix_iter_state *iter = seq->private; |
@@ -2091,7 +2113,6 @@ static struct sock *unix_seq_idx(struct seq_file *seq, loff_t pos) | |||
2091 | return NULL; | 2113 | return NULL; |
2092 | } | 2114 | } |
2093 | 2115 | ||
2094 | |||
2095 | static void *unix_seq_start(struct seq_file *seq, loff_t *pos) | 2116 | static void *unix_seq_start(struct seq_file *seq, loff_t *pos) |
2096 | __acquires(unix_table_lock) | 2117 | __acquires(unix_table_lock) |
2097 | { | 2118 | { |
@@ -2171,7 +2192,6 @@ static const struct seq_operations unix_seq_ops = { | |||
2171 | .show = unix_seq_show, | 2192 | .show = unix_seq_show, |
2172 | }; | 2193 | }; |
2173 | 2194 | ||
2174 | |||
2175 | static int unix_seq_open(struct inode *inode, struct file *file) | 2195 | static int unix_seq_open(struct inode *inode, struct file *file) |
2176 | { | 2196 | { |
2177 | return seq_open_net(inode, file, &unix_seq_ops, | 2197 | return seq_open_net(inode, file, &unix_seq_ops, |
@@ -2211,7 +2231,7 @@ static int unix_net_init(struct net *net) | |||
2211 | #endif | 2231 | #endif |
2212 | error = 0; | 2232 | error = 0; |
2213 | out: | 2233 | out: |
2214 | return 0; | 2234 | return error; |
2215 | } | 2235 | } |
2216 | 2236 | ||
2217 | static void unix_net_exit(struct net *net) | 2237 | static void unix_net_exit(struct net *net) |
diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 2a27b84f740b..19c17e4a0c8b 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c | |||
@@ -80,6 +80,7 @@ | |||
80 | #include <linux/file.h> | 80 | #include <linux/file.h> |
81 | #include <linux/proc_fs.h> | 81 | #include <linux/proc_fs.h> |
82 | #include <linux/mutex.h> | 82 | #include <linux/mutex.h> |
83 | #include <linux/wait.h> | ||
83 | 84 | ||
84 | #include <net/sock.h> | 85 | #include <net/sock.h> |
85 | #include <net/af_unix.h> | 86 | #include <net/af_unix.h> |
@@ -91,6 +92,7 @@ | |||
91 | static LIST_HEAD(gc_inflight_list); | 92 | static LIST_HEAD(gc_inflight_list); |
92 | static LIST_HEAD(gc_candidates); | 93 | static LIST_HEAD(gc_candidates); |
93 | static DEFINE_SPINLOCK(unix_gc_lock); | 94 | static DEFINE_SPINLOCK(unix_gc_lock); |
95 | static DECLARE_WAIT_QUEUE_HEAD(unix_gc_wait); | ||
94 | 96 | ||
95 | unsigned int unix_tot_inflight; | 97 | unsigned int unix_tot_inflight; |
96 | 98 | ||
@@ -104,8 +106,8 @@ static struct sock *unix_get_socket(struct file *filp) | |||
104 | * Socket ? | 106 | * Socket ? |
105 | */ | 107 | */ |
106 | if (S_ISSOCK(inode->i_mode)) { | 108 | if (S_ISSOCK(inode->i_mode)) { |
107 | struct socket * sock = SOCKET_I(inode); | 109 | struct socket *sock = SOCKET_I(inode); |
108 | struct sock * s = sock->sk; | 110 | struct sock *s = sock->sk; |
109 | 111 | ||
110 | /* | 112 | /* |
111 | * PF_UNIX ? | 113 | * PF_UNIX ? |
@@ -124,7 +126,7 @@ static struct sock *unix_get_socket(struct file *filp) | |||
124 | void unix_inflight(struct file *fp) | 126 | void unix_inflight(struct file *fp) |
125 | { | 127 | { |
126 | struct sock *s = unix_get_socket(fp); | 128 | struct sock *s = unix_get_socket(fp); |
127 | if(s) { | 129 | if (s) { |
128 | struct unix_sock *u = unix_sk(s); | 130 | struct unix_sock *u = unix_sk(s); |
129 | spin_lock(&unix_gc_lock); | 131 | spin_lock(&unix_gc_lock); |
130 | if (atomic_long_inc_return(&u->inflight) == 1) { | 132 | if (atomic_long_inc_return(&u->inflight) == 1) { |
@@ -141,7 +143,7 @@ void unix_inflight(struct file *fp) | |||
141 | void unix_notinflight(struct file *fp) | 143 | void unix_notinflight(struct file *fp) |
142 | { | 144 | { |
143 | struct sock *s = unix_get_socket(fp); | 145 | struct sock *s = unix_get_socket(fp); |
144 | if(s) { | 146 | if (s) { |
145 | struct unix_sock *u = unix_sk(s); | 147 | struct unix_sock *u = unix_sk(s); |
146 | spin_lock(&unix_gc_lock); | 148 | spin_lock(&unix_gc_lock); |
147 | BUG_ON(list_empty(&u->link)); | 149 | BUG_ON(list_empty(&u->link)); |
@@ -154,7 +156,7 @@ void unix_notinflight(struct file *fp) | |||
154 | 156 | ||
155 | static inline struct sk_buff *sock_queue_head(struct sock *sk) | 157 | static inline struct sk_buff *sock_queue_head(struct sock *sk) |
156 | { | 158 | { |
157 | return (struct sk_buff *) &sk->sk_receive_queue; | 159 | return (struct sk_buff *)&sk->sk_receive_queue; |
158 | } | 160 | } |
159 | 161 | ||
160 | #define receive_queue_for_each_skb(sk, next, skb) \ | 162 | #define receive_queue_for_each_skb(sk, next, skb) \ |
@@ -186,8 +188,17 @@ static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), | |||
186 | */ | 188 | */ |
187 | struct sock *sk = unix_get_socket(*fp++); | 189 | struct sock *sk = unix_get_socket(*fp++); |
188 | if (sk) { | 190 | if (sk) { |
189 | hit = true; | 191 | struct unix_sock *u = unix_sk(sk); |
190 | func(unix_sk(sk)); | 192 | |
193 | /* | ||
194 | * Ignore non-candidates, they could | ||
195 | * have been added to the queues after | ||
196 | * starting the garbage collection | ||
197 | */ | ||
198 | if (u->gc_candidate) { | ||
199 | hit = true; | ||
200 | func(u); | ||
201 | } | ||
191 | } | 202 | } |
192 | } | 203 | } |
193 | if (hit && hitlist != NULL) { | 204 | if (hit && hitlist != NULL) { |
@@ -249,24 +260,29 @@ static void inc_inflight_move_tail(struct unix_sock *u) | |||
249 | { | 260 | { |
250 | atomic_long_inc(&u->inflight); | 261 | atomic_long_inc(&u->inflight); |
251 | /* | 262 | /* |
252 | * If this is still a candidate, move it to the end of the | 263 | * If this still might be part of a cycle, move it to the end |
253 | * list, so that it's checked even if it was already passed | 264 | * of the list, so that it's checked even if it was already |
254 | * over | 265 | * passed over |
255 | */ | 266 | */ |
256 | if (u->gc_candidate) | 267 | if (u->gc_maybe_cycle) |
257 | list_move_tail(&u->link, &gc_candidates); | 268 | list_move_tail(&u->link, &gc_candidates); |
258 | } | 269 | } |
259 | 270 | ||
260 | /* The external entry point: unix_gc() */ | 271 | static bool gc_in_progress = false; |
261 | 272 | ||
262 | void unix_gc(void) | 273 | void wait_for_unix_gc(void) |
263 | { | 274 | { |
264 | static bool gc_in_progress = false; | 275 | wait_event(unix_gc_wait, gc_in_progress == false); |
276 | } | ||
265 | 277 | ||
278 | /* The external entry point: unix_gc() */ | ||
279 | void unix_gc(void) | ||
280 | { | ||
266 | struct unix_sock *u; | 281 | struct unix_sock *u; |
267 | struct unix_sock *next; | 282 | struct unix_sock *next; |
268 | struct sk_buff_head hitlist; | 283 | struct sk_buff_head hitlist; |
269 | struct list_head cursor; | 284 | struct list_head cursor; |
285 | LIST_HEAD(not_cycle_list); | ||
270 | 286 | ||
271 | spin_lock(&unix_gc_lock); | 287 | spin_lock(&unix_gc_lock); |
272 | 288 | ||
@@ -282,10 +298,14 @@ void unix_gc(void) | |||
282 | * | 298 | * |
283 | * Holding unix_gc_lock will protect these candidates from | 299 | * Holding unix_gc_lock will protect these candidates from |
284 | * being detached, and hence from gaining an external | 300 | * being detached, and hence from gaining an external |
285 | * reference. This also means, that since there are no | 301 | * reference. Since there are no possible receivers, all |
286 | * possible receivers, the receive queues of these sockets are | 302 | * buffers currently on the candidates' queues stay there |
287 | * static during the GC, even though the dequeue is done | 303 | * during the garbage collection. |
288 | * before the detach without atomicity guarantees. | 304 | * |
305 | * We also know that no new candidate can be added onto the | ||
306 | * receive queues. Other, non candidate sockets _can_ be | ||
307 | * added to queue, so we must make sure only to touch | ||
308 | * candidates. | ||
289 | */ | 309 | */ |
290 | list_for_each_entry_safe(u, next, &gc_inflight_list, link) { | 310 | list_for_each_entry_safe(u, next, &gc_inflight_list, link) { |
291 | long total_refs; | 311 | long total_refs; |
@@ -299,6 +319,7 @@ void unix_gc(void) | |||
299 | if (total_refs == inflight_refs) { | 319 | if (total_refs == inflight_refs) { |
300 | list_move_tail(&u->link, &gc_candidates); | 320 | list_move_tail(&u->link, &gc_candidates); |
301 | u->gc_candidate = 1; | 321 | u->gc_candidate = 1; |
322 | u->gc_maybe_cycle = 1; | ||
302 | } | 323 | } |
303 | } | 324 | } |
304 | 325 | ||
@@ -325,21 +346,31 @@ void unix_gc(void) | |||
325 | list_move(&cursor, &u->link); | 346 | list_move(&cursor, &u->link); |
326 | 347 | ||
327 | if (atomic_long_read(&u->inflight) > 0) { | 348 | if (atomic_long_read(&u->inflight) > 0) { |
328 | list_move_tail(&u->link, &gc_inflight_list); | 349 | list_move_tail(&u->link, ¬_cycle_list); |
329 | u->gc_candidate = 0; | 350 | u->gc_maybe_cycle = 0; |
330 | scan_children(&u->sk, inc_inflight_move_tail, NULL); | 351 | scan_children(&u->sk, inc_inflight_move_tail, NULL); |
331 | } | 352 | } |
332 | } | 353 | } |
333 | list_del(&cursor); | 354 | list_del(&cursor); |
334 | 355 | ||
335 | /* | 356 | /* |
357 | * not_cycle_list contains those sockets which do not make up a | ||
358 | * cycle. Restore these to the inflight list. | ||
359 | */ | ||
360 | while (!list_empty(¬_cycle_list)) { | ||
361 | u = list_entry(not_cycle_list.next, struct unix_sock, link); | ||
362 | u->gc_candidate = 0; | ||
363 | list_move_tail(&u->link, &gc_inflight_list); | ||
364 | } | ||
365 | |||
366 | /* | ||
336 | * Now gc_candidates contains only garbage. Restore original | 367 | * Now gc_candidates contains only garbage. Restore original |
337 | * inflight counters for these as well, and remove the skbuffs | 368 | * inflight counters for these as well, and remove the skbuffs |
338 | * which are creating the cycle(s). | 369 | * which are creating the cycle(s). |
339 | */ | 370 | */ |
340 | skb_queue_head_init(&hitlist); | 371 | skb_queue_head_init(&hitlist); |
341 | list_for_each_entry(u, &gc_candidates, link) | 372 | list_for_each_entry(u, &gc_candidates, link) |
342 | scan_children(&u->sk, inc_inflight, &hitlist); | 373 | scan_children(&u->sk, inc_inflight, &hitlist); |
343 | 374 | ||
344 | spin_unlock(&unix_gc_lock); | 375 | spin_unlock(&unix_gc_lock); |
345 | 376 | ||
@@ -351,6 +382,7 @@ void unix_gc(void) | |||
351 | /* All candidates should have been detached by now. */ | 382 | /* All candidates should have been detached by now. */ |
352 | BUG_ON(!list_empty(&gc_candidates)); | 383 | BUG_ON(!list_empty(&gc_candidates)); |
353 | gc_in_progress = false; | 384 | gc_in_progress = false; |
385 | wake_up(&unix_gc_wait); | ||
354 | 386 | ||
355 | out: | 387 | out: |
356 | spin_unlock(&unix_gc_lock); | 388 | spin_unlock(&unix_gc_lock); |
diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c index 77513d7e35f2..83c093077ebc 100644 --- a/net/unix/sysctl_net_unix.c +++ b/net/unix/sysctl_net_unix.c | |||
@@ -21,7 +21,7 @@ static ctl_table unix_table[] = { | |||
21 | .data = &init_net.unx.sysctl_max_dgram_qlen, | 21 | .data = &init_net.unx.sysctl_max_dgram_qlen, |
22 | .maxlen = sizeof(int), | 22 | .maxlen = sizeof(int), |
23 | .mode = 0644, | 23 | .mode = 0644, |
24 | .proc_handler = &proc_dointvec | 24 | .proc_handler = proc_dointvec |
25 | }, | 25 | }, |
26 | { .ctl_name = 0 } | 26 | { .ctl_name = 0 } |
27 | }; | 27 | }; |
@@ -61,4 +61,3 @@ void unix_sysctl_unregister(struct net *net) | |||
61 | unregister_sysctl_table(net->unx.ctl); | 61 | unregister_sysctl_table(net->unx.ctl); |
62 | kfree(table); | 62 | kfree(table); |
63 | } | 63 | } |
64 | |||