.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * NET4: Implementation of BSD Unix domain sockets. |
---|
3 | 4 | * |
---|
4 | 5 | * Authors: Alan Cox, <alan@lxorguk.ukuu.org.uk> |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or |
---|
7 | | - * modify it under the terms of the GNU General Public License |
---|
8 | | - * as published by the Free Software Foundation; either version |
---|
9 | | - * 2 of the License, or (at your option) any later version. |
---|
10 | 6 | * |
---|
11 | 7 | * Fixes: |
---|
12 | 8 | * Linus Torvalds : Assorted bug cures. |
---|
.. | .. |
---|
48 | 44 | * Arnaldo C. Melo : Remove MOD_{INC,DEC}_USE_COUNT, |
---|
49 | 45 | * the core infrastructure is doing that |
---|
50 | 46 | * for all net proto families now (2.5.69+) |
---|
51 | | - * |
---|
52 | 47 | * |
---|
53 | 48 | * Known differences from reference BSD that was tested: |
---|
54 | 49 | * |
---|
.. | .. |
---|
295 | 290 | |
---|
296 | 291 | if (u->addr->len == len && |
---|
297 | 292 | !memcmp(u->addr->name, sunname, len)) |
---|
298 | | - goto found; |
---|
| 293 | + return s; |
---|
299 | 294 | } |
---|
300 | | - s = NULL; |
---|
301 | | -found: |
---|
302 | | - return s; |
---|
| 295 | + return NULL; |
---|
303 | 296 | } |
---|
304 | 297 | |
---|
305 | 298 | static inline struct sock *unix_find_socket_byname(struct net *net, |
---|
.. | .. |
---|
445 | 438 | * -ECONNREFUSED. Otherwise, if we haven't queued any skbs |
---|
446 | 439 | * to other and its full, we will hang waiting for POLLOUT. |
---|
447 | 440 | */ |
---|
448 | | - if (unix_recvq_full(other) && !sock_flag(other, SOCK_DEAD)) |
---|
| 441 | + if (unix_recvq_full_lockless(other) && !sock_flag(other, SOCK_DEAD)) |
---|
449 | 442 | return 1; |
---|
450 | 443 | |
---|
451 | 444 | if (connected) |
---|
.. | .. |
---|
643 | 636 | int err; |
---|
644 | 637 | struct sock *sk = sock->sk; |
---|
645 | 638 | struct unix_sock *u = unix_sk(sk); |
---|
646 | | - struct pid *old_pid = NULL; |
---|
647 | 639 | |
---|
648 | 640 | err = -EOPNOTSUPP; |
---|
649 | 641 | if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET) |
---|
.. | .. |
---|
664 | 656 | |
---|
665 | 657 | out_unlock: |
---|
666 | 658 | unix_state_unlock(sk); |
---|
667 | | - put_pid(old_pid); |
---|
668 | 659 | out: |
---|
669 | 660 | return err; |
---|
670 | 661 | } |
---|
.. | .. |
---|
712 | 703 | return 0; |
---|
713 | 704 | } |
---|
714 | 705 | |
---|
| 706 | +#ifdef CONFIG_PROC_FS |
---|
| 707 | +static void unix_show_fdinfo(struct seq_file *m, struct socket *sock) |
---|
| 708 | +{ |
---|
| 709 | + struct sock *sk = sock->sk; |
---|
| 710 | + struct unix_sock *u; |
---|
| 711 | + |
---|
| 712 | + if (sk) { |
---|
| 713 | + u = unix_sk(sock->sk); |
---|
| 714 | + seq_printf(m, "scm_fds: %u\n", |
---|
| 715 | + atomic_read(&u->scm_stat.nr_fds)); |
---|
| 716 | + } |
---|
| 717 | +} |
---|
| 718 | +#else |
---|
| 719 | +#define unix_show_fdinfo NULL |
---|
| 720 | +#endif |
---|
715 | 721 | |
---|
716 | 722 | static const struct proto_ops unix_stream_ops = { |
---|
717 | 723 | .family = PF_UNIX, |
---|
.. | .. |
---|
729 | 735 | #endif |
---|
730 | 736 | .listen = unix_listen, |
---|
731 | 737 | .shutdown = unix_shutdown, |
---|
732 | | - .setsockopt = sock_no_setsockopt, |
---|
733 | | - .getsockopt = sock_no_getsockopt, |
---|
734 | 738 | .sendmsg = unix_stream_sendmsg, |
---|
735 | 739 | .recvmsg = unix_stream_recvmsg, |
---|
736 | 740 | .mmap = sock_no_mmap, |
---|
737 | 741 | .sendpage = unix_stream_sendpage, |
---|
738 | 742 | .splice_read = unix_stream_splice_read, |
---|
739 | 743 | .set_peek_off = unix_set_peek_off, |
---|
| 744 | + .show_fdinfo = unix_show_fdinfo, |
---|
740 | 745 | }; |
---|
741 | 746 | |
---|
742 | 747 | static const struct proto_ops unix_dgram_ops = { |
---|
.. | .. |
---|
755 | 760 | #endif |
---|
756 | 761 | .listen = sock_no_listen, |
---|
757 | 762 | .shutdown = unix_shutdown, |
---|
758 | | - .setsockopt = sock_no_setsockopt, |
---|
759 | | - .getsockopt = sock_no_getsockopt, |
---|
760 | 763 | .sendmsg = unix_dgram_sendmsg, |
---|
761 | 764 | .recvmsg = unix_dgram_recvmsg, |
---|
762 | 765 | .mmap = sock_no_mmap, |
---|
763 | 766 | .sendpage = sock_no_sendpage, |
---|
764 | 767 | .set_peek_off = unix_set_peek_off, |
---|
| 768 | + .show_fdinfo = unix_show_fdinfo, |
---|
765 | 769 | }; |
---|
766 | 770 | |
---|
767 | 771 | static const struct proto_ops unix_seqpacket_ops = { |
---|
.. | .. |
---|
780 | 784 | #endif |
---|
781 | 785 | .listen = unix_listen, |
---|
782 | 786 | .shutdown = unix_shutdown, |
---|
783 | | - .setsockopt = sock_no_setsockopt, |
---|
784 | | - .getsockopt = sock_no_getsockopt, |
---|
785 | 787 | .sendmsg = unix_seqpacket_sendmsg, |
---|
786 | 788 | .recvmsg = unix_seqpacket_recvmsg, |
---|
787 | 789 | .mmap = sock_no_mmap, |
---|
788 | 790 | .sendpage = sock_no_sendpage, |
---|
789 | 791 | .set_peek_off = unix_set_peek_off, |
---|
| 792 | + .show_fdinfo = unix_show_fdinfo, |
---|
790 | 793 | }; |
---|
791 | 794 | |
---|
792 | 795 | static struct proto unix_proto = { |
---|
.. | .. |
---|
824 | 827 | mutex_init(&u->bindlock); /* single task binding lock */ |
---|
825 | 828 | init_waitqueue_head(&u->peer_wait); |
---|
826 | 829 | init_waitqueue_func_entry(&u->peer_wake, unix_dgram_peer_wake_relay); |
---|
| 830 | + memset(&u->scm_stat, 0, sizeof(struct scm_stat)); |
---|
827 | 831 | unix_insert_socket(unix_sockets_unbound(sk), sk); |
---|
828 | 832 | out: |
---|
829 | 833 | if (sk == NULL) |
---|
.. | .. |
---|
854 | 858 | */ |
---|
855 | 859 | case SOCK_RAW: |
---|
856 | 860 | sock->type = SOCK_DGRAM; |
---|
857 | | - /* fall through */ |
---|
| 861 | + fallthrough; |
---|
858 | 862 | case SOCK_DGRAM: |
---|
859 | 863 | sock->ops = &unix_dgram_ops; |
---|
860 | 864 | break; |
---|
.. | .. |
---|
895 | 899 | if (err) |
---|
896 | 900 | return err; |
---|
897 | 901 | |
---|
898 | | - err = 0; |
---|
899 | 902 | if (u->addr) |
---|
900 | 903 | goto out; |
---|
901 | 904 | |
---|
.. | .. |
---|
1223 | 1226 | } |
---|
1224 | 1227 | |
---|
1225 | 1228 | static long unix_wait_for_peer(struct sock *other, long timeo) |
---|
| 1229 | + __releases(&unix_sk(other)->lock) |
---|
1226 | 1230 | { |
---|
1227 | 1231 | struct unix_sock *u = unix_sk(other); |
---|
1228 | 1232 | int sched; |
---|
.. | .. |
---|
1655 | 1659 | unix_secdata_eq(scm, skb); |
---|
1656 | 1660 | } |
---|
1657 | 1661 | |
---|
| 1662 | +static void scm_stat_add(struct sock *sk, struct sk_buff *skb) |
---|
| 1663 | +{ |
---|
| 1664 | + struct scm_fp_list *fp = UNIXCB(skb).fp; |
---|
| 1665 | + struct unix_sock *u = unix_sk(sk); |
---|
| 1666 | + |
---|
| 1667 | + if (unlikely(fp && fp->count)) |
---|
| 1668 | + atomic_add(fp->count, &u->scm_stat.nr_fds); |
---|
| 1669 | +} |
---|
| 1670 | + |
---|
| 1671 | +static void scm_stat_del(struct sock *sk, struct sk_buff *skb) |
---|
| 1672 | +{ |
---|
| 1673 | + struct scm_fp_list *fp = UNIXCB(skb).fp; |
---|
| 1674 | + struct unix_sock *u = unix_sk(sk); |
---|
| 1675 | + |
---|
| 1676 | + if (unlikely(fp && fp->count)) |
---|
| 1677 | + atomic_sub(fp->count, &u->scm_stat.nr_fds); |
---|
| 1678 | +} |
---|
| 1679 | + |
---|
1658 | 1680 | /* |
---|
1659 | 1681 | * Send AF_UNIX data. |
---|
1660 | 1682 | */ |
---|
.. | .. |
---|
1841 | 1863 | if (sock_flag(other, SOCK_RCVTSTAMP)) |
---|
1842 | 1864 | __net_timestamp(skb); |
---|
1843 | 1865 | maybe_add_creds(skb, sock, other); |
---|
| 1866 | + scm_stat_add(other, skb); |
---|
1844 | 1867 | skb_queue_tail(&other->sk_receive_queue, skb); |
---|
1845 | 1868 | unix_state_unlock(other); |
---|
1846 | 1869 | other->sk_data_ready(other); |
---|
.. | .. |
---|
1943 | 1966 | goto pipe_err_free; |
---|
1944 | 1967 | |
---|
1945 | 1968 | maybe_add_creds(skb, sock, other); |
---|
| 1969 | + scm_stat_add(other, skb); |
---|
1946 | 1970 | skb_queue_tail(&other->sk_receive_queue, skb); |
---|
1947 | 1971 | unix_state_unlock(other); |
---|
1948 | 1972 | other->sk_data_ready(other); |
---|
.. | .. |
---|
2129 | 2153 | struct unix_sock *u = unix_sk(sk); |
---|
2130 | 2154 | struct sk_buff *skb, *last; |
---|
2131 | 2155 | long timeo; |
---|
| 2156 | + int skip; |
---|
2132 | 2157 | int err; |
---|
2133 | | - int peeked, skip; |
---|
2134 | 2158 | |
---|
2135 | 2159 | err = -EOPNOTSUPP; |
---|
2136 | 2160 | if (flags&MSG_OOB) |
---|
.. | .. |
---|
2142 | 2166 | mutex_lock(&u->iolock); |
---|
2143 | 2167 | |
---|
2144 | 2168 | skip = sk_peek_offset(sk, flags); |
---|
2145 | | - skb = __skb_try_recv_datagram(sk, flags, NULL, &peeked, &skip, |
---|
2146 | | - &err, &last); |
---|
2147 | | - if (skb) |
---|
| 2169 | + skb = __skb_try_recv_datagram(sk, &sk->sk_receive_queue, flags, |
---|
| 2170 | + &skip, &err, &last); |
---|
| 2171 | + if (skb) { |
---|
| 2172 | + if (!(flags & MSG_PEEK)) |
---|
| 2173 | + scm_stat_del(sk, skb); |
---|
2148 | 2174 | break; |
---|
| 2175 | + } |
---|
2149 | 2176 | |
---|
2150 | 2177 | mutex_unlock(&u->iolock); |
---|
2151 | 2178 | |
---|
2152 | 2179 | if (err != -EAGAIN) |
---|
2153 | 2180 | break; |
---|
2154 | 2181 | } while (timeo && |
---|
2155 | | - !__skb_wait_for_more_packets(sk, &err, &timeo, last)); |
---|
| 2182 | + !__skb_wait_for_more_packets(sk, &sk->sk_receive_queue, |
---|
| 2183 | + &err, &timeo, last)); |
---|
2156 | 2184 | |
---|
2157 | 2185 | if (!skb) { /* implies iolock unlocked */ |
---|
2158 | 2186 | unix_state_lock(sk); |
---|
.. | .. |
---|
2437 | 2465 | |
---|
2438 | 2466 | sk_peek_offset_bwd(sk, chunk); |
---|
2439 | 2467 | |
---|
2440 | | - if (UNIXCB(skb).fp) |
---|
| 2468 | + if (UNIXCB(skb).fp) { |
---|
| 2469 | + scm_stat_del(sk, skb); |
---|
2441 | 2470 | unix_detach_fds(&scm, skb); |
---|
| 2471 | + } |
---|
2442 | 2472 | |
---|
2443 | 2473 | if (unix_skb_len(skb)) |
---|
2444 | 2474 | break; |
---|
.. | .. |
---|
2949 | 2979 | { |
---|
2950 | 2980 | int rc = -1; |
---|
2951 | 2981 | |
---|
2952 | | - BUILD_BUG_ON(sizeof(struct unix_skb_parms) > FIELD_SIZEOF(struct sk_buff, cb)); |
---|
| 2982 | + BUILD_BUG_ON(sizeof(struct unix_skb_parms) > sizeof_field(struct sk_buff, cb)); |
---|
2953 | 2983 | |
---|
2954 | 2984 | rc = proto_register(&unix_proto, 1); |
---|
2955 | 2985 | if (rc != 0) { |
---|
.. | .. |
---|
2978 | 3008 | module_exit(af_unix_exit); |
---|
2979 | 3009 | |
---|
2980 | 3010 | MODULE_LICENSE("GPL"); |
---|
| 3011 | +MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); |
---|
2981 | 3012 | MODULE_ALIAS_NETPROTO(PF_UNIX); |
---|