.. | .. |
---|
| 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) |
---|
.. | .. |
---|
536 | 529 | /* Clear state */ |
---|
537 | 530 | unix_state_lock(sk); |
---|
538 | 531 | sock_orphan(sk); |
---|
539 | | - sk->sk_shutdown = SHUTDOWN_MASK; |
---|
| 532 | + WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK); |
---|
540 | 533 | path = u->path; |
---|
541 | 534 | u->path.dentry = NULL; |
---|
542 | 535 | u->path.mnt = NULL; |
---|
.. | .. |
---|
554 | 547 | if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) { |
---|
555 | 548 | unix_state_lock(skpair); |
---|
556 | 549 | /* No more writes */ |
---|
557 | | - skpair->sk_shutdown = SHUTDOWN_MASK; |
---|
| 550 | + WRITE_ONCE(skpair->sk_shutdown, SHUTDOWN_MASK); |
---|
558 | 551 | if (!skb_queue_empty(&sk->sk_receive_queue) || embrion) |
---|
559 | 552 | skpair->sk_err = ECONNRESET; |
---|
560 | 553 | unix_state_unlock(skpair); |
---|
.. | .. |
---|
594 | 587 | * What the above comment does talk about? --ANK(980817) |
---|
595 | 588 | */ |
---|
596 | 589 | |
---|
597 | | - if (unix_tot_inflight) |
---|
| 590 | + if (READ_ONCE(unix_tot_inflight)) |
---|
598 | 591 | unix_gc(); /* Garbage collect fds */ |
---|
599 | 592 | } |
---|
600 | 593 | |
---|
.. | .. |
---|
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 | } |
---|
.. | .. |
---|
706 | 697 | if (mutex_lock_interruptible(&u->iolock)) |
---|
707 | 698 | return -EINTR; |
---|
708 | 699 | |
---|
709 | | - sk->sk_peek_off = val; |
---|
| 700 | + WRITE_ONCE(sk->sk_peek_off, val); |
---|
710 | 701 | mutex_unlock(&u->iolock); |
---|
711 | 702 | |
---|
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; |
---|
.. | .. |
---|
1232 | 1236 | |
---|
1233 | 1237 | sched = !sock_flag(other, SOCK_DEAD) && |
---|
1234 | 1238 | !(other->sk_shutdown & RCV_SHUTDOWN) && |
---|
1235 | | - unix_recvq_full(other); |
---|
| 1239 | + unix_recvq_full_lockless(other); |
---|
1236 | 1240 | |
---|
1237 | 1241 | unix_state_unlock(other); |
---|
1238 | 1242 | |
---|
.. | .. |
---|
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); |
---|
.. | .. |
---|
1984 | 2008 | |
---|
1985 | 2009 | if (false) { |
---|
1986 | 2010 | alloc_skb: |
---|
| 2011 | + spin_unlock(&other->sk_receive_queue.lock); |
---|
1987 | 2012 | unix_state_unlock(other); |
---|
1988 | 2013 | mutex_unlock(&unix_sk(other)->iolock); |
---|
1989 | 2014 | newskb = sock_alloc_send_pskb(sk, 0, 0, flags & MSG_DONTWAIT, |
---|
.. | .. |
---|
2023 | 2048 | init_scm = false; |
---|
2024 | 2049 | } |
---|
2025 | 2050 | |
---|
| 2051 | + spin_lock(&other->sk_receive_queue.lock); |
---|
2026 | 2052 | skb = skb_peek_tail(&other->sk_receive_queue); |
---|
2027 | 2053 | if (tail && tail == skb) { |
---|
2028 | 2054 | skb = newskb; |
---|
.. | .. |
---|
2053 | 2079 | refcount_add(size, &sk->sk_wmem_alloc); |
---|
2054 | 2080 | |
---|
2055 | 2081 | if (newskb) { |
---|
2056 | | - err = unix_scm_to_skb(&scm, skb, false); |
---|
2057 | | - if (err) |
---|
2058 | | - goto err_state_unlock; |
---|
2059 | | - spin_lock(&other->sk_receive_queue.lock); |
---|
| 2082 | + unix_scm_to_skb(&scm, skb, false); |
---|
2060 | 2083 | __skb_queue_tail(&other->sk_receive_queue, newskb); |
---|
2061 | | - spin_unlock(&other->sk_receive_queue.lock); |
---|
2062 | 2084 | } |
---|
2063 | 2085 | |
---|
| 2086 | + spin_unlock(&other->sk_receive_queue.lock); |
---|
2064 | 2087 | unix_state_unlock(other); |
---|
2065 | 2088 | mutex_unlock(&unix_sk(other)->iolock); |
---|
2066 | 2089 | |
---|
.. | .. |
---|
2129 | 2152 | struct unix_sock *u = unix_sk(sk); |
---|
2130 | 2153 | struct sk_buff *skb, *last; |
---|
2131 | 2154 | long timeo; |
---|
| 2155 | + int skip; |
---|
2132 | 2156 | int err; |
---|
2133 | | - int peeked, skip; |
---|
2134 | 2157 | |
---|
2135 | 2158 | err = -EOPNOTSUPP; |
---|
2136 | 2159 | if (flags&MSG_OOB) |
---|
.. | .. |
---|
2142 | 2165 | mutex_lock(&u->iolock); |
---|
2143 | 2166 | |
---|
2144 | 2167 | skip = sk_peek_offset(sk, flags); |
---|
2145 | | - skb = __skb_try_recv_datagram(sk, flags, NULL, &peeked, &skip, |
---|
2146 | | - &err, &last); |
---|
2147 | | - if (skb) |
---|
| 2168 | + skb = __skb_try_recv_datagram(sk, &sk->sk_receive_queue, flags, |
---|
| 2169 | + &skip, &err, &last); |
---|
| 2170 | + if (skb) { |
---|
| 2171 | + if (!(flags & MSG_PEEK)) |
---|
| 2172 | + scm_stat_del(sk, skb); |
---|
2148 | 2173 | break; |
---|
| 2174 | + } |
---|
2149 | 2175 | |
---|
2150 | 2176 | mutex_unlock(&u->iolock); |
---|
2151 | 2177 | |
---|
2152 | 2178 | if (err != -EAGAIN) |
---|
2153 | 2179 | break; |
---|
2154 | 2180 | } while (timeo && |
---|
2155 | | - !__skb_wait_for_more_packets(sk, &err, &timeo, last)); |
---|
| 2181 | + !__skb_wait_for_more_packets(sk, &sk->sk_receive_queue, |
---|
| 2182 | + &err, &timeo, last)); |
---|
2156 | 2183 | |
---|
2157 | 2184 | if (!skb) { /* implies iolock unlocked */ |
---|
2158 | 2185 | unix_state_lock(sk); |
---|
.. | .. |
---|
2437 | 2464 | |
---|
2438 | 2465 | sk_peek_offset_bwd(sk, chunk); |
---|
2439 | 2466 | |
---|
2440 | | - if (UNIXCB(skb).fp) |
---|
| 2467 | + if (UNIXCB(skb).fp) { |
---|
| 2468 | + scm_stat_del(sk, skb); |
---|
2441 | 2469 | unix_detach_fds(&scm, skb); |
---|
| 2470 | + } |
---|
2442 | 2471 | |
---|
2443 | 2472 | if (unix_skb_len(skb)) |
---|
2444 | 2473 | break; |
---|
.. | .. |
---|
2551 | 2580 | ++mode; |
---|
2552 | 2581 | |
---|
2553 | 2582 | unix_state_lock(sk); |
---|
2554 | | - sk->sk_shutdown |= mode; |
---|
| 2583 | + WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | mode); |
---|
2555 | 2584 | other = unix_peer(sk); |
---|
2556 | 2585 | if (other) |
---|
2557 | 2586 | sock_hold(other); |
---|
.. | .. |
---|
2568 | 2597 | if (mode&SEND_SHUTDOWN) |
---|
2569 | 2598 | peer_mode |= RCV_SHUTDOWN; |
---|
2570 | 2599 | unix_state_lock(other); |
---|
2571 | | - other->sk_shutdown |= peer_mode; |
---|
| 2600 | + WRITE_ONCE(other->sk_shutdown, other->sk_shutdown | peer_mode); |
---|
2572 | 2601 | unix_state_unlock(other); |
---|
2573 | 2602 | other->sk_state_change(other); |
---|
2574 | 2603 | if (peer_mode == SHUTDOWN_MASK) |
---|
.. | .. |
---|
2687 | 2716 | { |
---|
2688 | 2717 | struct sock *sk = sock->sk; |
---|
2689 | 2718 | __poll_t mask; |
---|
| 2719 | + u8 shutdown; |
---|
2690 | 2720 | |
---|
2691 | 2721 | sock_poll_wait(file, sock, wait); |
---|
2692 | 2722 | mask = 0; |
---|
| 2723 | + shutdown = READ_ONCE(sk->sk_shutdown); |
---|
2693 | 2724 | |
---|
2694 | 2725 | /* exceptional events? */ |
---|
2695 | 2726 | if (sk->sk_err) |
---|
2696 | 2727 | mask |= EPOLLERR; |
---|
2697 | | - if (sk->sk_shutdown == SHUTDOWN_MASK) |
---|
| 2728 | + if (shutdown == SHUTDOWN_MASK) |
---|
2698 | 2729 | mask |= EPOLLHUP; |
---|
2699 | | - if (sk->sk_shutdown & RCV_SHUTDOWN) |
---|
| 2730 | + if (shutdown & RCV_SHUTDOWN) |
---|
2700 | 2731 | mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM; |
---|
2701 | 2732 | |
---|
2702 | 2733 | /* readable? */ |
---|
.. | .. |
---|
2724 | 2755 | struct sock *sk = sock->sk, *other; |
---|
2725 | 2756 | unsigned int writable; |
---|
2726 | 2757 | __poll_t mask; |
---|
| 2758 | + u8 shutdown; |
---|
2727 | 2759 | |
---|
2728 | 2760 | sock_poll_wait(file, sock, wait); |
---|
2729 | 2761 | mask = 0; |
---|
| 2762 | + shutdown = READ_ONCE(sk->sk_shutdown); |
---|
2730 | 2763 | |
---|
2731 | 2764 | /* exceptional events? */ |
---|
2732 | 2765 | if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue)) |
---|
2733 | 2766 | mask |= EPOLLERR | |
---|
2734 | 2767 | (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0); |
---|
2735 | 2768 | |
---|
2736 | | - if (sk->sk_shutdown & RCV_SHUTDOWN) |
---|
| 2769 | + if (shutdown & RCV_SHUTDOWN) |
---|
2737 | 2770 | mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM; |
---|
2738 | | - if (sk->sk_shutdown == SHUTDOWN_MASK) |
---|
| 2771 | + if (shutdown == SHUTDOWN_MASK) |
---|
2739 | 2772 | mask |= EPOLLHUP; |
---|
2740 | 2773 | |
---|
2741 | 2774 | /* readable? */ |
---|
.. | .. |
---|
2949 | 2982 | { |
---|
2950 | 2983 | int rc = -1; |
---|
2951 | 2984 | |
---|
2952 | | - BUILD_BUG_ON(sizeof(struct unix_skb_parms) > FIELD_SIZEOF(struct sk_buff, cb)); |
---|
| 2985 | + BUILD_BUG_ON(sizeof(struct unix_skb_parms) > sizeof_field(struct sk_buff, cb)); |
---|
2953 | 2986 | |
---|
2954 | 2987 | rc = proto_register(&unix_proto, 1); |
---|
2955 | 2988 | if (rc != 0) { |
---|
.. | .. |
---|
2978 | 3011 | module_exit(af_unix_exit); |
---|
2979 | 3012 | |
---|
2980 | 3013 | MODULE_LICENSE("GPL"); |
---|
| 3014 | +MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); |
---|
2981 | 3015 | MODULE_ALIAS_NETPROTO(PF_UNIX); |
---|