diff options
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r-- | net/unix/af_unix.c | 87 |
1 files changed, 51 insertions, 36 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index dd419d28620..de870184e45 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -1171,7 +1171,7 @@ restart: | |||
1171 | newsk->sk_type = sk->sk_type; | 1171 | newsk->sk_type = sk->sk_type; |
1172 | init_peercred(newsk); | 1172 | init_peercred(newsk); |
1173 | newu = unix_sk(newsk); | 1173 | newu = unix_sk(newsk); |
1174 | newsk->sk_wq = &newu->peer_wq; | 1174 | RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq); |
1175 | otheru = unix_sk(other); | 1175 | otheru = unix_sk(other); |
1176 | 1176 | ||
1177 | /* copy address information from listening to new sock*/ | 1177 | /* copy address information from listening to new sock*/ |
@@ -1475,6 +1475,12 @@ restart: | |||
1475 | goto out_free; | 1475 | goto out_free; |
1476 | } | 1476 | } |
1477 | 1477 | ||
1478 | if (sk_filter(other, skb) < 0) { | ||
1479 | /* Toss the packet but do not return any error to the sender */ | ||
1480 | err = len; | ||
1481 | goto out_free; | ||
1482 | } | ||
1483 | |||
1478 | unix_state_lock(other); | 1484 | unix_state_lock(other); |
1479 | err = -EPERM; | 1485 | err = -EPERM; |
1480 | if (!unix_may_send(sk, other)) | 1486 | if (!unix_may_send(sk, other)) |
@@ -1561,7 +1567,6 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1561 | struct sock_iocb *siocb = kiocb_to_siocb(kiocb); | 1567 | struct sock_iocb *siocb = kiocb_to_siocb(kiocb); |
1562 | struct sock *sk = sock->sk; | 1568 | struct sock *sk = sock->sk; |
1563 | struct sock *other = NULL; | 1569 | struct sock *other = NULL; |
1564 | struct sockaddr_un *sunaddr = msg->msg_name; | ||
1565 | int err, size; | 1570 | int err, size; |
1566 | struct sk_buff *skb; | 1571 | struct sk_buff *skb; |
1567 | int sent = 0; | 1572 | int sent = 0; |
@@ -1584,7 +1589,6 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1584 | err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP; | 1589 | err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP; |
1585 | goto out_err; | 1590 | goto out_err; |
1586 | } else { | 1591 | } else { |
1587 | sunaddr = NULL; | ||
1588 | err = -ENOTCONN; | 1592 | err = -ENOTCONN; |
1589 | other = unix_peer(sk); | 1593 | other = unix_peer(sk); |
1590 | if (!other) | 1594 | if (!other) |
@@ -1724,7 +1728,11 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1724 | 1728 | ||
1725 | msg->msg_namelen = 0; | 1729 | msg->msg_namelen = 0; |
1726 | 1730 | ||
1727 | mutex_lock(&u->readlock); | 1731 | err = mutex_lock_interruptible(&u->readlock); |
1732 | if (err) { | ||
1733 | err = sock_intr_errno(sock_rcvtimeo(sk, noblock)); | ||
1734 | goto out; | ||
1735 | } | ||
1728 | 1736 | ||
1729 | skb = skb_recv_datagram(sk, flags, noblock, &err); | 1737 | skb = skb_recv_datagram(sk, flags, noblock, &err); |
1730 | if (!skb) { | 1738 | if (!skb) { |
@@ -1864,7 +1872,11 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1864 | memset(&tmp_scm, 0, sizeof(tmp_scm)); | 1872 | memset(&tmp_scm, 0, sizeof(tmp_scm)); |
1865 | } | 1873 | } |
1866 | 1874 | ||
1867 | mutex_lock(&u->readlock); | 1875 | err = mutex_lock_interruptible(&u->readlock); |
1876 | if (err) { | ||
1877 | err = sock_intr_errno(timeo); | ||
1878 | goto out; | ||
1879 | } | ||
1868 | 1880 | ||
1869 | do { | 1881 | do { |
1870 | int chunk; | 1882 | int chunk; |
@@ -1895,11 +1907,12 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1895 | 1907 | ||
1896 | timeo = unix_stream_data_wait(sk, timeo); | 1908 | timeo = unix_stream_data_wait(sk, timeo); |
1897 | 1909 | ||
1898 | if (signal_pending(current)) { | 1910 | if (signal_pending(current) |
1911 | || mutex_lock_interruptible(&u->readlock)) { | ||
1899 | err = sock_intr_errno(timeo); | 1912 | err = sock_intr_errno(timeo); |
1900 | goto out; | 1913 | goto out; |
1901 | } | 1914 | } |
1902 | mutex_lock(&u->readlock); | 1915 | |
1903 | continue; | 1916 | continue; |
1904 | unlock: | 1917 | unlock: |
1905 | unix_state_unlock(sk); | 1918 | unix_state_unlock(sk); |
@@ -1978,36 +1991,38 @@ static int unix_shutdown(struct socket *sock, int mode) | |||
1978 | 1991 | ||
1979 | mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN); | 1992 | mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN); |
1980 | 1993 | ||
1981 | if (mode) { | 1994 | if (!mode) |
1982 | unix_state_lock(sk); | 1995 | return 0; |
1983 | sk->sk_shutdown |= mode; | 1996 | |
1984 | other = unix_peer(sk); | 1997 | unix_state_lock(sk); |
1985 | if (other) | 1998 | sk->sk_shutdown |= mode; |
1986 | sock_hold(other); | 1999 | other = unix_peer(sk); |
1987 | unix_state_unlock(sk); | 2000 | if (other) |
1988 | sk->sk_state_change(sk); | 2001 | sock_hold(other); |
1989 | 2002 | unix_state_unlock(sk); | |
1990 | if (other && | 2003 | sk->sk_state_change(sk); |
1991 | (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) { | 2004 | |
1992 | 2005 | if (other && | |
1993 | int peer_mode = 0; | 2006 | (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) { |
1994 | 2007 | ||
1995 | if (mode&RCV_SHUTDOWN) | 2008 | int peer_mode = 0; |
1996 | peer_mode |= SEND_SHUTDOWN; | 2009 | |
1997 | if (mode&SEND_SHUTDOWN) | 2010 | if (mode&RCV_SHUTDOWN) |
1998 | peer_mode |= RCV_SHUTDOWN; | 2011 | peer_mode |= SEND_SHUTDOWN; |
1999 | unix_state_lock(other); | 2012 | if (mode&SEND_SHUTDOWN) |
2000 | other->sk_shutdown |= peer_mode; | 2013 | peer_mode |= RCV_SHUTDOWN; |
2001 | unix_state_unlock(other); | 2014 | unix_state_lock(other); |
2002 | other->sk_state_change(other); | 2015 | other->sk_shutdown |= peer_mode; |
2003 | if (peer_mode == SHUTDOWN_MASK) | 2016 | unix_state_unlock(other); |
2004 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP); | 2017 | other->sk_state_change(other); |
2005 | else if (peer_mode & RCV_SHUTDOWN) | 2018 | if (peer_mode == SHUTDOWN_MASK) |
2006 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN); | 2019 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP); |
2007 | } | 2020 | else if (peer_mode & RCV_SHUTDOWN) |
2008 | if (other) | 2021 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN); |
2009 | sock_put(other); | ||
2010 | } | 2022 | } |
2023 | if (other) | ||
2024 | sock_put(other); | ||
2025 | |||
2011 | return 0; | 2026 | return 0; |
2012 | } | 2027 | } |
2013 | 2028 | ||