diff options
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r-- | net/unix/af_unix.c | 92 |
1 files changed, 56 insertions, 36 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 437a99e560e..b1d75beb7e2 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -207,7 +207,7 @@ static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned *hashp) | |||
207 | /* | 207 | /* |
208 | * This may look like an off by one error but it is a bit more | 208 | * This may look like an off by one error but it is a bit more |
209 | * subtle. 108 is the longest valid AF_UNIX path for a binding. | 209 | * subtle. 108 is the longest valid AF_UNIX path for a binding. |
210 | * sun_path[108] doesnt as such exist. However in kernel space | 210 | * sun_path[108] doesn't as such exist. However in kernel space |
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 | */ |
@@ -524,6 +524,8 @@ static int unix_dgram_connect(struct socket *, struct sockaddr *, | |||
524 | int, int); | 524 | int, int); |
525 | static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *, | 525 | static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *, |
526 | struct msghdr *, size_t); | 526 | struct msghdr *, size_t); |
527 | static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *, | ||
528 | struct msghdr *, size_t, int); | ||
527 | 529 | ||
528 | static const struct proto_ops unix_stream_ops = { | 530 | static const struct proto_ops unix_stream_ops = { |
529 | .family = PF_UNIX, | 531 | .family = PF_UNIX, |
@@ -583,7 +585,7 @@ static const struct proto_ops unix_seqpacket_ops = { | |||
583 | .setsockopt = sock_no_setsockopt, | 585 | .setsockopt = sock_no_setsockopt, |
584 | .getsockopt = sock_no_getsockopt, | 586 | .getsockopt = sock_no_getsockopt, |
585 | .sendmsg = unix_seqpacket_sendmsg, | 587 | .sendmsg = unix_seqpacket_sendmsg, |
586 | .recvmsg = unix_dgram_recvmsg, | 588 | .recvmsg = unix_seqpacket_recvmsg, |
587 | .mmap = sock_no_mmap, | 589 | .mmap = sock_no_mmap, |
588 | .sendpage = sock_no_sendpage, | 590 | .sendpage = sock_no_sendpage, |
589 | }; | 591 | }; |
@@ -850,7 +852,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
850 | * Get the parent directory, calculate the hash for last | 852 | * Get the parent directory, calculate the hash for last |
851 | * component. | 853 | * component. |
852 | */ | 854 | */ |
853 | err = path_lookup(sunaddr->sun_path, LOOKUP_PARENT, &nd); | 855 | err = kern_path_parent(sunaddr->sun_path, &nd); |
854 | if (err) | 856 | if (err) |
855 | goto out_mknod_parent; | 857 | goto out_mknod_parent; |
856 | 858 | ||
@@ -1124,7 +1126,7 @@ restart: | |||
1124 | 1126 | ||
1125 | /* Latch our state. | 1127 | /* Latch our state. |
1126 | 1128 | ||
1127 | It is tricky place. We need to grab write lock and cannot | 1129 | It is tricky place. We need to grab our state lock and cannot |
1128 | drop lock on peer. It is dangerous because deadlock is | 1130 | drop lock on peer. It is dangerous because deadlock is |
1129 | possible. Connect to self case and simultaneous | 1131 | possible. Connect to self case and simultaneous |
1130 | attempt to connect are eliminated by checking socket | 1132 | attempt to connect are eliminated by checking socket |
@@ -1171,7 +1173,7 @@ restart: | |||
1171 | newsk->sk_type = sk->sk_type; | 1173 | newsk->sk_type = sk->sk_type; |
1172 | init_peercred(newsk); | 1174 | init_peercred(newsk); |
1173 | newu = unix_sk(newsk); | 1175 | newu = unix_sk(newsk); |
1174 | newsk->sk_wq = &newu->peer_wq; | 1176 | RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq); |
1175 | otheru = unix_sk(other); | 1177 | otheru = unix_sk(other); |
1176 | 1178 | ||
1177 | /* copy address information from listening to new sock*/ | 1179 | /* copy address information from listening to new sock*/ |
@@ -1475,6 +1477,12 @@ restart: | |||
1475 | goto out_free; | 1477 | goto out_free; |
1476 | } | 1478 | } |
1477 | 1479 | ||
1480 | if (sk_filter(other, skb) < 0) { | ||
1481 | /* Toss the packet but do not return any error to the sender */ | ||
1482 | err = len; | ||
1483 | goto out_free; | ||
1484 | } | ||
1485 | |||
1478 | unix_state_lock(other); | 1486 | unix_state_lock(other); |
1479 | err = -EPERM; | 1487 | err = -EPERM; |
1480 | if (!unix_may_send(sk, other)) | 1488 | if (!unix_may_send(sk, other)) |
@@ -1561,7 +1569,6 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1561 | struct sock_iocb *siocb = kiocb_to_siocb(kiocb); | 1569 | struct sock_iocb *siocb = kiocb_to_siocb(kiocb); |
1562 | struct sock *sk = sock->sk; | 1570 | struct sock *sk = sock->sk; |
1563 | struct sock *other = NULL; | 1571 | struct sock *other = NULL; |
1564 | struct sockaddr_un *sunaddr = msg->msg_name; | ||
1565 | int err, size; | 1572 | int err, size; |
1566 | struct sk_buff *skb; | 1573 | struct sk_buff *skb; |
1567 | int sent = 0; | 1574 | int sent = 0; |
@@ -1584,7 +1591,6 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1584 | err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP; | 1591 | err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP; |
1585 | goto out_err; | 1592 | goto out_err; |
1586 | } else { | 1593 | } else { |
1587 | sunaddr = NULL; | ||
1588 | err = -ENOTCONN; | 1594 | err = -ENOTCONN; |
1589 | other = unix_peer(sk); | 1595 | other = unix_peer(sk); |
1590 | if (!other) | 1596 | if (!other) |
@@ -1695,6 +1701,18 @@ static int unix_seqpacket_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1695 | return unix_dgram_sendmsg(kiocb, sock, msg, len); | 1701 | return unix_dgram_sendmsg(kiocb, sock, msg, len); |
1696 | } | 1702 | } |
1697 | 1703 | ||
1704 | static int unix_seqpacket_recvmsg(struct kiocb *iocb, struct socket *sock, | ||
1705 | struct msghdr *msg, size_t size, | ||
1706 | int flags) | ||
1707 | { | ||
1708 | struct sock *sk = sock->sk; | ||
1709 | |||
1710 | if (sk->sk_state != TCP_ESTABLISHED) | ||
1711 | return -ENOTCONN; | ||
1712 | |||
1713 | return unix_dgram_recvmsg(iocb, sock, msg, size, flags); | ||
1714 | } | ||
1715 | |||
1698 | static void unix_copy_addr(struct msghdr *msg, struct sock *sk) | 1716 | static void unix_copy_addr(struct msghdr *msg, struct sock *sk) |
1699 | { | 1717 | { |
1700 | struct unix_sock *u = unix_sk(sk); | 1718 | struct unix_sock *u = unix_sk(sk); |
@@ -1987,36 +2005,38 @@ static int unix_shutdown(struct socket *sock, int mode) | |||
1987 | 2005 | ||
1988 | mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN); | 2006 | mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN); |
1989 | 2007 | ||
1990 | if (mode) { | 2008 | if (!mode) |
1991 | unix_state_lock(sk); | 2009 | return 0; |
1992 | sk->sk_shutdown |= mode; | 2010 | |
1993 | other = unix_peer(sk); | 2011 | unix_state_lock(sk); |
1994 | if (other) | 2012 | sk->sk_shutdown |= mode; |
1995 | sock_hold(other); | 2013 | other = unix_peer(sk); |
1996 | unix_state_unlock(sk); | 2014 | if (other) |
1997 | sk->sk_state_change(sk); | 2015 | sock_hold(other); |
1998 | 2016 | unix_state_unlock(sk); | |
1999 | if (other && | 2017 | sk->sk_state_change(sk); |
2000 | (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) { | 2018 | |
2001 | 2019 | if (other && | |
2002 | int peer_mode = 0; | 2020 | (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) { |
2003 | 2021 | ||
2004 | if (mode&RCV_SHUTDOWN) | 2022 | int peer_mode = 0; |
2005 | peer_mode |= SEND_SHUTDOWN; | 2023 | |
2006 | if (mode&SEND_SHUTDOWN) | 2024 | if (mode&RCV_SHUTDOWN) |
2007 | peer_mode |= RCV_SHUTDOWN; | 2025 | peer_mode |= SEND_SHUTDOWN; |
2008 | unix_state_lock(other); | 2026 | if (mode&SEND_SHUTDOWN) |
2009 | other->sk_shutdown |= peer_mode; | 2027 | peer_mode |= RCV_SHUTDOWN; |
2010 | unix_state_unlock(other); | 2028 | unix_state_lock(other); |
2011 | other->sk_state_change(other); | 2029 | other->sk_shutdown |= peer_mode; |
2012 | if (peer_mode == SHUTDOWN_MASK) | 2030 | unix_state_unlock(other); |
2013 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP); | 2031 | other->sk_state_change(other); |
2014 | else if (peer_mode & RCV_SHUTDOWN) | 2032 | if (peer_mode == SHUTDOWN_MASK) |
2015 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN); | 2033 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP); |
2016 | } | 2034 | else if (peer_mode & RCV_SHUTDOWN) |
2017 | if (other) | 2035 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN); |
2018 | sock_put(other); | ||
2019 | } | 2036 | } |
2037 | if (other) | ||
2038 | sock_put(other); | ||
2039 | |||
2020 | return 0; | 2040 | return 0; |
2021 | } | 2041 | } |
2022 | 2042 | ||